[PATCH 3/3] V4L2: WL1273 FM Radio: Controls for the FM radio.

2010-04-30 Thread Matti J. Aaltonen
This file implements V4L2 controls for using the Texas Instruments
WL1273 FM Radio.

Signed-off-by: Matti J. Aaltonen 
---
 drivers/media/radio/Kconfig|   15 +
 drivers/media/radio/Makefile   |1 +
 drivers/media/radio/radio-wl1273.c | 1849 
 3 files changed, 1865 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/radio/radio-wl1273.c

diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index 83567b8..209fd37 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -452,4 +452,19 @@ config RADIO_TIMBERDALE
  found behind the Timberdale FPGA on the Russellville board.
  Enabling this driver will automatically select the DSP and tuner.
 
+config RADIO_WL1273
+   tristate "Texas Instruments WL1273 I2C FM Radio"
+depends on I2C && VIDEO_V4L2 && SND
+   select FW_LOADER
+   ---help---
+ Choose Y here if you have this FM radio chip.
+
+ In order to control your radio card, you will need to use programs
+ that are compatible with the Video For Linux 2 API.  Information on
+ this API and pointers to "v4l2" programs may be found at
+ .
+
+ To compile this driver as a module, choose M here: the
+ module will be called radio-wl1273.
+
 endif # RADIO_ADAPTERS
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile
index f615583..d297074 100644
--- a/drivers/media/radio/Makefile
+++ b/drivers/media/radio/Makefile
@@ -26,5 +26,6 @@ obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o
 obj-$(CONFIG_RADIO_SAA7706H) += saa7706h.o
 obj-$(CONFIG_RADIO_TEF6862) += tef6862.o
 obj-$(CONFIG_RADIO_TIMBERDALE) += radio-timb.o
+obj-$(CONFIG_RADIO_WL1273) += radio-wl1273.o
 
 EXTRA_CFLAGS += -Isound
diff --git a/drivers/media/radio/radio-wl1273.c 
b/drivers/media/radio/radio-wl1273.c
new file mode 100644
index 000..17b72df
--- /dev/null
+++ b/drivers/media/radio/radio-wl1273.c
@@ -0,0 +1,1849 @@
+/*
+ * Driver for the Texas Instruments WL1273 FM radio.
+ *
+ * Copyright (C) Nokia Corporation
+ * Author: Matti J. Aaltonen 
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#undef DEBUG
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DRIVER_DESC "Wl1273 FM Radio - V4L2"
+
+#define WL1273_POWER_SET_OFF   0
+#define WL1273_POWER_SET_FM(1 << 0)
+#define WL1273_POWER_SET_RDS   (1 << 1)
+#define WL1273_POWER_SET_RETENTION (1 << 4)
+
+#define WL1273_PUPD_SET_OFF0x00
+#define WL1273_PUPD_SET_ON 0x01
+#define WL1273_PUPD_SET_RETENTION  0x10
+
+#define WL1273_FREQ_MULT   (1 / 625)
+#define WL1273_INV_FREQ_MULT   (625 / 1)
+/*
+ * static unsigned char radio_region - Region
+ *
+ * The regions are 0=Japan, 1=USA-Europe. USA-Europe is the default.
+ */
+static unsigned char radio_region = 1;
+module_param(radio_region, byte, 0);
+MODULE_PARM_DESC(radio_region, "Region: 0=Japan, 1=USA-Europe*");
+
+/*
+ * static int radio_nr - The number of the radio device
+ *
+ * The default is 0.
+ */
+static int radio_nr = -1;
+module_param(radio_nr, int, 0);
+MODULE_PARM_DESC(radio_nr, "Radio Nr");
+
+struct wl1273_device {
+   struct v4l2_device v4l2dev;
+   struct video_device videodev;
+   struct device *dev;
+   struct wl1273_core *core;
+   bool rds_on;
+};
+
+static int wl1273_fm_set_tx_freq(struct wl1273_core *core, unsigned int freq)
+{
+   int r = 0;
+
+   if (freq < core->regions[core->region].bottom_frequency) {
+   dev_err(&core->i2c_dev->dev,
+   "Frequency out of range: %d < %d\n",
+   freq, core->regions[core->region].bottom_frequency);
+   return -EDOM;
+   }
+
+   if (freq > core->regions[core->region].top_frequency) {
+   dev_err(&core->i2c_dev->dev,
+   "Frequency out of range: %d > %d\n",
+   freq, core->regions[core->region].top_frequency);
+   return -EDOM;
+   }
+
+   /*
+*  The driver works better with this msleep,
+*  the documentation doesn't mention it.
+*/
+   msleep(5);
+   dev_dbg(&core->i2c_dev->dev, "%s: freq: %d kHz\n", __func__, freq);
+
+   INIT_COMPLETION(core->

[PATCH 3/3] V4L2: WL1273 FM Radio: Controls for the FM radio.

2010-04-20 Thread Matti J. Aaltonen
This file implements V4L2 controls for using the Texas Instruments
WL1273 FM Radio.

Signed-off-by: Matti J. Aaltonen 
---
 drivers/media/radio/Kconfig|   15 +
 drivers/media/radio/Makefile   |1 +
 drivers/media/radio/radio-wl1273.c |  805 
 3 files changed, 821 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/radio/radio-wl1273.c

diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index 83567b8..209fd37 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -452,4 +452,19 @@ config RADIO_TIMBERDALE
  found behind the Timberdale FPGA on the Russellville board.
  Enabling this driver will automatically select the DSP and tuner.
 
+config RADIO_WL1273
+   tristate "Texas Instruments WL1273 I2C FM Radio"
+depends on I2C && VIDEO_V4L2 && SND
+   select FW_LOADER
+   ---help---
+ Choose Y here if you have this FM radio chip.
+
+ In order to control your radio card, you will need to use programs
+ that are compatible with the Video For Linux 2 API.  Information on
+ this API and pointers to "v4l2" programs may be found at
+ .
+
+ To compile this driver as a module, choose M here: the
+ module will be called radio-wl1273.
+
 endif # RADIO_ADAPTERS
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile
index f615583..d297074 100644
--- a/drivers/media/radio/Makefile
+++ b/drivers/media/radio/Makefile
@@ -26,5 +26,6 @@ obj-$(CONFIG_RADIO_TEA5764) += radio-tea5764.o
 obj-$(CONFIG_RADIO_SAA7706H) += saa7706h.o
 obj-$(CONFIG_RADIO_TEF6862) += tef6862.o
 obj-$(CONFIG_RADIO_TIMBERDALE) += radio-timb.o
+obj-$(CONFIG_RADIO_WL1273) += radio-wl1273.o
 
 EXTRA_CFLAGS += -Isound
diff --git a/drivers/media/radio/radio-wl1273.c 
b/drivers/media/radio/radio-wl1273.c
new file mode 100644
index 000..07f6787
--- /dev/null
+++ b/drivers/media/radio/radio-wl1273.c
@@ -0,0 +1,805 @@
+/*
+ * Driver for the Texas Instruments WL1273 FM radio.
+ *
+ * Copyright (C) Nokia Corporation
+ * Author: Matti J. Aaltonen 
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#undef DEBUG
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DRIVER_DESC "Wl1273 FM Radio - V4L2"
+
+/*
+ * static int radio_nr - The number of the radio device
+ *
+ * The default is 0.
+ */
+static int radio_nr = -1;
+module_param(radio_nr, int, 0);
+MODULE_PARM_DESC(radio_nr, "Radio Nr");
+
+struct wl1273_device {
+   struct video_device *videodev;
+   struct device *dev;
+   struct wl1273_core *core;
+   bool rds_on;
+};
+
+static ssize_t wl1273_fm_fops_write(struct file *file, const char __user *buf,
+   size_t count, loff_t *ppos)
+{
+   struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+   unsigned char *s;
+   u16 val;
+   int r;
+
+   dev_dbg(radio->dev, "%s\n", __func__);
+
+   if (radio->core->mode == WL1273_MODE_RX)
+   return count;
+
+   if (mutex_lock_interruptible(&radio->core->lock))
+   return -EINTR;
+
+   /* Manual Mode */
+   if (count > 255)
+   val = 255;
+   else
+   val = count;
+
+   wl1273_fm_write_cmd(radio->core, WL1273_RDS_CONFIG_DATA_SET, val);
+
+   s = kmalloc(val + 1, GFP_KERNEL);
+   if (!s) {
+   r = -ENOMEM;
+   goto out;
+   }
+
+   if (copy_from_user(s + 1, buf, val)) {
+   kfree(s);
+   r = -EFAULT;
+   goto out;
+   }
+
+   dev_dbg(radio->dev, "Count: %d\n", val);
+   dev_dbg(radio->dev, "From user: \"%s\"\n", s);
+
+   s[0] = WL1273_RDS_DATA_SET;
+   wl1273_fm_write_data(radio->core, s, val + 1);
+
+   kfree(s);
+   r = val;
+
+out:
+   mutex_unlock(&radio->core->lock);
+
+   return r;
+}
+
+static unsigned int wl1273_fm_fops_poll(struct file *file,
+   struct poll_table_struct *pts)
+{
+   struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+   struct wl1273_core *core = radio->core;
+   unsigned int rd_index, wr_index;
+
+   /* TODO: handle the case of multiple readers */
+
+   poll_wait(file, &core->read_queue, pts);
+
+   rd_index = core->