Re: [PATCH 1/6] si4713 : Reorganized drivers/media/radio directory

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Dinesh,

On Fri, Aug 30, 2013 at 7:28 AM, Dinesh Ram <dinram@xxxxxxxxx> wrote:
> Added a new si4713 directory which will contain all si4713 related files.
> Also updated Makefile and Kconfig
>
> Signed-off-by: Dinesh Ram <dinram@xxxxxxxxx>
> ---
>  drivers/media/radio/Kconfig                        |   29 +-
>  drivers/media/radio/Makefile                       |    3 +-
>  drivers/media/radio/radio-si4713.c                 |  246 ----
>  drivers/media/radio/si4713-i2c.c                   | 1532 --------------------
>  drivers/media/radio/si4713-i2c.h                   |  238 ---
>  drivers/media/radio/si4713/Kconfig                 |   25 +
>  drivers/media/radio/si4713/Makefile                |    7 +
>  drivers/media/radio/si4713/radio-platform-si4713.c |  246 ++++
>  drivers/media/radio/si4713/si4713.c                | 1532 ++++++++++++++++++++
>  drivers/media/radio/si4713/si4713.h                |  238 +++
>  10 files changed, 2055 insertions(+), 2041 deletions(-)
>  delete mode 100644 drivers/media/radio/radio-si4713.c
>  delete mode 100644 drivers/media/radio/si4713-i2c.c
>  delete mode 100644 drivers/media/radio/si4713-i2c.h
>  create mode 100644 drivers/media/radio/si4713/Kconfig
>  create mode 100644 drivers/media/radio/si4713/Makefile
>  create mode 100644 drivers/media/radio/si4713/radio-platform-si4713.c
>  create mode 100644 drivers/media/radio/si4713/si4713.c
>  create mode 100644 drivers/media/radio/si4713/si4713.h
>


Not that this is mandatory, but it eases the review process if you add
the flag --find-renames in your git format-patch command. It will
append a summary of file renames and the patch will contain only the
difference you made inside the files while moving them.


> diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
> index 39882dd..c92d654 100644
> --- a/drivers/media/radio/Kconfig
> +++ b/drivers/media/radio/Kconfig
> @@ -15,6 +15,12 @@ if RADIO_ADAPTERS && VIDEO_V4L2
>  config RADIO_TEA575X
>         tristate
>
> +config RADIO_SI4713
> +       tristate "Silicon Labs Si4713 FM Radio with RDS Transmitter support"
> +       depends on VIDEO_V4L2
> +
> +source "drivers/media/radio/si4713/Kconfig"
> +
>  config RADIO_SI470X
>         bool "Silicon Labs Si470x FM Radio Receiver support"
>         depends on VIDEO_V4L2
> @@ -113,29 +119,6 @@ config RADIO_SHARK2
>           To compile this driver as a module, choose M here: the
>           module will be called radio-shark2.
>
> -config I2C_SI4713
> -       tristate "I2C driver for Silicon Labs Si4713 device"
> -       depends on I2C && VIDEO_V4L2
> -       ---help---
> -         Say Y here if you want support to Si4713 I2C device.
> -         This device driver supports only i2c bus.
> -
> -         To compile this driver as a module, choose M here: the
> -         module will be called si4713.
> -
> -config RADIO_SI4713
> -       tristate "Silicon Labs Si4713 FM Radio Transmitter support"
> -       depends on I2C && VIDEO_V4L2
> -       select I2C_SI4713
> -       ---help---
> -         Say Y here if you want support to Si4713 FM Radio Transmitter.
> -         This device can transmit audio through FM. It can transmit
> -         RDS and RBDS signals as well. This module is the v4l2 radio
> -         interface for the i2c driver of this device.
> -
> -         To compile this driver as a module, choose M here: the
> -         module will be called radio-si4713.
> -
>  config USB_KEENE
>         tristate "Keene FM Transmitter USB support"
>         depends on USB && VIDEO_V4L2
> diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile
> index 3b64560..eb1a3a0 100644
> --- a/drivers/media/radio/Makefile
> +++ b/drivers/media/radio/Makefile
> @@ -17,12 +17,11 @@ obj-$(CONFIG_RADIO_RTRACK) += radio-aimslab.o
>  obj-$(CONFIG_RADIO_ZOLTRIX) += radio-zoltrix.o
>  obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o
>  obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
> -obj-$(CONFIG_I2C_SI4713) += si4713-i2c.o
> -obj-$(CONFIG_RADIO_SI4713) += radio-si4713.o
>  obj-$(CONFIG_RADIO_SI476X) += radio-si476x.o
>  obj-$(CONFIG_RADIO_MIROPCM20) += radio-miropcm20.o
>  obj-$(CONFIG_USB_DSBR) += dsbr100.o
>  obj-$(CONFIG_RADIO_SI470X) += si470x/
> +obj-$(CONFIG_RADIO_SI4713) += si4713/
>  obj-$(CONFIG_USB_MR800) += radio-mr800.o
>  obj-$(CONFIG_USB_KEENE) += radio-keene.o
>  obj-$(CONFIG_USB_MA901) += radio-ma901.o
> diff --git a/drivers/media/radio/radio-si4713.c b/drivers/media/radio/radio-si4713.c
> deleted file mode 100644
> index ba4cfc9..0000000
> --- a/drivers/media/radio/radio-si4713.c
> +++ /dev/null
> @@ -1,246 +0,0 @@
> -/*
> - * drivers/media/radio/radio-si4713.c
> - *
> - * Platform Driver for Silicon Labs Si4713 FM Radio Transmitter:
> - *
> - * Copyright (c) 2008 Instituto Nokia de Tecnologia - INdT
> - * Contact: Eduardo Valentin <eduardo.valentin@xxxxxxxxx>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - *
> - * 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
> - */
> -
> -#include <linux/kernel.h>
> -#include <linux/module.h>
> -#include <linux/init.h>
> -#include <linux/platform_device.h>
> -#include <linux/i2c.h>
> -#include <linux/videodev2.h>
> -#include <linux/slab.h>
> -#include <media/v4l2-device.h>
> -#include <media/v4l2-common.h>
> -#include <media/v4l2-ioctl.h>
> -#include <media/v4l2-fh.h>
> -#include <media/v4l2-ctrls.h>
> -#include <media/v4l2-event.h>
> -#include <media/radio-si4713.h>
> -
> -/* module parameters */
> -static int radio_nr = -1;      /* radio device minor (-1 ==> auto assign) */
> -module_param(radio_nr, int, 0);
> -MODULE_PARM_DESC(radio_nr,
> -                "Minor number for radio device (-1 ==> auto assign)");
> -
> -MODULE_LICENSE("GPL v2");
> -MODULE_AUTHOR("Eduardo Valentin <eduardo.valentin@xxxxxxxxx>");
> -MODULE_DESCRIPTION("Platform driver for Si4713 FM Radio Transmitter");
> -MODULE_VERSION("0.0.1");
> -MODULE_ALIAS("platform:radio-si4713");
> -
> -/* Driver state struct */
> -struct radio_si4713_device {
> -       struct v4l2_device              v4l2_dev;
> -       struct video_device             radio_dev;
> -       struct mutex lock;
> -};
> -
> -/* radio_si4713_fops - file operations interface */
> -static const struct v4l2_file_operations radio_si4713_fops = {
> -       .owner          = THIS_MODULE,
> -       .open = v4l2_fh_open,
> -       .release = v4l2_fh_release,
> -       .poll = v4l2_ctrl_poll,
> -       /* Note: locking is done at the subdev level in the i2c driver. */
> -       .unlocked_ioctl = video_ioctl2,
> -};
> -
> -/* Video4Linux Interface */
> -
> -/* radio_si4713_querycap - query device capabilities */
> -static int radio_si4713_querycap(struct file *file, void *priv,
> -                                       struct v4l2_capability *capability)
> -{
> -       strlcpy(capability->driver, "radio-si4713", sizeof(capability->driver));
> -       strlcpy(capability->card, "Silicon Labs Si4713 Modulator",
> -               sizeof(capability->card));
> -       strlcpy(capability->bus_info, "platform:radio-si4713",
> -               sizeof(capability->bus_info));
> -       capability->device_caps = V4L2_CAP_MODULATOR | V4L2_CAP_RDS_OUTPUT;
> -       capability->capabilities = capability->device_caps | V4L2_CAP_DEVICE_CAPS;
> -
> -       return 0;
> -}
> -
> -/*
> - * v4l2 ioctl call backs.
> - * we are just a wrapper for v4l2_sub_devs.
> - */
> -static inline struct v4l2_device *get_v4l2_dev(struct file *file)
> -{
> -       return &((struct radio_si4713_device *)video_drvdata(file))->v4l2_dev;
> -}
> -
> -static int radio_si4713_g_modulator(struct file *file, void *p,
> -                                   struct v4l2_modulator *vm)
> -{
> -       return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
> -                                         g_modulator, vm);
> -}
> -
> -static int radio_si4713_s_modulator(struct file *file, void *p,
> -                                   const struct v4l2_modulator *vm)
> -{
> -       return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
> -                                         s_modulator, vm);
> -}
> -
> -static int radio_si4713_g_frequency(struct file *file, void *p,
> -                                   struct v4l2_frequency *vf)
> -{
> -       return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
> -                                         g_frequency, vf);
> -}
> -
> -static int radio_si4713_s_frequency(struct file *file, void *p,
> -                                   const struct v4l2_frequency *vf)
> -{
> -       return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
> -                                         s_frequency, vf);
> -}
> -
> -static long radio_si4713_default(struct file *file, void *p,
> -                                bool valid_prio, unsigned int cmd, void *arg)
> -{
> -       return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
> -                                         ioctl, cmd, arg);
> -}
> -
> -static struct v4l2_ioctl_ops radio_si4713_ioctl_ops = {
> -       .vidioc_querycap        = radio_si4713_querycap,
> -       .vidioc_g_modulator     = radio_si4713_g_modulator,
> -       .vidioc_s_modulator     = radio_si4713_s_modulator,
> -       .vidioc_g_frequency     = radio_si4713_g_frequency,
> -       .vidioc_s_frequency     = radio_si4713_s_frequency,
> -       .vidioc_log_status      = v4l2_ctrl_log_status,
> -       .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
> -       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
> -       .vidioc_default         = radio_si4713_default,
> -};
> -
> -/* radio_si4713_vdev_template - video device interface */
> -static struct video_device radio_si4713_vdev_template = {
> -       .fops                   = &radio_si4713_fops,
> -       .name                   = "radio-si4713",
> -       .release                = video_device_release_empty,
> -       .ioctl_ops              = &radio_si4713_ioctl_ops,
> -       .vfl_dir                = VFL_DIR_TX,
> -};
> -
> -/* Platform driver interface */
> -/* radio_si4713_pdriver_probe - probe for the device */
> -static int radio_si4713_pdriver_probe(struct platform_device *pdev)
> -{
> -       struct radio_si4713_platform_data *pdata = pdev->dev.platform_data;
> -       struct radio_si4713_device *rsdev;
> -       struct i2c_adapter *adapter;
> -       struct v4l2_subdev *sd;
> -       int rval = 0;
> -
> -       if (!pdata) {
> -               dev_err(&pdev->dev, "Cannot proceed without platform data.\n");
> -               rval = -EINVAL;
> -               goto exit;
> -       }
> -
> -       rsdev = devm_kzalloc(&pdev->dev, sizeof(*rsdev), GFP_KERNEL);
> -       if (!rsdev) {
> -               dev_err(&pdev->dev, "Failed to alloc video device.\n");
> -               rval = -ENOMEM;
> -               goto exit;
> -       }
> -       mutex_init(&rsdev->lock);
> -
> -       rval = v4l2_device_register(&pdev->dev, &rsdev->v4l2_dev);
> -       if (rval) {
> -               dev_err(&pdev->dev, "Failed to register v4l2 device.\n");
> -               goto exit;
> -       }
> -
> -       adapter = i2c_get_adapter(pdata->i2c_bus);
> -       if (!adapter) {
> -               dev_err(&pdev->dev, "Cannot get i2c adapter %d\n",
> -                       pdata->i2c_bus);
> -               rval = -ENODEV;
> -               goto unregister_v4l2_dev;
> -       }
> -
> -       sd = v4l2_i2c_new_subdev_board(&rsdev->v4l2_dev, adapter,
> -                                      pdata->subdev_board_info, NULL);
> -       if (!sd) {
> -               dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n");
> -               rval = -ENODEV;
> -               goto put_adapter;
> -       }
> -
> -       rsdev->radio_dev = radio_si4713_vdev_template;
> -       rsdev->radio_dev.v4l2_dev = &rsdev->v4l2_dev;
> -       rsdev->radio_dev.ctrl_handler = sd->ctrl_handler;
> -       set_bit(V4L2_FL_USE_FH_PRIO, &rsdev->radio_dev.flags);
> -       /* Serialize all access to the si4713 */
> -       rsdev->radio_dev.lock = &rsdev->lock;
> -       video_set_drvdata(&rsdev->radio_dev, rsdev);
> -       if (video_register_device(&rsdev->radio_dev, VFL_TYPE_RADIO, radio_nr)) {
> -               dev_err(&pdev->dev, "Could not register video device.\n");
> -               rval = -EIO;
> -               goto put_adapter;
> -       }
> -       dev_info(&pdev->dev, "New device successfully probed\n");
> -
> -       goto exit;
> -
> -put_adapter:
> -       i2c_put_adapter(adapter);
> -unregister_v4l2_dev:
> -       v4l2_device_unregister(&rsdev->v4l2_dev);
> -exit:
> -       return rval;
> -}
> -
> -/* radio_si4713_pdriver_remove - remove the device */
> -static int radio_si4713_pdriver_remove(struct platform_device *pdev)
> -{
> -       struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
> -       struct v4l2_subdev *sd = list_entry(v4l2_dev->subdevs.next,
> -                                           struct v4l2_subdev, list);
> -       struct i2c_client *client = v4l2_get_subdevdata(sd);
> -       struct radio_si4713_device *rsdev;
> -
> -       rsdev = container_of(v4l2_dev, struct radio_si4713_device, v4l2_dev);
> -       video_unregister_device(&rsdev->radio_dev);
> -       i2c_put_adapter(client->adapter);
> -       v4l2_device_unregister(&rsdev->v4l2_dev);
> -
> -       return 0;
> -}
> -
> -static struct platform_driver radio_si4713_pdriver = {
> -       .driver         = {
> -               .name   = "radio-si4713",
> -               .owner  = THIS_MODULE,
> -       },
> -       .probe          = radio_si4713_pdriver_probe,
> -       .remove         = radio_si4713_pdriver_remove,
> -};
> -
> -module_platform_driver(radio_si4713_pdriver);
> diff --git a/drivers/media/radio/si4713-i2c.c b/drivers/media/radio/si4713-i2c.c
> deleted file mode 100644
> index fe16088..0000000
> --- a/drivers/media/radio/si4713-i2c.c
> +++ /dev/null
> @@ -1,1532 +0,0 @@
> -/*
> - * drivers/media/radio/si4713-i2c.c
> - *
> - * Silicon Labs Si4713 FM Radio Transmitter I2C commands.
> - *
> - * Copyright (c) 2009 Nokia Corporation
> - * Contact: Eduardo Valentin <eduardo.valentin@xxxxxxxxx>
> - *
> - * This program is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; either version 2 of the License, or
> - * (at your option) any later version.
> - *
> - * 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
> - */
> -
> -#include <linux/completion.h>
> -#include <linux/delay.h>
> -#include <linux/interrupt.h>
> -#include <linux/i2c.h>
> -#include <linux/slab.h>
> -#include <linux/gpio.h>
> -#include <linux/regulator/consumer.h>
> -#include <linux/module.h>
> -#include <media/v4l2-device.h>
> -#include <media/v4l2-ioctl.h>
> -#include <media/v4l2-common.h>
> -
> -#include "si4713-i2c.h"
> -
> -/* module parameters */
> -static int debug;
> -module_param(debug, int, S_IRUGO | S_IWUSR);
> -MODULE_PARM_DESC(debug, "Debug level (0 - 2)");
> -
> -MODULE_LICENSE("GPL");
> -MODULE_AUTHOR("Eduardo Valentin <eduardo.valentin@xxxxxxxxx>");
> -MODULE_DESCRIPTION("I2C driver for Si4713 FM Radio Transmitter");
> -MODULE_VERSION("0.0.1");
> -
> -static const char *si4713_supply_names[SI4713_NUM_SUPPLIES] = {
> -       "vio",
> -       "vdd",
> -};
> -
> -#define DEFAULT_RDS_PI                 0x00
> -#define DEFAULT_RDS_PTY                        0x00
> -#define DEFAULT_RDS_DEVIATION          0x00C8
> -#define DEFAULT_RDS_PS_REPEAT_COUNT    0x0003
> -#define DEFAULT_LIMITER_RTIME          0x1392
> -#define DEFAULT_LIMITER_DEV            0x102CA
> -#define DEFAULT_PILOT_FREQUENCY        0x4A38
> -#define DEFAULT_PILOT_DEVIATION                0x1A5E
> -#define DEFAULT_ACOMP_ATIME            0x0000
> -#define DEFAULT_ACOMP_RTIME            0xF4240L
> -#define DEFAULT_ACOMP_GAIN             0x0F
> -#define DEFAULT_ACOMP_THRESHOLD        (-0x28)
> -#define DEFAULT_MUTE                   0x01
> -#define DEFAULT_POWER_LEVEL            88
> -#define DEFAULT_FREQUENCY              8800
> -#define DEFAULT_PREEMPHASIS            FMPE_EU
> -#define DEFAULT_TUNE_RNL               0xFF
> -
> -#define to_si4713_device(sd)   container_of(sd, struct si4713_device, sd)
> -
> -/* frequency domain transformation (using times 10 to avoid floats) */
> -#define FREQDEV_UNIT   100000
> -#define FREQV4L2_MULTI 625
> -#define si4713_to_v4l2(f)      ((f * FREQDEV_UNIT) / FREQV4L2_MULTI)
> -#define v4l2_to_si4713(f)      ((f * FREQV4L2_MULTI) / FREQDEV_UNIT)
> -#define FREQ_RANGE_LOW                 7600
> -#define FREQ_RANGE_HIGH                        10800
> -
> -#define MAX_ARGS 7
> -
> -#define RDS_BLOCK                      8
> -#define RDS_BLOCK_CLEAR                        0x03
> -#define RDS_BLOCK_LOAD                 0x04
> -#define RDS_RADIOTEXT_2A               0x20
> -#define RDS_RADIOTEXT_BLK_SIZE         4
> -#define RDS_RADIOTEXT_INDEX_MAX                0x0F
> -#define RDS_CARRIAGE_RETURN            0x0D
> -
> -#define rds_ps_nblocks(len)    ((len / RDS_BLOCK) + (len % RDS_BLOCK ? 1 : 0))
> -
> -#define get_status_bit(p, b, m)        (((p) & (m)) >> (b))
> -#define set_bits(p, v, b, m)   (((p) & ~(m)) | ((v) << (b)))
> -
> -#define ATTACK_TIME_UNIT       500
> -
> -#define POWER_OFF                      0x00
> -#define POWER_ON                       0x01
> -
> -#define msb(x)                  ((u8)((u16) x >> 8))
> -#define lsb(x)                  ((u8)((u16) x &  0x00FF))
> -#define compose_u16(msb, lsb)  (((u16)msb << 8) | lsb)
> -#define check_command_failed(status)   (!(status & SI4713_CTS) || \
> -                                       (status & SI4713_ERR))
> -/* mute definition */
> -#define set_mute(p)    ((p & 1) | ((p & 1) << 1));
> -
> -#ifdef DEBUG
> -#define DBG_BUFFER(device, message, buffer, size)                      \
> -       {                                                               \
> -               int i;                                                  \
> -               char str[(size)*5];                                     \
> -               for (i = 0; i < size; i++)                              \
> -                       sprintf(str + i * 5, " 0x%02x", buffer[i]);     \
> -               v4l2_dbg(2, debug, device, "%s:%s\n", message, str);    \
> -       }
> -#else
> -#define DBG_BUFFER(device, message, buffer, size)
> -#endif
> -
> -/*
> - * Values for limiter release time (sorted by second column)
> - *     device  release
> - *     value   time (us)
> - */
> -static long limiter_times[] = {
> -       2000,   250,
> -       1000,   500,
> -       510,    1000,
> -       255,    2000,
> -       170,    3000,
> -       127,    4020,
> -       102,    5010,
> -       85,     6020,
> -       73,     7010,
> -       64,     7990,
> -       57,     8970,
> -       51,     10030,
> -       25,     20470,
> -       17,     30110,
> -       13,     39380,
> -       10,     51190,
> -       8,      63690,
> -       7,      73140,
> -       6,      85330,
> -       5,      102390,
> -};
> -
> -/*
> - * Values for audio compression release time (sorted by second column)
> - *     device  release
> - *     value   time (us)
> - */
> -static unsigned long acomp_rtimes[] = {
> -       0,      100000,
> -       1,      200000,
> -       2,      350000,
> -       3,      525000,
> -       4,      1000000,
> -};
> -
> -/*
> - * Values for preemphasis (sorted by second column)
> - *     device  preemphasis
> - *     value   value (v4l2)
> - */
> -static unsigned long preemphasis_values[] = {
> -       FMPE_DISABLED,  V4L2_PREEMPHASIS_DISABLED,
> -       FMPE_EU,        V4L2_PREEMPHASIS_50_uS,
> -       FMPE_USA,       V4L2_PREEMPHASIS_75_uS,
> -};
> -
> -static int usecs_to_dev(unsigned long usecs, unsigned long const array[],
> -                       int size)
> -{
> -       int i;
> -       int rval = -EINVAL;
> -
> -       for (i = 0; i < size / 2; i++)
> -               if (array[(i * 2) + 1] >= usecs) {
> -                       rval = array[i * 2];
> -                       break;
> -               }
> -
> -       return rval;
> -}
> -
> -/* si4713_handler: IRQ handler, just complete work */
> -static irqreturn_t si4713_handler(int irq, void *dev)
> -{
> -       struct si4713_device *sdev = dev;
> -
> -       v4l2_dbg(2, debug, &sdev->sd,
> -                       "%s: sending signal to completion work.\n", __func__);
> -       complete(&sdev->work);
> -
> -       return IRQ_HANDLED;
> -}
> -
> -/*
> - * si4713_send_command - sends a command to si4713 and waits its response
> - * @sdev: si4713_device structure for the device we are communicating
> - * @command: command id
> - * @args: command arguments we are sending (up to 7)
> - * @argn: actual size of @args
> - * @response: buffer to place the expected response from the device (up to 15)
> - * @respn: actual size of @response
> - * @usecs: amount of time to wait before reading the response (in usecs)
> - */
> -static int si4713_send_command(struct si4713_device *sdev, const u8 command,
> -                               const u8 args[], const int argn,
> -                               u8 response[], const int respn, const int usecs)
> -{
> -       struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
> -       u8 data1[MAX_ARGS + 1];
> -       int err;
> -
> -       if (!client->adapter)
> -               return -ENODEV;
> -
> -       /* First send the command and its arguments */
> -       data1[0] = command;
> -       memcpy(data1 + 1, args, argn);
> -       DBG_BUFFER(&sdev->sd, "Parameters", data1, argn + 1);
> -
> -       err = i2c_master_send(client, data1, argn + 1);
> -       if (err != argn + 1) {
> -               v4l2_err(&sdev->sd, "Error while sending command 0x%02x\n",
> -                       command);
> -               return (err > 0) ? -EIO : err;
> -       }
> -
> -       /* Wait response from interrupt */
> -       if (!wait_for_completion_timeout(&sdev->work,
> -                               usecs_to_jiffies(usecs) + 1))
> -               v4l2_warn(&sdev->sd,
> -                               "(%s) Device took too much time to answer.\n",
> -                               __func__);
> -
> -       /* Then get the response */
> -       err = i2c_master_recv(client, response, respn);
> -       if (err != respn) {
> -               v4l2_err(&sdev->sd,
> -                       "Error while reading response for command 0x%02x\n",
> -                       command);
> -               return (err > 0) ? -EIO : err;
> -       }
> -
> -       DBG_BUFFER(&sdev->sd, "Response", response, respn);
> -       if (check_command_failed(response[0]))
> -               return -EBUSY;
> -
> -       return 0;
> -}
> -
> -/*
> - * si4713_read_property - reads a si4713 property
> - * @sdev: si4713_device structure for the device we are communicating
> - * @prop: property identification number
> - * @pv: property value to be returned on success
> - */
> -static int si4713_read_property(struct si4713_device *sdev, u16 prop, u32 *pv)
> -{
> -       int err;
> -       u8 val[SI4713_GET_PROP_NRESP];
> -       /*
> -        *      .First byte = 0
> -        *      .Second byte = property's MSB
> -        *      .Third byte = property's LSB
> -        */
> -       const u8 args[SI4713_GET_PROP_NARGS] = {
> -               0x00,
> -               msb(prop),
> -               lsb(prop),
> -       };
> -
> -       err = si4713_send_command(sdev, SI4713_CMD_GET_PROPERTY,
> -                                 args, ARRAY_SIZE(args), val,
> -                                 ARRAY_SIZE(val), DEFAULT_TIMEOUT);
> -
> -       if (err < 0)
> -               return err;
> -
> -       *pv = compose_u16(val[2], val[3]);
> -
> -       v4l2_dbg(1, debug, &sdev->sd,
> -                       "%s: property=0x%02x value=0x%02x status=0x%02x\n",
> -                       __func__, prop, *pv, val[0]);
> -
> -       return err;
> -}
> -
> -/*
> - * si4713_write_property - modifies a si4713 property
> - * @sdev: si4713_device structure for the device we are communicating
> - * @prop: property identification number
> - * @val: new value for that property
> - */
> -static int si4713_write_property(struct si4713_device *sdev, u16 prop, u16 val)
> -{
> -       int rval;
> -       u8 resp[SI4713_SET_PROP_NRESP];
> -       /*
> -        *      .First byte = 0
> -        *      .Second byte = property's MSB
> -        *      .Third byte = property's LSB
> -        *      .Fourth byte = value's MSB
> -        *      .Fifth byte = value's LSB
> -        */
> -       const u8 args[SI4713_SET_PROP_NARGS] = {
> -               0x00,
> -               msb(prop),
> -               lsb(prop),
> -               msb(val),
> -               lsb(val),
> -       };
> -
> -       rval = si4713_send_command(sdev, SI4713_CMD_SET_PROPERTY,
> -                                       args, ARRAY_SIZE(args),
> -                                       resp, ARRAY_SIZE(resp),
> -                                       DEFAULT_TIMEOUT);
> -
> -       if (rval < 0)
> -               return rval;
> -
> -       v4l2_dbg(1, debug, &sdev->sd,
> -                       "%s: property=0x%02x value=0x%02x status=0x%02x\n",
> -                       __func__, prop, val, resp[0]);
> -
> -       /*
> -        * As there is no command response for SET_PROPERTY,
> -        * wait Tcomp time to finish before proceed, in order
> -        * to have property properly set.
> -        */
> -       msleep(TIMEOUT_SET_PROPERTY);
> -
> -       return rval;
> -}
> -
> -/*
> - * si4713_powerup - Powers the device up
> - * @sdev: si4713_device structure for the device we are communicating
> - */
> -static int si4713_powerup(struct si4713_device *sdev)
> -{
> -       int err;
> -       u8 resp[SI4713_PWUP_NRESP];
> -       /*
> -        *      .First byte = Enabled interrupts and boot function
> -        *      .Second byte = Input operation mode
> -        */
> -       const u8 args[SI4713_PWUP_NARGS] = {
> -               SI4713_PWUP_CTSIEN | SI4713_PWUP_GPO2OEN | SI4713_PWUP_FUNC_TX,
> -               SI4713_PWUP_OPMOD_ANALOG,
> -       };
> -
> -       if (sdev->power_state)
> -               return 0;
> -
> -       err = regulator_bulk_enable(ARRAY_SIZE(sdev->supplies),
> -                                   sdev->supplies);
> -       if (err) {
> -               v4l2_err(&sdev->sd, "Failed to enable supplies: %d\n", err);
> -               return err;
> -       }
> -       if (gpio_is_valid(sdev->gpio_reset)) {
> -               udelay(50);
> -               gpio_set_value(sdev->gpio_reset, 1);
> -       }
> -
> -       err = si4713_send_command(sdev, SI4713_CMD_POWER_UP,
> -                                       args, ARRAY_SIZE(args),
> -                                       resp, ARRAY_SIZE(resp),
> -                                       TIMEOUT_POWER_UP);
> -
> -       if (!err) {
> -               v4l2_dbg(1, debug, &sdev->sd, "Powerup response: 0x%02x\n",
> -                               resp[0]);
> -               v4l2_dbg(1, debug, &sdev->sd, "Device in power up mode\n");
> -               sdev->power_state = POWER_ON;
> -
> -               err = si4713_write_property(sdev, SI4713_GPO_IEN,
> -                                               SI4713_STC_INT | SI4713_CTS);
> -       } else {
> -               if (gpio_is_valid(sdev->gpio_reset))
> -                       gpio_set_value(sdev->gpio_reset, 0);
> -               err = regulator_bulk_disable(ARRAY_SIZE(sdev->supplies),
> -                                            sdev->supplies);
> -               if (err)
> -                       v4l2_err(&sdev->sd,
> -                                "Failed to disable supplies: %d\n", err);
> -       }
> -
> -       return err;
> -}
> -
> -/*
> - * si4713_powerdown - Powers the device down
> - * @sdev: si4713_device structure for the device we are communicating
> - */
> -static int si4713_powerdown(struct si4713_device *sdev)
> -{
> -       int err;
> -       u8 resp[SI4713_PWDN_NRESP];
> -
> -       if (!sdev->power_state)
> -               return 0;
> -
> -       err = si4713_send_command(sdev, SI4713_CMD_POWER_DOWN,
> -                                       NULL, 0,
> -                                       resp, ARRAY_SIZE(resp),
> -                                       DEFAULT_TIMEOUT);
> -
> -       if (!err) {
> -               v4l2_dbg(1, debug, &sdev->sd, "Power down response: 0x%02x\n",
> -                               resp[0]);
> -               v4l2_dbg(1, debug, &sdev->sd, "Device in reset mode\n");
> -               if (gpio_is_valid(sdev->gpio_reset))
> -                       gpio_set_value(sdev->gpio_reset, 0);
> -               err = regulator_bulk_disable(ARRAY_SIZE(sdev->supplies),
> -                                            sdev->supplies);
> -               if (err)
> -                       v4l2_err(&sdev->sd,
> -                                "Failed to disable supplies: %d\n", err);
> -               sdev->power_state = POWER_OFF;
> -       }
> -
> -       return err;
> -}
> -
> -/*
> - * si4713_checkrev - Checks if we are treating a device with the correct rev.
> - * @sdev: si4713_device structure for the device we are communicating
> - */
> -static int si4713_checkrev(struct si4713_device *sdev)
> -{
> -       struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
> -       int rval;
> -       u8 resp[SI4713_GETREV_NRESP];
> -
> -       rval = si4713_send_command(sdev, SI4713_CMD_GET_REV,
> -                                       NULL, 0,
> -                                       resp, ARRAY_SIZE(resp),
> -                                       DEFAULT_TIMEOUT);
> -
> -       if (rval < 0)
> -               return rval;
> -
> -       if (resp[1] == SI4713_PRODUCT_NUMBER) {
> -               v4l2_info(&sdev->sd, "chip found @ 0x%02x (%s)\n",
> -                               client->addr << 1, client->adapter->name);
> -       } else {
> -               v4l2_err(&sdev->sd, "Invalid product number\n");
> -               rval = -EINVAL;
> -       }
> -       return rval;
> -}
> -
> -/*
> - * si4713_wait_stc - Waits STC interrupt and clears status bits. Useful
> - *                  for TX_TUNE_POWER, TX_TUNE_FREQ and TX_TUNE_MEAS
> - * @sdev: si4713_device structure for the device we are communicating
> - * @usecs: timeout to wait for STC interrupt signal
> - */
> -static int si4713_wait_stc(struct si4713_device *sdev, const int usecs)
> -{
> -       int err;
> -       u8 resp[SI4713_GET_STATUS_NRESP];
> -
> -       /* Wait response from STC interrupt */
> -       if (!wait_for_completion_timeout(&sdev->work,
> -                       usecs_to_jiffies(usecs) + 1))
> -               v4l2_warn(&sdev->sd,
> -                       "%s: device took too much time to answer (%d usec).\n",
> -                               __func__, usecs);
> -
> -       /* Clear status bits */
> -       err = si4713_send_command(sdev, SI4713_CMD_GET_INT_STATUS,
> -                                       NULL, 0,
> -                                       resp, ARRAY_SIZE(resp),
> -                                       DEFAULT_TIMEOUT);
> -
> -       if (err < 0)
> -               goto exit;
> -
> -       v4l2_dbg(1, debug, &sdev->sd,
> -                       "%s: status bits: 0x%02x\n", __func__, resp[0]);
> -
> -       if (!(resp[0] & SI4713_STC_INT))
> -               err = -EIO;
> -
> -exit:
> -       return err;
> -}
> -
> -/*
> - * si4713_tx_tune_freq - Sets the state of the RF carrier and sets the tuning
> - *                     frequency between 76 and 108 MHz in 10 kHz units and
> - *                     steps of 50 kHz.
> - * @sdev: si4713_device structure for the device we are communicating
> - * @frequency: desired frequency (76 - 108 MHz, unit 10 KHz, step 50 kHz)
> - */
> -static int si4713_tx_tune_freq(struct si4713_device *sdev, u16 frequency)
> -{
> -       int err;
> -       u8 val[SI4713_TXFREQ_NRESP];
> -       /*
> -        *      .First byte = 0
> -        *      .Second byte = frequency's MSB
> -        *      .Third byte = frequency's LSB
> -        */
> -       const u8 args[SI4713_TXFREQ_NARGS] = {
> -               0x00,
> -               msb(frequency),
> -               lsb(frequency),
> -       };
> -
> -       err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_FREQ,
> -                                 args, ARRAY_SIZE(args), val,
> -                                 ARRAY_SIZE(val), DEFAULT_TIMEOUT);
> -
> -       if (err < 0)
> -               return err;
> -
> -       v4l2_dbg(1, debug, &sdev->sd,
> -                       "%s: frequency=0x%02x status=0x%02x\n", __func__,
> -                       frequency, val[0]);
> -
> -       err = si4713_wait_stc(sdev, TIMEOUT_TX_TUNE);
> -       if (err < 0)
> -               return err;
> -
> -       return compose_u16(args[1], args[2]);
> -}
> -
> -/*
> - * si4713_tx_tune_power - Sets the RF voltage level between 88 and 115 dBuV in
> - *                     1 dB units. A value of 0x00 indicates off. The command
> - *                     also sets the antenna tuning capacitance. A value of 0
> - *                     indicates autotuning, and a value of 1 - 191 indicates
> - *                     a manual override, which results in a tuning
> - *                     capacitance of 0.25 pF x @antcap.
> - * @sdev: si4713_device structure for the device we are communicating
> - * @power: tuning power (88 - 115 dBuV, unit/step 1 dB)
> - * @antcap: value of antenna tuning capacitor (0 - 191)
> - */
> -static int si4713_tx_tune_power(struct si4713_device *sdev, u8 power,
> -                               u8 antcap)
> -{
> -       int err;
> -       u8 val[SI4713_TXPWR_NRESP];
> -       /*
> -        *      .First byte = 0
> -        *      .Second byte = 0
> -        *      .Third byte = power
> -        *      .Fourth byte = antcap
> -        */
> -       const u8 args[SI4713_TXPWR_NARGS] = {
> -               0x00,
> -               0x00,
> -               power,
> -               antcap,
> -       };
> -
> -       if (((power > 0) && (power < SI4713_MIN_POWER)) ||
> -               power > SI4713_MAX_POWER || antcap > SI4713_MAX_ANTCAP)
> -               return -EDOM;
> -
> -       err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_POWER,
> -                                 args, ARRAY_SIZE(args), val,
> -                                 ARRAY_SIZE(val), DEFAULT_TIMEOUT);
> -
> -       if (err < 0)
> -               return err;
> -
> -       v4l2_dbg(1, debug, &sdev->sd,
> -                       "%s: power=0x%02x antcap=0x%02x status=0x%02x\n",
> -                       __func__, power, antcap, val[0]);
> -
> -       return si4713_wait_stc(sdev, TIMEOUT_TX_TUNE_POWER);
> -}
> -
> -/*
> - * si4713_tx_tune_measure - Enters receive mode and measures the received noise
> - *                     level in units of dBuV on the selected frequency.
> - *                     The Frequency must be between 76 and 108 MHz in 10 kHz
> - *                     units and steps of 50 kHz. The command also sets the
> - *                     antenna tuning capacitance. A value of 0 means
> - *                     autotuning, and a value of 1 to 191 indicates manual
> - *                     override.
> - * @sdev: si4713_device structure for the device we are communicating
> - * @frequency: desired frequency (76 - 108 MHz, unit 10 KHz, step 50 kHz)
> - * @antcap: value of antenna tuning capacitor (0 - 191)
> - */
> -static int si4713_tx_tune_measure(struct si4713_device *sdev, u16 frequency,
> -                                       u8 antcap)
> -{
> -       int err;
> -       u8 val[SI4713_TXMEA_NRESP];
> -       /*
> -        *      .First byte = 0
> -        *      .Second byte = frequency's MSB
> -        *      .Third byte = frequency's LSB
> -        *      .Fourth byte = antcap
> -        */
> -       const u8 args[SI4713_TXMEA_NARGS] = {
> -               0x00,
> -               msb(frequency),
> -               lsb(frequency),
> -               antcap,
> -       };
> -
> -       sdev->tune_rnl = DEFAULT_TUNE_RNL;
> -
> -       if (antcap > SI4713_MAX_ANTCAP)
> -               return -EDOM;
> -
> -       err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_MEASURE,
> -                                 args, ARRAY_SIZE(args), val,
> -                                 ARRAY_SIZE(val), DEFAULT_TIMEOUT);
> -
> -       if (err < 0)
> -               return err;
> -
> -       v4l2_dbg(1, debug, &sdev->sd,
> -                       "%s: frequency=0x%02x antcap=0x%02x status=0x%02x\n",
> -                       __func__, frequency, antcap, val[0]);
> -
> -       return si4713_wait_stc(sdev, TIMEOUT_TX_TUNE);
> -}
> -
> -/*
> - * si4713_tx_tune_status- Returns the status of the tx_tune_freq, tx_tune_mea or
> - *                     tx_tune_power commands. This command return the current
> - *                     frequency, output voltage in dBuV, the antenna tunning
> - *                     capacitance value and the received noise level. The
> - *                     command also clears the stcint interrupt bit when the
> - *                     first bit of its arguments is high.
> - * @sdev: si4713_device structure for the device we are communicating
> - * @intack: 0x01 to clear the seek/tune complete interrupt status indicator.
> - * @frequency: returned frequency
> - * @power: returned power
> - * @antcap: returned antenna capacitance
> - * @noise: returned noise level
> - */
> -static int si4713_tx_tune_status(struct si4713_device *sdev, u8 intack,
> -                                       u16 *frequency, u8 *power,
> -                                       u8 *antcap, u8 *noise)
> -{
> -       int err;
> -       u8 val[SI4713_TXSTATUS_NRESP];
> -       /*
> -        *      .First byte = intack bit
> -        */
> -       const u8 args[SI4713_TXSTATUS_NARGS] = {
> -               intack & SI4713_INTACK_MASK,
> -       };
> -
> -       err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_STATUS,
> -                                 args, ARRAY_SIZE(args), val,
> -                                 ARRAY_SIZE(val), DEFAULT_TIMEOUT);
> -
> -       if (!err) {
> -               v4l2_dbg(1, debug, &sdev->sd,
> -                       "%s: status=0x%02x\n", __func__, val[0]);
> -               *frequency = compose_u16(val[2], val[3]);
> -               sdev->frequency = *frequency;
> -               *power = val[5];
> -               *antcap = val[6];
> -               *noise = val[7];
> -               v4l2_dbg(1, debug, &sdev->sd, "%s: response: %d x 10 kHz "
> -                               "(power %d, antcap %d, rnl %d)\n", __func__,
> -                               *frequency, *power, *antcap, *noise);
> -       }
> -
> -       return err;
> -}
> -
> -/*
> - * si4713_tx_rds_buff - Loads the RDS group buffer FIFO or circular buffer.
> - * @sdev: si4713_device structure for the device we are communicating
> - * @mode: the buffer operation mode.
> - * @rdsb: RDS Block B
> - * @rdsc: RDS Block C
> - * @rdsd: RDS Block D
> - * @cbleft: returns the number of available circular buffer blocks minus the
> - *          number of used circular buffer blocks.
> - */
> -static int si4713_tx_rds_buff(struct si4713_device *sdev, u8 mode, u16 rdsb,
> -                               u16 rdsc, u16 rdsd, s8 *cbleft)
> -{
> -       int err;
> -       u8 val[SI4713_RDSBUFF_NRESP];
> -
> -       const u8 args[SI4713_RDSBUFF_NARGS] = {
> -               mode & SI4713_RDSBUFF_MODE_MASK,
> -               msb(rdsb),
> -               lsb(rdsb),
> -               msb(rdsc),
> -               lsb(rdsc),
> -               msb(rdsd),
> -               lsb(rdsd),
> -       };
> -
> -       err = si4713_send_command(sdev, SI4713_CMD_TX_RDS_BUFF,
> -                                 args, ARRAY_SIZE(args), val,
> -                                 ARRAY_SIZE(val), DEFAULT_TIMEOUT);
> -
> -       if (!err) {
> -               v4l2_dbg(1, debug, &sdev->sd,
> -                       "%s: status=0x%02x\n", __func__, val[0]);
> -               *cbleft = (s8)val[2] - val[3];
> -               v4l2_dbg(1, debug, &sdev->sd, "%s: response: interrupts"
> -                               " 0x%02x cb avail: %d cb used %d fifo avail"
> -                               " %d fifo used %d\n", __func__, val[1],
> -                               val[2], val[3], val[4], val[5]);
> -       }
> -
> -       return err;
> -}
> -
> -/*
> - * si4713_tx_rds_ps - Loads the program service buffer.
> - * @sdev: si4713_device structure for the device we are communicating
> - * @psid: program service id to be loaded.
> - * @pschar: assumed 4 size char array to be loaded into the program service
> - */
> -static int si4713_tx_rds_ps(struct si4713_device *sdev, u8 psid,
> -                               unsigned char *pschar)
> -{
> -       int err;
> -       u8 val[SI4713_RDSPS_NRESP];
> -
> -       const u8 args[SI4713_RDSPS_NARGS] = {
> -               psid & SI4713_RDSPS_PSID_MASK,
> -               pschar[0],
> -               pschar[1],
> -               pschar[2],
> -               pschar[3],
> -       };
> -
> -       err = si4713_send_command(sdev, SI4713_CMD_TX_RDS_PS,
> -                                 args, ARRAY_SIZE(args), val,
> -                                 ARRAY_SIZE(val), DEFAULT_TIMEOUT);
> -
> -       if (err < 0)
> -               return err;
> -
> -       v4l2_dbg(1, debug, &sdev->sd, "%s: status=0x%02x\n", __func__, val[0]);
> -
> -       return err;
> -}
> -
> -static int si4713_set_power_state(struct si4713_device *sdev, u8 value)
> -{
> -       if (value)
> -               return si4713_powerup(sdev);
> -       return si4713_powerdown(sdev);
> -}
> -
> -static int si4713_set_mute(struct si4713_device *sdev, u16 mute)
> -{
> -       int rval = 0;
> -
> -       mute = set_mute(mute);
> -
> -       if (sdev->power_state)
> -               rval = si4713_write_property(sdev,
> -                               SI4713_TX_LINE_INPUT_MUTE, mute);
> -
> -       return rval;
> -}
> -
> -static int si4713_set_rds_ps_name(struct si4713_device *sdev, char *ps_name)
> -{
> -       int rval = 0, i;
> -       u8 len = 0;
> -
> -       /* We want to clear the whole thing */
> -       if (!strlen(ps_name))
> -               memset(ps_name, 0, MAX_RDS_PS_NAME + 1);
> -
> -       if (sdev->power_state) {
> -               /* Write the new ps name and clear the padding */
> -               for (i = 0; i < MAX_RDS_PS_NAME; i += (RDS_BLOCK / 2)) {
> -                       rval = si4713_tx_rds_ps(sdev, (i / (RDS_BLOCK / 2)),
> -                                               ps_name + i);
> -                       if (rval < 0)
> -                               return rval;
> -               }
> -
> -               /* Setup the size to be sent */
> -               if (strlen(ps_name))
> -                       len = strlen(ps_name) - 1;
> -               else
> -                       len = 1;
> -
> -               rval = si4713_write_property(sdev,
> -                               SI4713_TX_RDS_PS_MESSAGE_COUNT,
> -                               rds_ps_nblocks(len));
> -               if (rval < 0)
> -                       return rval;
> -
> -               rval = si4713_write_property(sdev,
> -                               SI4713_TX_RDS_PS_REPEAT_COUNT,
> -                               DEFAULT_RDS_PS_REPEAT_COUNT * 2);
> -               if (rval < 0)
> -                       return rval;
> -       }
> -
> -       return rval;
> -}
> -
> -static int si4713_set_rds_radio_text(struct si4713_device *sdev, char *rt)
> -{
> -       int rval = 0, i;
> -       u16 t_index = 0;
> -       u8 b_index = 0, cr_inserted = 0;
> -       s8 left;
> -
> -       if (!sdev->power_state)
> -               return rval;
> -
> -       rval = si4713_tx_rds_buff(sdev, RDS_BLOCK_CLEAR, 0, 0, 0, &left);
> -       if (rval < 0)
> -               return rval;
> -
> -       if (!strlen(rt))
> -               return rval;
> -
> -       do {
> -               /* RDS spec says that if the last block isn't used,
> -                * then apply a carriage return
> -                */
> -               if (t_index < (RDS_RADIOTEXT_INDEX_MAX * RDS_RADIOTEXT_BLK_SIZE)) {
> -                       for (i = 0; i < RDS_RADIOTEXT_BLK_SIZE; i++) {
> -                               if (!rt[t_index + i] ||
> -                                   rt[t_index + i] == RDS_CARRIAGE_RETURN) {
> -                                       rt[t_index + i] = RDS_CARRIAGE_RETURN;
> -                                       cr_inserted = 1;
> -                                       break;
> -                               }
> -                       }
> -               }
> -
> -               rval = si4713_tx_rds_buff(sdev, RDS_BLOCK_LOAD,
> -                               compose_u16(RDS_RADIOTEXT_2A, b_index++),
> -                               compose_u16(rt[t_index], rt[t_index + 1]),
> -                               compose_u16(rt[t_index + 2], rt[t_index + 3]),
> -                               &left);
> -               if (rval < 0)
> -                       return rval;
> -
> -               t_index += RDS_RADIOTEXT_BLK_SIZE;
> -
> -               if (cr_inserted)
> -                       break;
> -       } while (left > 0);
> -
> -       return rval;
> -}
> -
> -/*
> - * si4713_update_tune_status - update properties from tx_tune_status
> - * command. Must be called with sdev->mutex held.
> - * @sdev: si4713_device structure for the device we are communicating
> - */
> -static int si4713_update_tune_status(struct si4713_device *sdev)
> -{
> -       int rval;
> -       u16 f = 0;
> -       u8 p = 0, a = 0, n = 0;
> -
> -       rval = si4713_tx_tune_status(sdev, 0x00, &f, &p, &a, &n);
> -
> -       if (rval < 0)
> -               goto exit;
> -
> -/*     TODO: check that power_level and antenna_capacitor really are not
> -       changed by the hardware. If they are, then these controls should become
> -       volatiles.
> -       sdev->power_level = p;
> -       sdev->antenna_capacitor = a;*/
> -       sdev->tune_rnl = n;
> -
> -exit:
> -       return rval;
> -}
> -
> -static int si4713_choose_econtrol_action(struct si4713_device *sdev, u32 id,
> -               s32 *bit, s32 *mask, u16 *property, int *mul,
> -               unsigned long **table, int *size)
> -{
> -       s32 rval = 0;
> -
> -       switch (id) {
> -       /* FM_TX class controls */
> -       case V4L2_CID_RDS_TX_PI:
> -               *property = SI4713_TX_RDS_PI;
> -               *mul = 1;
> -               break;
> -       case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD:
> -               *property = SI4713_TX_ACOMP_THRESHOLD;
> -               *mul = 1;
> -               break;
> -       case V4L2_CID_AUDIO_COMPRESSION_GAIN:
> -               *property = SI4713_TX_ACOMP_GAIN;
> -               *mul = 1;
> -               break;
> -       case V4L2_CID_PILOT_TONE_FREQUENCY:
> -               *property = SI4713_TX_PILOT_FREQUENCY;
> -               *mul = 1;
> -               break;
> -       case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME:
> -               *property = SI4713_TX_ACOMP_ATTACK_TIME;
> -               *mul = ATTACK_TIME_UNIT;
> -               break;
> -       case V4L2_CID_PILOT_TONE_DEVIATION:
> -               *property = SI4713_TX_PILOT_DEVIATION;
> -               *mul = 10;
> -               break;
> -       case V4L2_CID_AUDIO_LIMITER_DEVIATION:
> -               *property = SI4713_TX_AUDIO_DEVIATION;
> -               *mul = 10;
> -               break;
> -       case V4L2_CID_RDS_TX_DEVIATION:
> -               *property = SI4713_TX_RDS_DEVIATION;
> -               *mul = 1;
> -               break;
> -
> -       case V4L2_CID_RDS_TX_PTY:
> -               *property = SI4713_TX_RDS_PS_MISC;
> -               *bit = 5;
> -               *mask = 0x1F << 5;
> -               break;
> -       case V4L2_CID_AUDIO_LIMITER_ENABLED:
> -               *property = SI4713_TX_ACOMP_ENABLE;
> -               *bit = 1;
> -               *mask = 1 << 1;
> -               break;
> -       case V4L2_CID_AUDIO_COMPRESSION_ENABLED:
> -               *property = SI4713_TX_ACOMP_ENABLE;
> -               *bit = 0;
> -               *mask = 1 << 0;
> -               break;
> -       case V4L2_CID_PILOT_TONE_ENABLED:
> -               *property = SI4713_TX_COMPONENT_ENABLE;
> -               *bit = 0;
> -               *mask = 1 << 0;
> -               break;
> -
> -       case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME:
> -               *property = SI4713_TX_LIMITER_RELEASE_TIME;
> -               *table = limiter_times;
> -               *size = ARRAY_SIZE(limiter_times);
> -               break;
> -       case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME:
> -               *property = SI4713_TX_ACOMP_RELEASE_TIME;
> -               *table = acomp_rtimes;
> -               *size = ARRAY_SIZE(acomp_rtimes);
> -               break;
> -       case V4L2_CID_TUNE_PREEMPHASIS:
> -               *property = SI4713_TX_PREEMPHASIS;
> -               *table = preemphasis_values;
> -               *size = ARRAY_SIZE(preemphasis_values);
> -               break;
> -
> -       default:
> -               rval = -EINVAL;
> -               break;
> -       }
> -
> -       return rval;
> -}
> -
> -static int si4713_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *f);
> -static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulator *);
> -/*
> - * si4713_setup - Sets the device up with current configuration.
> - * @sdev: si4713_device structure for the device we are communicating
> - */
> -static int si4713_setup(struct si4713_device *sdev)
> -{
> -       struct v4l2_frequency f;
> -       struct v4l2_modulator vm;
> -       int rval;
> -
> -       /* Device procedure needs to set frequency first */
> -       f.tuner = 0;
> -       f.frequency = sdev->frequency ? sdev->frequency : DEFAULT_FREQUENCY;
> -       f.frequency = si4713_to_v4l2(f.frequency);
> -       rval = si4713_s_frequency(&sdev->sd, &f);
> -
> -       vm.index = 0;
> -       if (sdev->stereo)
> -               vm.txsubchans = V4L2_TUNER_SUB_STEREO;
> -       else
> -               vm.txsubchans = V4L2_TUNER_SUB_MONO;
> -       if (sdev->rds_enabled)
> -               vm.txsubchans |= V4L2_TUNER_SUB_RDS;
> -       si4713_s_modulator(&sdev->sd, &vm);
> -
> -       return rval;
> -}
> -
> -/*
> - * si4713_initialize - Sets the device up with default configuration.
> - * @sdev: si4713_device structure for the device we are communicating
> - */
> -static int si4713_initialize(struct si4713_device *sdev)
> -{
> -       int rval;
> -
> -       rval = si4713_set_power_state(sdev, POWER_ON);
> -       if (rval < 0)
> -               return rval;
> -
> -       rval = si4713_checkrev(sdev);
> -       if (rval < 0)
> -               return rval;
> -
> -       rval = si4713_set_power_state(sdev, POWER_OFF);
> -       if (rval < 0)
> -               return rval;
> -
> -
> -       sdev->frequency = DEFAULT_FREQUENCY;
> -       sdev->stereo = 1;
> -       sdev->tune_rnl = DEFAULT_TUNE_RNL;
> -       return 0;
> -}
> -
> -/* si4713_s_ctrl - set the value of a control */
> -static int si4713_s_ctrl(struct v4l2_ctrl *ctrl)
> -{
> -       struct si4713_device *sdev =
> -               container_of(ctrl->handler, struct si4713_device, ctrl_handler);
> -       u32 val = 0;
> -       s32 bit = 0, mask = 0;
> -       u16 property = 0;
> -       int mul = 0;
> -       unsigned long *table = NULL;
> -       int size = 0;
> -       bool force = false;
> -       int c;
> -       int ret = 0;
> -
> -       if (ctrl->id != V4L2_CID_AUDIO_MUTE)
> -               return -EINVAL;
> -       if (ctrl->is_new) {
> -               if (ctrl->val) {
> -                       ret = si4713_set_mute(sdev, ctrl->val);
> -                       if (!ret)
> -                               ret = si4713_set_power_state(sdev, POWER_DOWN);
> -                       return ret;
> -               }
> -               ret = si4713_set_power_state(sdev, POWER_UP);
> -               if (!ret)
> -                       ret = si4713_set_mute(sdev, ctrl->val);
> -               if (!ret)
> -                       ret = si4713_setup(sdev);
> -               if (ret)
> -                       return ret;
> -               force = true;
> -       }
> -
> -       if (!sdev->power_state)
> -               return 0;
> -
> -       for (c = 1; !ret && c < ctrl->ncontrols; c++) {
> -               ctrl = ctrl->cluster[c];
> -
> -               if (!force && !ctrl->is_new)
> -                       continue;
> -
> -               switch (ctrl->id) {
> -               case V4L2_CID_RDS_TX_PS_NAME:
> -                       ret = si4713_set_rds_ps_name(sdev, ctrl->string);
> -                       break;
> -
> -               case V4L2_CID_RDS_TX_RADIO_TEXT:
> -                       ret = si4713_set_rds_radio_text(sdev, ctrl->string);
> -                       break;
> -
> -               case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
> -                       /* don't handle this control if we force setting all
> -                        * controls since in that case it will be handled by
> -                        * V4L2_CID_TUNE_POWER_LEVEL. */
> -                       if (force)
> -                               break;
> -                       /* fall through */
> -               case V4L2_CID_TUNE_POWER_LEVEL:
> -                       ret = si4713_tx_tune_power(sdev,
> -                               sdev->tune_pwr_level->val, sdev->tune_ant_cap->val);
> -                       if (!ret) {
> -                               /* Make sure we don't set this twice */
> -                               sdev->tune_ant_cap->is_new = false;
> -                               sdev->tune_pwr_level->is_new = false;
> -                       }
> -                       break;
> -
> -               default:
> -                       ret = si4713_choose_econtrol_action(sdev, ctrl->id, &bit,
> -                                       &mask, &property, &mul, &table, &size);
> -                       if (ret < 0)
> -                               break;
> -
> -                       val = ctrl->val;
> -                       if (mul) {
> -                               val = val / mul;
> -                       } else if (table) {
> -                               ret = usecs_to_dev(val, table, size);
> -                               if (ret < 0)
> -                                       break;
> -                               val = ret;
> -                               ret = 0;
> -                       }
> -
> -                       if (mask) {
> -                               ret = si4713_read_property(sdev, property, &val);
> -                               if (ret < 0)
> -                                       break;
> -                               val = set_bits(val, ctrl->val, bit, mask);
> -                       }
> -
> -                       ret = si4713_write_property(sdev, property, val);
> -                       if (ret < 0)
> -                               break;
> -                       if (mask)
> -                               val = ctrl->val;
> -                       break;
> -               }
> -       }
> -
> -       return ret;
> -}
> -
> -/* si4713_ioctl - deal with private ioctls (only rnl for now) */
> -static long si4713_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
> -{
> -       struct si4713_device *sdev = to_si4713_device(sd);
> -       struct si4713_rnl *rnl = arg;
> -       u16 frequency;
> -       int rval = 0;
> -
> -       if (!arg)
> -               return -EINVAL;
> -
> -       switch (cmd) {
> -       case SI4713_IOC_MEASURE_RNL:
> -               frequency = v4l2_to_si4713(rnl->frequency);
> -
> -               if (sdev->power_state) {
> -                       /* Set desired measurement frequency */
> -                       rval = si4713_tx_tune_measure(sdev, frequency, 0);
> -                       if (rval < 0)
> -                               return rval;
> -                       /* get results from tune status */
> -                       rval = si4713_update_tune_status(sdev);
> -                       if (rval < 0)
> -                               return rval;
> -               }
> -               rnl->rnl = sdev->tune_rnl;
> -               break;
> -
> -       default:
> -               /* nothing */
> -               rval = -ENOIOCTLCMD;
> -       }
> -
> -       return rval;
> -}
> -
> -/* si4713_g_modulator - get modulator attributes */
> -static int si4713_g_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm)
> -{
> -       struct si4713_device *sdev = to_si4713_device(sd);
> -       int rval = 0;
> -
> -       if (!sdev)
> -               return -ENODEV;
> -
> -       if (vm->index > 0)
> -               return -EINVAL;
> -
> -       strncpy(vm->name, "FM Modulator", 32);
> -       vm->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW |
> -               V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_CONTROLS;
> -
> -       /* Report current frequency range limits */
> -       vm->rangelow = si4713_to_v4l2(FREQ_RANGE_LOW);
> -       vm->rangehigh = si4713_to_v4l2(FREQ_RANGE_HIGH);
> -
> -       if (sdev->power_state) {
> -               u32 comp_en = 0;
> -
> -               rval = si4713_read_property(sdev, SI4713_TX_COMPONENT_ENABLE,
> -                                               &comp_en);
> -               if (rval < 0)
> -                       return rval;
> -
> -               sdev->stereo = get_status_bit(comp_en, 1, 1 << 1);
> -       }
> -
> -       /* Report current audio mode: mono or stereo */
> -       if (sdev->stereo)
> -               vm->txsubchans = V4L2_TUNER_SUB_STEREO;
> -       else
> -               vm->txsubchans = V4L2_TUNER_SUB_MONO;
> -
> -       /* Report rds feature status */
> -       if (sdev->rds_enabled)
> -               vm->txsubchans |= V4L2_TUNER_SUB_RDS;
> -       else
> -               vm->txsubchans &= ~V4L2_TUNER_SUB_RDS;
> -
> -       return rval;
> -}
> -
> -/* si4713_s_modulator - set modulator attributes */
> -static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulator *vm)
> -{
> -       struct si4713_device *sdev = to_si4713_device(sd);
> -       int rval = 0;
> -       u16 stereo, rds;
> -       u32 p;
> -
> -       if (!sdev)
> -               return -ENODEV;
> -
> -       if (vm->index > 0)
> -               return -EINVAL;
> -
> -       /* Set audio mode: mono or stereo */
> -       if (vm->txsubchans & V4L2_TUNER_SUB_STEREO)
> -               stereo = 1;
> -       else if (vm->txsubchans & V4L2_TUNER_SUB_MONO)
> -               stereo = 0;
> -       else
> -               return -EINVAL;
> -
> -       rds = !!(vm->txsubchans & V4L2_TUNER_SUB_RDS);
> -
> -       if (sdev->power_state) {
> -               rval = si4713_read_property(sdev,
> -                                               SI4713_TX_COMPONENT_ENABLE, &p);
> -               if (rval < 0)
> -                       return rval;
> -
> -               p = set_bits(p, stereo, 1, 1 << 1);
> -               p = set_bits(p, rds, 2, 1 << 2);
> -
> -               rval = si4713_write_property(sdev,
> -                                               SI4713_TX_COMPONENT_ENABLE, p);
> -               if (rval < 0)
> -                       return rval;
> -       }
> -
> -       sdev->stereo = stereo;
> -       sdev->rds_enabled = rds;
> -
> -       return rval;
> -}
> -
> -/* si4713_g_frequency - get tuner or modulator radio frequency */
> -static int si4713_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
> -{
> -       struct si4713_device *sdev = to_si4713_device(sd);
> -       int rval = 0;
> -
> -       if (f->tuner)
> -               return -EINVAL;
> -
> -       if (sdev->power_state) {
> -               u16 freq;
> -               u8 p, a, n;
> -
> -               rval = si4713_tx_tune_status(sdev, 0x00, &freq, &p, &a, &n);
> -               if (rval < 0)
> -                       return rval;
> -
> -               sdev->frequency = freq;
> -       }
> -
> -       f->frequency = si4713_to_v4l2(sdev->frequency);
> -
> -       return rval;
> -}
> -
> -/* si4713_s_frequency - set tuner or modulator radio frequency */
> -static int si4713_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *f)
> -{
> -       struct si4713_device *sdev = to_si4713_device(sd);
> -       int rval = 0;
> -       u16 frequency = v4l2_to_si4713(f->frequency);
> -
> -       if (f->tuner)
> -               return -EINVAL;
> -
> -       /* Check frequency range */
> -       frequency = clamp_t(u16, frequency, FREQ_RANGE_LOW, FREQ_RANGE_HIGH);
> -
> -       if (sdev->power_state) {
> -               rval = si4713_tx_tune_freq(sdev, frequency);
> -               if (rval < 0)
> -                       return rval;
> -               frequency = rval;
> -               rval = 0;
> -       }
> -       sdev->frequency = frequency;
> -
> -       return rval;
> -}
> -
> -static const struct v4l2_ctrl_ops si4713_ctrl_ops = {
> -       .s_ctrl = si4713_s_ctrl,
> -};
> -
> -static const struct v4l2_subdev_core_ops si4713_subdev_core_ops = {
> -       .ioctl          = si4713_ioctl,
> -};
> -
> -static const struct v4l2_subdev_tuner_ops si4713_subdev_tuner_ops = {
> -       .g_frequency    = si4713_g_frequency,
> -       .s_frequency    = si4713_s_frequency,
> -       .g_modulator    = si4713_g_modulator,
> -       .s_modulator    = si4713_s_modulator,
> -};
> -
> -static const struct v4l2_subdev_ops si4713_subdev_ops = {
> -       .core           = &si4713_subdev_core_ops,
> -       .tuner          = &si4713_subdev_tuner_ops,
> -};
> -
> -/*
> - * I2C driver interface
> - */
> -/* si4713_probe - probe for the device */
> -static int si4713_probe(struct i2c_client *client,
> -                                       const struct i2c_device_id *id)
> -{
> -       struct si4713_device *sdev;
> -       struct si4713_platform_data *pdata = client->dev.platform_data;
> -       struct v4l2_ctrl_handler *hdl;
> -       int rval, i;
> -
> -       sdev = kzalloc(sizeof *sdev, GFP_KERNEL);
> -       if (!sdev) {
> -               dev_err(&client->dev, "Failed to alloc video device.\n");
> -               rval = -ENOMEM;
> -               goto exit;
> -       }
> -
> -       sdev->gpio_reset = -1;
> -       if (pdata && gpio_is_valid(pdata->gpio_reset)) {
> -               rval = gpio_request(pdata->gpio_reset, "si4713 reset");
> -               if (rval) {
> -                       dev_err(&client->dev,
> -                               "Failed to request gpio: %d\n", rval);
> -                       goto free_sdev;
> -               }
> -               sdev->gpio_reset = pdata->gpio_reset;
> -               gpio_direction_output(sdev->gpio_reset, 0);
> -       }
> -
> -       for (i = 0; i < ARRAY_SIZE(sdev->supplies); i++)
> -               sdev->supplies[i].supply = si4713_supply_names[i];
> -
> -       rval = regulator_bulk_get(&client->dev, ARRAY_SIZE(sdev->supplies),
> -                                 sdev->supplies);
> -       if (rval) {
> -               dev_err(&client->dev, "Cannot get regulators: %d\n", rval);
> -               goto free_gpio;
> -       }
> -
> -       v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops);
> -
> -       init_completion(&sdev->work);
> -
> -       hdl = &sdev->ctrl_handler;
> -       v4l2_ctrl_handler_init(hdl, 20);
> -       sdev->mute = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> -                       V4L2_CID_AUDIO_MUTE, 0, 1, 1, DEFAULT_MUTE);
> -
> -       sdev->rds_pi = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> -                       V4L2_CID_RDS_TX_PI, 0, 0xffff, 1, DEFAULT_RDS_PI);
> -       sdev->rds_pty = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> -                       V4L2_CID_RDS_TX_PTY, 0, 31, 1, DEFAULT_RDS_PTY);
> -       sdev->rds_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> -                       V4L2_CID_RDS_TX_DEVIATION, 0, MAX_RDS_DEVIATION,
> -                       10, DEFAULT_RDS_DEVIATION);
> -       /*
> -        * Report step as 8. From RDS spec, psname
> -        * should be 8. But there are receivers which scroll strings
> -        * sized as 8xN.
> -        */
> -       sdev->rds_ps_name = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> -                       V4L2_CID_RDS_TX_PS_NAME, 0, MAX_RDS_PS_NAME, 8, 0);
> -       /*
> -        * Report step as 32 (2A block). From RDS spec,
> -        * radio text should be 32 for 2A block. But there are receivers
> -        * which scroll strings sized as 32xN. Setting default to 32.
> -        */
> -       sdev->rds_radio_text = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> -                       V4L2_CID_RDS_TX_RADIO_TEXT, 0, MAX_RDS_RADIO_TEXT, 32, 0);
> -
> -       sdev->limiter_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> -                       V4L2_CID_AUDIO_LIMITER_ENABLED, 0, 1, 1, 1);
> -       sdev->limiter_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> -                       V4L2_CID_AUDIO_LIMITER_RELEASE_TIME, 250,
> -                       MAX_LIMITER_RELEASE_TIME, 10, DEFAULT_LIMITER_RTIME);
> -       sdev->limiter_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> -                       V4L2_CID_AUDIO_LIMITER_DEVIATION, 0,
> -                       MAX_LIMITER_DEVIATION, 10, DEFAULT_LIMITER_DEV);
> -
> -       sdev->compression_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> -                       V4L2_CID_AUDIO_COMPRESSION_ENABLED, 0, 1, 1, 1);
> -       sdev->compression_gain = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> -                       V4L2_CID_AUDIO_COMPRESSION_GAIN, 0, MAX_ACOMP_GAIN, 1,
> -                       DEFAULT_ACOMP_GAIN);
> -       sdev->compression_threshold = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> -                       V4L2_CID_AUDIO_COMPRESSION_THRESHOLD, MIN_ACOMP_THRESHOLD,
> -                       MAX_ACOMP_THRESHOLD, 1,
> -                       DEFAULT_ACOMP_THRESHOLD);
> -       sdev->compression_attack_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> -                       V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME, 0,
> -                       MAX_ACOMP_ATTACK_TIME, 500, DEFAULT_ACOMP_ATIME);
> -       sdev->compression_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> -                       V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME, 100000,
> -                       MAX_ACOMP_RELEASE_TIME, 100000, DEFAULT_ACOMP_RTIME);
> -
> -       sdev->pilot_tone_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> -                       V4L2_CID_PILOT_TONE_ENABLED, 0, 1, 1, 1);
> -       sdev->pilot_tone_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> -                       V4L2_CID_PILOT_TONE_DEVIATION, 0, MAX_PILOT_DEVIATION,
> -                       10, DEFAULT_PILOT_DEVIATION);
> -       sdev->pilot_tone_freq = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> -                       V4L2_CID_PILOT_TONE_FREQUENCY, 0, MAX_PILOT_FREQUENCY,
> -                       1, DEFAULT_PILOT_FREQUENCY);
> -
> -       sdev->tune_preemphasis = v4l2_ctrl_new_std_menu(hdl, &si4713_ctrl_ops,
> -                       V4L2_CID_TUNE_PREEMPHASIS,
> -                       V4L2_PREEMPHASIS_75_uS, 0, V4L2_PREEMPHASIS_50_uS);
> -       sdev->tune_pwr_level = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> -                       V4L2_CID_TUNE_POWER_LEVEL, 0, 120, 1, DEFAULT_POWER_LEVEL);
> -       sdev->tune_ant_cap = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> -                       V4L2_CID_TUNE_ANTENNA_CAPACITOR, 0, 191, 1, 0);
> -
> -       if (hdl->error) {
> -               rval = hdl->error;
> -               goto free_ctrls;
> -       }
> -       v4l2_ctrl_cluster(20, &sdev->mute);
> -       sdev->sd.ctrl_handler = hdl;
> -
> -       if (client->irq) {
> -               rval = request_irq(client->irq,
> -                       si4713_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED,
> -                       client->name, sdev);
> -               if (rval < 0) {
> -                       v4l2_err(&sdev->sd, "Could not request IRQ\n");
> -                       goto put_reg;
> -               }
> -               v4l2_dbg(1, debug, &sdev->sd, "IRQ requested.\n");
> -       } else {
> -               v4l2_warn(&sdev->sd, "IRQ not configured. Using timeouts.\n");
> -       }
> -
> -       rval = si4713_initialize(sdev);
> -       if (rval < 0) {
> -               v4l2_err(&sdev->sd, "Failed to probe device information.\n");
> -               goto free_irq;
> -       }
> -
> -       return 0;
> -
> -free_irq:
> -       if (client->irq)
> -               free_irq(client->irq, sdev);
> -free_ctrls:
> -       v4l2_ctrl_handler_free(hdl);
> -put_reg:
> -       regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies);
> -free_gpio:
> -       if (gpio_is_valid(sdev->gpio_reset))
> -               gpio_free(sdev->gpio_reset);
> -free_sdev:
> -       kfree(sdev);
> -exit:
> -       return rval;
> -}
> -
> -/* si4713_remove - remove the device */
> -static int si4713_remove(struct i2c_client *client)
> -{
> -       struct v4l2_subdev *sd = i2c_get_clientdata(client);
> -       struct si4713_device *sdev = to_si4713_device(sd);
> -
> -       if (sdev->power_state)
> -               si4713_set_power_state(sdev, POWER_DOWN);
> -
> -       if (client->irq > 0)
> -               free_irq(client->irq, sdev);
> -
> -       v4l2_device_unregister_subdev(sd);
> -       v4l2_ctrl_handler_free(sd->ctrl_handler);
> -       regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies);
> -       if (gpio_is_valid(sdev->gpio_reset))
> -               gpio_free(sdev->gpio_reset);
> -       kfree(sdev);
> -
> -       return 0;
> -}
> -
> -/* si4713_i2c_driver - i2c driver interface */
> -static const struct i2c_device_id si4713_id[] = {
> -       { "si4713" , 0 },
> -       { },
> -};
> -MODULE_DEVICE_TABLE(i2c, si4713_id);
> -
> -static struct i2c_driver si4713_i2c_driver = {
> -       .driver         = {
> -               .name   = "si4713",
> -       },
> -       .probe          = si4713_probe,
> -       .remove         = si4713_remove,
> -       .id_table       = si4713_id,
> -};
> -
> -module_i2c_driver(si4713_i2c_driver);
> diff --git a/drivers/media/radio/si4713-i2c.h b/drivers/media/radio/si4713-i2c.h
> deleted file mode 100644
> index 25cdea2..0000000
> --- a/drivers/media/radio/si4713-i2c.h
> +++ /dev/null
> @@ -1,238 +0,0 @@
> -/*
> - * drivers/media/radio/si4713-i2c.h
> - *
> - * Property and commands definitions for Si4713 radio transmitter chip.
> - *
> - * Copyright (c) 2008 Instituto Nokia de Tecnologia - INdT
> - * Contact: Eduardo Valentin <eduardo.valentin@xxxxxxxxx>
> - *
> - * This file is licensed under the terms of the GNU General Public License
> - * version 2. This program is licensed "as is" without any warranty of any
> - * kind, whether express or implied.
> - *
> - */
> -
> -#ifndef SI4713_I2C_H
> -#define SI4713_I2C_H
> -
> -#include <media/v4l2-subdev.h>
> -#include <media/v4l2-ctrls.h>
> -#include <media/si4713.h>
> -
> -#define SI4713_PRODUCT_NUMBER          0x0D
> -
> -/* Command Timeouts */
> -#define DEFAULT_TIMEOUT                        500
> -#define TIMEOUT_SET_PROPERTY           20
> -#define TIMEOUT_TX_TUNE_POWER          30000
> -#define TIMEOUT_TX_TUNE                        110000
> -#define TIMEOUT_POWER_UP               200000
> -
> -/*
> - * Command and its arguments definitions
> - */
> -#define SI4713_PWUP_CTSIEN             (1<<7)
> -#define SI4713_PWUP_GPO2OEN            (1<<6)
> -#define SI4713_PWUP_PATCH              (1<<5)
> -#define SI4713_PWUP_XOSCEN             (1<<4)
> -#define SI4713_PWUP_FUNC_TX            0x02
> -#define SI4713_PWUP_FUNC_PATCH         0x0F
> -#define SI4713_PWUP_OPMOD_ANALOG       0x50
> -#define SI4713_PWUP_OPMOD_DIGITAL      0x0F
> -#define SI4713_PWUP_NARGS              2
> -#define SI4713_PWUP_NRESP              1
> -#define SI4713_CMD_POWER_UP            0x01
> -
> -#define SI4713_GETREV_NRESP            9
> -#define SI4713_CMD_GET_REV             0x10
> -
> -#define SI4713_PWDN_NRESP              1
> -#define SI4713_CMD_POWER_DOWN          0x11
> -
> -#define SI4713_SET_PROP_NARGS          5
> -#define SI4713_SET_PROP_NRESP          1
> -#define SI4713_CMD_SET_PROPERTY                0x12
> -
> -#define SI4713_GET_PROP_NARGS          3
> -#define SI4713_GET_PROP_NRESP          4
> -#define SI4713_CMD_GET_PROPERTY                0x13
> -
> -#define SI4713_GET_STATUS_NRESP                1
> -#define SI4713_CMD_GET_INT_STATUS      0x14
> -
> -#define SI4713_CMD_PATCH_ARGS          0x15
> -#define SI4713_CMD_PATCH_DATA          0x16
> -
> -#define SI4713_MAX_FREQ                        10800
> -#define SI4713_MIN_FREQ                        7600
> -#define SI4713_TXFREQ_NARGS            3
> -#define SI4713_TXFREQ_NRESP            1
> -#define SI4713_CMD_TX_TUNE_FREQ                0x30
> -
> -#define SI4713_MAX_POWER               120
> -#define SI4713_MIN_POWER               88
> -#define SI4713_MAX_ANTCAP              191
> -#define SI4713_MIN_ANTCAP              0
> -#define SI4713_TXPWR_NARGS             4
> -#define SI4713_TXPWR_NRESP             1
> -#define SI4713_CMD_TX_TUNE_POWER       0x31
> -
> -#define SI4713_TXMEA_NARGS             4
> -#define SI4713_TXMEA_NRESP             1
> -#define SI4713_CMD_TX_TUNE_MEASURE     0x32
> -
> -#define SI4713_INTACK_MASK             0x01
> -#define SI4713_TXSTATUS_NARGS          1
> -#define SI4713_TXSTATUS_NRESP          8
> -#define SI4713_CMD_TX_TUNE_STATUS      0x33
> -
> -#define SI4713_OVERMOD_BIT             (1 << 2)
> -#define SI4713_IALH_BIT                        (1 << 1)
> -#define SI4713_IALL_BIT                        (1 << 0)
> -#define SI4713_ASQSTATUS_NARGS         1
> -#define SI4713_ASQSTATUS_NRESP         5
> -#define SI4713_CMD_TX_ASQ_STATUS       0x34
> -
> -#define SI4713_RDSBUFF_MODE_MASK       0x87
> -#define SI4713_RDSBUFF_NARGS           7
> -#define SI4713_RDSBUFF_NRESP           6
> -#define SI4713_CMD_TX_RDS_BUFF         0x35
> -
> -#define SI4713_RDSPS_PSID_MASK         0x1F
> -#define SI4713_RDSPS_NARGS             5
> -#define SI4713_RDSPS_NRESP             1
> -#define SI4713_CMD_TX_RDS_PS           0x36
> -
> -#define SI4713_CMD_GPO_CTL             0x80
> -#define SI4713_CMD_GPO_SET             0x81
> -
> -/*
> - * Bits from status response
> - */
> -#define SI4713_CTS                     (1<<7)
> -#define SI4713_ERR                     (1<<6)
> -#define SI4713_RDS_INT                 (1<<2)
> -#define SI4713_ASQ_INT                 (1<<1)
> -#define SI4713_STC_INT                 (1<<0)
> -
> -/*
> - * Property definitions
> - */
> -#define SI4713_GPO_IEN                 0x0001
> -#define SI4713_DIG_INPUT_FORMAT                0x0101
> -#define SI4713_DIG_INPUT_SAMPLE_RATE   0x0103
> -#define SI4713_REFCLK_FREQ             0x0201
> -#define SI4713_REFCLK_PRESCALE         0x0202
> -#define SI4713_TX_COMPONENT_ENABLE     0x2100
> -#define SI4713_TX_AUDIO_DEVIATION      0x2101
> -#define SI4713_TX_PILOT_DEVIATION      0x2102
> -#define SI4713_TX_RDS_DEVIATION                0x2103
> -#define SI4713_TX_LINE_INPUT_LEVEL     0x2104
> -#define SI4713_TX_LINE_INPUT_MUTE      0x2105
> -#define SI4713_TX_PREEMPHASIS          0x2106
> -#define SI4713_TX_PILOT_FREQUENCY      0x2107
> -#define SI4713_TX_ACOMP_ENABLE         0x2200
> -#define SI4713_TX_ACOMP_THRESHOLD      0x2201
> -#define SI4713_TX_ACOMP_ATTACK_TIME    0x2202
> -#define SI4713_TX_ACOMP_RELEASE_TIME   0x2203
> -#define SI4713_TX_ACOMP_GAIN           0x2204
> -#define SI4713_TX_LIMITER_RELEASE_TIME 0x2205
> -#define SI4713_TX_ASQ_INTERRUPT_SOURCE 0x2300
> -#define SI4713_TX_ASQ_LEVEL_LOW                0x2301
> -#define SI4713_TX_ASQ_DURATION_LOW     0x2302
> -#define SI4713_TX_ASQ_LEVEL_HIGH       0x2303
> -#define SI4713_TX_ASQ_DURATION_HIGH    0x2304
> -#define SI4713_TX_RDS_INTERRUPT_SOURCE 0x2C00
> -#define SI4713_TX_RDS_PI               0x2C01
> -#define SI4713_TX_RDS_PS_MIX           0x2C02
> -#define SI4713_TX_RDS_PS_MISC          0x2C03
> -#define SI4713_TX_RDS_PS_REPEAT_COUNT  0x2C04
> -#define SI4713_TX_RDS_PS_MESSAGE_COUNT 0x2C05
> -#define SI4713_TX_RDS_PS_AF            0x2C06
> -#define SI4713_TX_RDS_FIFO_SIZE                0x2C07
> -
> -#define PREEMPHASIS_USA                        75
> -#define PREEMPHASIS_EU                 50
> -#define PREEMPHASIS_DISABLED           0
> -#define FMPE_USA                       0x00
> -#define FMPE_EU                                0x01
> -#define FMPE_DISABLED                  0x02
> -
> -#define POWER_UP                       0x01
> -#define POWER_DOWN                     0x00
> -
> -#define MAX_RDS_PTY                    31
> -#define MAX_RDS_DEVIATION              90000
> -
> -/*
> - * PSNAME is known to be defined as 8 character sized (RDS Spec).
> - * However, there is receivers which scroll PSNAME 8xN sized.
> - */
> -#define MAX_RDS_PS_NAME                        96
> -
> -/*
> - * MAX_RDS_RADIO_TEXT is known to be defined as 32 (2A group) or 64 (2B group)
> - * character sized (RDS Spec).
> - * However, there is receivers which scroll them as well.
> - */
> -#define MAX_RDS_RADIO_TEXT             384
> -
> -#define MAX_LIMITER_RELEASE_TIME       102390
> -#define MAX_LIMITER_DEVIATION          90000
> -
> -#define MAX_PILOT_DEVIATION            90000
> -#define MAX_PILOT_FREQUENCY            19000
> -
> -#define MAX_ACOMP_RELEASE_TIME         1000000
> -#define MAX_ACOMP_ATTACK_TIME          5000
> -#define MAX_ACOMP_THRESHOLD            0
> -#define MIN_ACOMP_THRESHOLD            (-40)
> -#define MAX_ACOMP_GAIN                 20
> -
> -#define SI4713_NUM_SUPPLIES            2
> -
> -/*
> - * si4713_device - private data
> - */
> -struct si4713_device {
> -       /* v4l2_subdev and i2c reference (v4l2_subdev priv data) */
> -       struct v4l2_subdev sd;
> -       struct v4l2_ctrl_handler ctrl_handler;
> -       /* private data structures */
> -       struct { /* si4713 control cluster */
> -               /* This is one big cluster since the mute control
> -                * powers off the device and after unmuting again all
> -                * controls need to be set at once. The only way of doing
> -                * that is by making it one big cluster. */
> -               struct v4l2_ctrl *mute;
> -               struct v4l2_ctrl *rds_ps_name;
> -               struct v4l2_ctrl *rds_radio_text;
> -               struct v4l2_ctrl *rds_pi;
> -               struct v4l2_ctrl *rds_deviation;
> -               struct v4l2_ctrl *rds_pty;
> -               struct v4l2_ctrl *compression_enabled;
> -               struct v4l2_ctrl *compression_threshold;
> -               struct v4l2_ctrl *compression_gain;
> -               struct v4l2_ctrl *compression_attack_time;
> -               struct v4l2_ctrl *compression_release_time;
> -               struct v4l2_ctrl *pilot_tone_enabled;
> -               struct v4l2_ctrl *pilot_tone_freq;
> -               struct v4l2_ctrl *pilot_tone_deviation;
> -               struct v4l2_ctrl *limiter_enabled;
> -               struct v4l2_ctrl *limiter_deviation;
> -               struct v4l2_ctrl *limiter_release_time;
> -               struct v4l2_ctrl *tune_preemphasis;
> -               struct v4l2_ctrl *tune_pwr_level;
> -               struct v4l2_ctrl *tune_ant_cap;
> -       };
> -       struct completion work;
> -       struct regulator_bulk_data supplies[SI4713_NUM_SUPPLIES];
> -       int gpio_reset;
> -       u32 power_state;
> -       u32 rds_enabled;
> -       u32 frequency;
> -       u32 preemphasis;
> -       u32 stereo;
> -       u32 tune_rnl;
> -};
> -#endif /* ifndef SI4713_I2C_H */
> diff --git a/drivers/media/radio/si4713/Kconfig b/drivers/media/radio/si4713/Kconfig
> new file mode 100644
> index 0000000..f8ac328
> --- /dev/null
> +++ b/drivers/media/radio/si4713/Kconfig
> @@ -0,0 +1,25 @@
> +config PLATFORM_SI4713
> +       tristate "Silicon Labs Si4713 FM Radio Transmitter support with I2C"
> +       depends on I2C && RADIO_SI4713
> +       select SI4713
> +       ---help---
> +         This is a driver for I2C devices with the Silicon Labs SI4713
> +         chip.
> +
> +         Say Y here if you want to connect this type of radio to your
> +         computer's I2C port.
> +
> +         To compile this driver as a module, choose M here: the
> +         module will be called radio-platform-si4713.
> +
> +config I2C_SI4713
> +       tristate "Silicon Labs Si4713 FM Radio Transmitter support"
> +       depends on I2C && RADIO_SI4713
> +       ---help---
> +         Say Y here if you want support to Si4713 FM Radio Transmitter.
> +         This device can transmit audio through FM. It can transmit
> +         RDS and RBDS signals as well. This module is the v4l2 radio
> +         interface for the i2c driver of this device.
> +
> +         To compile this driver as a module, choose M here: the
> +         module will be called si4713.
> diff --git a/drivers/media/radio/si4713/Makefile b/drivers/media/radio/si4713/Makefile
> new file mode 100644
> index 0000000..9d0bd0e
> --- /dev/null
> +++ b/drivers/media/radio/si4713/Makefile
> @@ -0,0 +1,7 @@
> +#
> +# Makefile for radios with Silicon Labs Si4713 FM Radio Transmitters
> +#
> +
> +obj-$(CONFIG_I2C_SI4713) += si4713.o
> +obj-$(CONFIG_PLATFORM_SI4713) += radio-platform-si4713.o
> +
> diff --git a/drivers/media/radio/si4713/radio-platform-si4713.c b/drivers/media/radio/si4713/radio-platform-si4713.c
> new file mode 100644
> index 0000000..cf0aad4
> --- /dev/null
> +++ b/drivers/media/radio/si4713/radio-platform-si4713.c
> @@ -0,0 +1,246 @@
> +/*
> + * drivers/media/radio/radio-platform-si4713.c
> + *
> + * Platform Driver for Silicon Labs Si4713 FM Radio Transmitter:
> + *
> + * Copyright (c) 2008 Instituto Nokia de Tecnologia - INdT
> + * Contact: Eduardo Valentin <eduardo.valentin@xxxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * 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
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/platform_device.h>
> +#include <linux/i2c.h>
> +#include <linux/videodev2.h>
> +#include <linux/slab.h>
> +#include <media/v4l2-device.h>
> +#include <media/v4l2-common.h>
> +#include <media/v4l2-ioctl.h>
> +#include <media/v4l2-fh.h>
> +#include <media/v4l2-ctrls.h>
> +#include <media/v4l2-event.h>
> +#include <media/radio-si4713.h>
> +
> +/* module parameters */
> +static int radio_nr = -1;      /* radio device minor (-1 ==> auto assign) */
> +module_param(radio_nr, int, 0);
> +MODULE_PARM_DESC(radio_nr,
> +                "Minor number for radio device (-1 ==> auto assign)");
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("Eduardo Valentin <eduardo.valentin@xxxxxxxxx>");
> +MODULE_DESCRIPTION("Platform driver for Si4713 FM Radio Transmitter");
> +MODULE_VERSION("0.0.1");
> +MODULE_ALIAS("platform:radio-si4713");
> +
> +/* Driver state struct */
> +struct radio_si4713_device {
> +       struct v4l2_device              v4l2_dev;
> +       struct video_device             radio_dev;
> +       struct mutex lock;
> +};
> +
> +/* radio_si4713_fops - file operations interface */
> +static const struct v4l2_file_operations radio_si4713_fops = {
> +       .owner          = THIS_MODULE,
> +       .open = v4l2_fh_open,
> +       .release = v4l2_fh_release,
> +       .poll = v4l2_ctrl_poll,
> +       /* Note: locking is done at the subdev level in the i2c driver. */
> +       .unlocked_ioctl = video_ioctl2,
> +};
> +
> +/* Video4Linux Interface */
> +
> +/* radio_si4713_querycap - query device capabilities */
> +static int radio_si4713_querycap(struct file *file, void *priv,
> +                                       struct v4l2_capability *capability)
> +{
> +       strlcpy(capability->driver, "radio-si4713", sizeof(capability->driver));
> +       strlcpy(capability->card, "Silicon Labs Si4713 Modulator",
> +               sizeof(capability->card));
> +       strlcpy(capability->bus_info, "platform:radio-si4713",
> +               sizeof(capability->bus_info));
> +       capability->device_caps = V4L2_CAP_MODULATOR | V4L2_CAP_RDS_OUTPUT;
> +       capability->capabilities = capability->device_caps | V4L2_CAP_DEVICE_CAPS;
> +
> +       return 0;
> +}
> +
> +/*
> + * v4l2 ioctl call backs.
> + * we are just a wrapper for v4l2_sub_devs.
> + */
> +static inline struct v4l2_device *get_v4l2_dev(struct file *file)
> +{
> +       return &((struct radio_si4713_device *)video_drvdata(file))->v4l2_dev;
> +}
> +
> +static int radio_si4713_g_modulator(struct file *file, void *p,
> +                                   struct v4l2_modulator *vm)
> +{
> +       return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
> +                                         g_modulator, vm);
> +}
> +
> +static int radio_si4713_s_modulator(struct file *file, void *p,
> +                                   const struct v4l2_modulator *vm)
> +{
> +       return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
> +                                         s_modulator, vm);
> +}
> +
> +static int radio_si4713_g_frequency(struct file *file, void *p,
> +                                   struct v4l2_frequency *vf)
> +{
> +       return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
> +                                         g_frequency, vf);
> +}
> +
> +static int radio_si4713_s_frequency(struct file *file, void *p,
> +                                   const struct v4l2_frequency *vf)
> +{
> +       return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
> +                                         s_frequency, vf);
> +}
> +
> +static long radio_si4713_default(struct file *file, void *p,
> +                                bool valid_prio, unsigned int cmd, void *arg)
> +{
> +       return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
> +                                         ioctl, cmd, arg);
> +}
> +
> +static struct v4l2_ioctl_ops radio_si4713_ioctl_ops = {
> +       .vidioc_querycap        = radio_si4713_querycap,
> +       .vidioc_g_modulator     = radio_si4713_g_modulator,
> +       .vidioc_s_modulator     = radio_si4713_s_modulator,
> +       .vidioc_g_frequency     = radio_si4713_g_frequency,
> +       .vidioc_s_frequency     = radio_si4713_s_frequency,
> +       .vidioc_log_status      = v4l2_ctrl_log_status,
> +       .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
> +       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
> +       .vidioc_default         = radio_si4713_default,
> +};
> +
> +/* radio_si4713_vdev_template - video device interface */
> +static struct video_device radio_si4713_vdev_template = {
> +       .fops                   = &radio_si4713_fops,
> +       .name                   = "radio-si4713",
> +       .release                = video_device_release_empty,
> +       .ioctl_ops              = &radio_si4713_ioctl_ops,
> +       .vfl_dir                = VFL_DIR_TX,
> +};
> +
> +/* Platform driver interface */
> +/* radio_si4713_pdriver_probe - probe for the device */
> +static int radio_si4713_pdriver_probe(struct platform_device *pdev)
> +{
> +       struct radio_si4713_platform_data *pdata = pdev->dev.platform_data;
> +       struct radio_si4713_device *rsdev;
> +       struct i2c_adapter *adapter;
> +       struct v4l2_subdev *sd;
> +       int rval = 0;
> +
> +       if (!pdata) {
> +               dev_err(&pdev->dev, "Cannot proceed without platform data.\n");
> +               rval = -EINVAL;
> +               goto exit;
> +       }
> +
> +       rsdev = devm_kzalloc(&pdev->dev, sizeof(*rsdev), GFP_KERNEL);
> +       if (!rsdev) {
> +               dev_err(&pdev->dev, "Failed to alloc video device.\n");
> +               rval = -ENOMEM;
> +               goto exit;
> +       }
> +       mutex_init(&rsdev->lock);
> +
> +       rval = v4l2_device_register(&pdev->dev, &rsdev->v4l2_dev);
> +       if (rval) {
> +               dev_err(&pdev->dev, "Failed to register v4l2 device.\n");
> +               goto exit;
> +       }
> +
> +       adapter = i2c_get_adapter(pdata->i2c_bus);
> +       if (!adapter) {
> +               dev_err(&pdev->dev, "Cannot get i2c adapter %d\n",
> +                       pdata->i2c_bus);
> +               rval = -ENODEV;
> +               goto unregister_v4l2_dev;
> +       }
> +
> +       sd = v4l2_i2c_new_subdev_board(&rsdev->v4l2_dev, adapter,
> +                                      pdata->subdev_board_info, NULL);
> +       if (!sd) {
> +               dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n");
> +               rval = -ENODEV;
> +               goto put_adapter;
> +       }
> +
> +       rsdev->radio_dev = radio_si4713_vdev_template;
> +       rsdev->radio_dev.v4l2_dev = &rsdev->v4l2_dev;
> +       rsdev->radio_dev.ctrl_handler = sd->ctrl_handler;
> +       set_bit(V4L2_FL_USE_FH_PRIO, &rsdev->radio_dev.flags);
> +       /* Serialize all access to the si4713 */
> +       rsdev->radio_dev.lock = &rsdev->lock;
> +       video_set_drvdata(&rsdev->radio_dev, rsdev);
> +       if (video_register_device(&rsdev->radio_dev, VFL_TYPE_RADIO, radio_nr)) {
> +               dev_err(&pdev->dev, "Could not register video device.\n");
> +               rval = -EIO;
> +               goto put_adapter;
> +       }
> +       dev_info(&pdev->dev, "New device successfully probed\n");
> +
> +       goto exit;
> +
> +put_adapter:
> +       i2c_put_adapter(adapter);
> +unregister_v4l2_dev:
> +       v4l2_device_unregister(&rsdev->v4l2_dev);
> +exit:
> +       return rval;
> +}
> +
> +/* radio_si4713_pdriver_remove - remove the device */
> +static int radio_si4713_pdriver_remove(struct platform_device *pdev)
> +{
> +       struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
> +       struct v4l2_subdev *sd = list_entry(v4l2_dev->subdevs.next,
> +                                           struct v4l2_subdev, list);
> +       struct i2c_client *client = v4l2_get_subdevdata(sd);
> +       struct radio_si4713_device *rsdev;
> +
> +       rsdev = container_of(v4l2_dev, struct radio_si4713_device, v4l2_dev);
> +       video_unregister_device(&rsdev->radio_dev);
> +       i2c_put_adapter(client->adapter);
> +       v4l2_device_unregister(&rsdev->v4l2_dev);
> +
> +       return 0;
> +}
> +
> +static struct platform_driver radio_si4713_pdriver = {
> +       .driver         = {
> +               .name   = "radio-si4713",
> +               .owner  = THIS_MODULE,
> +       },
> +       .probe          = radio_si4713_pdriver_probe,
> +       .remove         = radio_si4713_pdriver_remove,
> +};
> +
> +module_platform_driver(radio_si4713_pdriver);
> diff --git a/drivers/media/radio/si4713/si4713.c b/drivers/media/radio/si4713/si4713.c
> new file mode 100644
> index 0000000..ac727e3
> --- /dev/null
> +++ b/drivers/media/radio/si4713/si4713.c
> @@ -0,0 +1,1532 @@
> +/*
> + * drivers/media/radio/si4713.c
> + *
> + * Silicon Labs Si4713 FM Radio Transmitter I2C commands.
> + *
> + * Copyright (c) 2009 Nokia Corporation
> + * Contact: Eduardo Valentin <eduardo.valentin@xxxxxxxxx>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * 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
> + */
> +
> +#include <linux/completion.h>
> +#include <linux/delay.h>
> +#include <linux/interrupt.h>
> +#include <linux/i2c.h>
> +#include <linux/slab.h>
> +#include <linux/gpio.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/module.h>
> +#include <media/v4l2-device.h>
> +#include <media/v4l2-ioctl.h>
> +#include <media/v4l2-common.h>
> +
> +#include "si4713.h"
> +
> +/* module parameters */
> +static int debug;
> +module_param(debug, int, S_IRUGO | S_IWUSR);
> +MODULE_PARM_DESC(debug, "Debug level (0 - 2)");
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Eduardo Valentin <eduardo.valentin@xxxxxxxxx>");
> +MODULE_DESCRIPTION("I2C driver for Si4713 FM Radio Transmitter");
> +MODULE_VERSION("0.0.1");
> +
> +static const char *si4713_supply_names[SI4713_NUM_SUPPLIES] = {
> +       "vio",
> +       "vdd",
> +};
> +
> +#define DEFAULT_RDS_PI                 0x00
> +#define DEFAULT_RDS_PTY                        0x00
> +#define DEFAULT_RDS_DEVIATION          0x00C8
> +#define DEFAULT_RDS_PS_REPEAT_COUNT    0x0003
> +#define DEFAULT_LIMITER_RTIME          0x1392
> +#define DEFAULT_LIMITER_DEV            0x102CA
> +#define DEFAULT_PILOT_FREQUENCY        0x4A38
> +#define DEFAULT_PILOT_DEVIATION                0x1A5E
> +#define DEFAULT_ACOMP_ATIME            0x0000
> +#define DEFAULT_ACOMP_RTIME            0xF4240L
> +#define DEFAULT_ACOMP_GAIN             0x0F
> +#define DEFAULT_ACOMP_THRESHOLD        (-0x28)
> +#define DEFAULT_MUTE                   0x01
> +#define DEFAULT_POWER_LEVEL            88
> +#define DEFAULT_FREQUENCY              8800
> +#define DEFAULT_PREEMPHASIS            FMPE_EU
> +#define DEFAULT_TUNE_RNL               0xFF
> +
> +#define to_si4713_device(sd)   container_of(sd, struct si4713_device, sd)
> +
> +/* frequency domain transformation (using times 10 to avoid floats) */
> +#define FREQDEV_UNIT   100000
> +#define FREQV4L2_MULTI 625
> +#define si4713_to_v4l2(f)      ((f * FREQDEV_UNIT) / FREQV4L2_MULTI)
> +#define v4l2_to_si4713(f)      ((f * FREQV4L2_MULTI) / FREQDEV_UNIT)
> +#define FREQ_RANGE_LOW                 7600
> +#define FREQ_RANGE_HIGH                        10800
> +
> +#define MAX_ARGS 7
> +
> +#define RDS_BLOCK                      8
> +#define RDS_BLOCK_CLEAR                        0x03
> +#define RDS_BLOCK_LOAD                 0x04
> +#define RDS_RADIOTEXT_2A               0x20
> +#define RDS_RADIOTEXT_BLK_SIZE         4
> +#define RDS_RADIOTEXT_INDEX_MAX                0x0F
> +#define RDS_CARRIAGE_RETURN            0x0D
> +
> +#define rds_ps_nblocks(len)    ((len / RDS_BLOCK) + (len % RDS_BLOCK ? 1 : 0))
> +
> +#define get_status_bit(p, b, m)        (((p) & (m)) >> (b))
> +#define set_bits(p, v, b, m)   (((p) & ~(m)) | ((v) << (b)))
> +
> +#define ATTACK_TIME_UNIT       500
> +
> +#define POWER_OFF                      0x00
> +#define POWER_ON                       0x01
> +
> +#define msb(x)                  ((u8)((u16) x >> 8))
> +#define lsb(x)                  ((u8)((u16) x &  0x00FF))
> +#define compose_u16(msb, lsb)  (((u16)msb << 8) | lsb)
> +#define check_command_failed(status)   (!(status & SI4713_CTS) || \
> +                                       (status & SI4713_ERR))
> +/* mute definition */
> +#define set_mute(p)    ((p & 1) | ((p & 1) << 1));
> +
> +#ifdef DEBUG
> +#define DBG_BUFFER(device, message, buffer, size)                      \
> +       {                                                               \
> +               int i;                                                  \
> +               char str[(size)*5];                                     \
> +               for (i = 0; i < size; i++)                              \
> +                       sprintf(str + i * 5, " 0x%02x", buffer[i]);     \
> +               v4l2_dbg(2, debug, device, "%s:%s\n", message, str);    \
> +       }
> +#else
> +#define DBG_BUFFER(device, message, buffer, size)
> +#endif
> +
> +/*
> + * Values for limiter release time (sorted by second column)
> + *     device  release
> + *     value   time (us)
> + */
> +static long limiter_times[] = {
> +       2000,   250,
> +       1000,   500,
> +       510,    1000,
> +       255,    2000,
> +       170,    3000,
> +       127,    4020,
> +       102,    5010,
> +       85,     6020,
> +       73,     7010,
> +       64,     7990,
> +       57,     8970,
> +       51,     10030,
> +       25,     20470,
> +       17,     30110,
> +       13,     39380,
> +       10,     51190,
> +       8,      63690,
> +       7,      73140,
> +       6,      85330,
> +       5,      102390,
> +};
> +
> +/*
> + * Values for audio compression release time (sorted by second column)
> + *     device  release
> + *     value   time (us)
> + */
> +static unsigned long acomp_rtimes[] = {
> +       0,      100000,
> +       1,      200000,
> +       2,      350000,
> +       3,      525000,
> +       4,      1000000,
> +};
> +
> +/*
> + * Values for preemphasis (sorted by second column)
> + *     device  preemphasis
> + *     value   value (v4l2)
> + */
> +static unsigned long preemphasis_values[] = {
> +       FMPE_DISABLED,  V4L2_PREEMPHASIS_DISABLED,
> +       FMPE_EU,        V4L2_PREEMPHASIS_50_uS,
> +       FMPE_USA,       V4L2_PREEMPHASIS_75_uS,
> +};
> +
> +static int usecs_to_dev(unsigned long usecs, unsigned long const array[],
> +                       int size)
> +{
> +       int i;
> +       int rval = -EINVAL;
> +
> +       for (i = 0; i < size / 2; i++)
> +               if (array[(i * 2) + 1] >= usecs) {
> +                       rval = array[i * 2];
> +                       break;
> +               }
> +
> +       return rval;
> +}
> +
> +/* si4713_handler: IRQ handler, just complete work */
> +static irqreturn_t si4713_handler(int irq, void *dev)
> +{
> +       struct si4713_device *sdev = dev;
> +
> +       v4l2_dbg(2, debug, &sdev->sd,
> +                       "%s: sending signal to completion work.\n", __func__);
> +       complete(&sdev->work);
> +
> +       return IRQ_HANDLED;
> +}
> +
> +/*
> + * si4713_send_command - sends a command to si4713 and waits its response
> + * @sdev: si4713_device structure for the device we are communicating
> + * @command: command id
> + * @args: command arguments we are sending (up to 7)
> + * @argn: actual size of @args
> + * @response: buffer to place the expected response from the device (up to 15)
> + * @respn: actual size of @response
> + * @usecs: amount of time to wait before reading the response (in usecs)
> + */
> +static int si4713_send_command(struct si4713_device *sdev, const u8 command,
> +                               const u8 args[], const int argn,
> +                               u8 response[], const int respn, const int usecs)
> +{
> +       struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
> +       u8 data1[MAX_ARGS + 1];
> +       int err;
> +
> +       if (!client->adapter)
> +               return -ENODEV;
> +
> +       /* First send the command and its arguments */
> +       data1[0] = command;
> +       memcpy(data1 + 1, args, argn);
> +       DBG_BUFFER(&sdev->sd, "Parameters", data1, argn + 1);
> +
> +       err = i2c_master_send(client, data1, argn + 1);
> +       if (err != argn + 1) {
> +               v4l2_err(&sdev->sd, "Error while sending command 0x%02x\n",
> +                       command);
> +               return (err > 0) ? -EIO : err;
> +       }
> +
> +       /* Wait response from interrupt */
> +       if (!wait_for_completion_timeout(&sdev->work,
> +                               usecs_to_jiffies(usecs) + 1))
> +               v4l2_warn(&sdev->sd,
> +                               "(%s) Device took too much time to answer.\n",
> +                               __func__);
> +
> +       /* Then get the response */
> +       err = i2c_master_recv(client, response, respn);
> +       if (err != respn) {
> +               v4l2_err(&sdev->sd,
> +                       "Error while reading response for command 0x%02x\n",
> +                       command);
> +               return (err > 0) ? -EIO : err;
> +       }
> +
> +       DBG_BUFFER(&sdev->sd, "Response", response, respn);
> +       if (check_command_failed(response[0]))
> +               return -EBUSY;
> +
> +       return 0;
> +}
> +
> +/*
> + * si4713_read_property - reads a si4713 property
> + * @sdev: si4713_device structure for the device we are communicating
> + * @prop: property identification number
> + * @pv: property value to be returned on success
> + */
> +static int si4713_read_property(struct si4713_device *sdev, u16 prop, u32 *pv)
> +{
> +       int err;
> +       u8 val[SI4713_GET_PROP_NRESP];
> +       /*
> +        *      .First byte = 0
> +        *      .Second byte = property's MSB
> +        *      .Third byte = property's LSB
> +        */
> +       const u8 args[SI4713_GET_PROP_NARGS] = {
> +               0x00,
> +               msb(prop),
> +               lsb(prop),
> +       };
> +
> +       err = si4713_send_command(sdev, SI4713_CMD_GET_PROPERTY,
> +                                 args, ARRAY_SIZE(args), val,
> +                                 ARRAY_SIZE(val), DEFAULT_TIMEOUT);
> +
> +       if (err < 0)
> +               return err;
> +
> +       *pv = compose_u16(val[2], val[3]);
> +
> +       v4l2_dbg(1, debug, &sdev->sd,
> +                       "%s: property=0x%02x value=0x%02x status=0x%02x\n",
> +                       __func__, prop, *pv, val[0]);
> +
> +       return err;
> +}
> +
> +/*
> + * si4713_write_property - modifies a si4713 property
> + * @sdev: si4713_device structure for the device we are communicating
> + * @prop: property identification number
> + * @val: new value for that property
> + */
> +static int si4713_write_property(struct si4713_device *sdev, u16 prop, u16 val)
> +{
> +       int rval;
> +       u8 resp[SI4713_SET_PROP_NRESP];
> +       /*
> +        *      .First byte = 0
> +        *      .Second byte = property's MSB
> +        *      .Third byte = property's LSB
> +        *      .Fourth byte = value's MSB
> +        *      .Fifth byte = value's LSB
> +        */
> +       const u8 args[SI4713_SET_PROP_NARGS] = {
> +               0x00,
> +               msb(prop),
> +               lsb(prop),
> +               msb(val),
> +               lsb(val),
> +       };
> +
> +       rval = si4713_send_command(sdev, SI4713_CMD_SET_PROPERTY,
> +                                       args, ARRAY_SIZE(args),
> +                                       resp, ARRAY_SIZE(resp),
> +                                       DEFAULT_TIMEOUT);
> +
> +       if (rval < 0)
> +               return rval;
> +
> +       v4l2_dbg(1, debug, &sdev->sd,
> +                       "%s: property=0x%02x value=0x%02x status=0x%02x\n",
> +                       __func__, prop, val, resp[0]);
> +
> +       /*
> +        * As there is no command response for SET_PROPERTY,
> +        * wait Tcomp time to finish before proceed, in order
> +        * to have property properly set.
> +        */
> +       msleep(TIMEOUT_SET_PROPERTY);
> +
> +       return rval;
> +}
> +
> +/*
> + * si4713_powerup - Powers the device up
> + * @sdev: si4713_device structure for the device we are communicating
> + */
> +static int si4713_powerup(struct si4713_device *sdev)
> +{
> +       int err;
> +       u8 resp[SI4713_PWUP_NRESP];
> +       /*
> +        *      .First byte = Enabled interrupts and boot function
> +        *      .Second byte = Input operation mode
> +        */
> +       const u8 args[SI4713_PWUP_NARGS] = {
> +               SI4713_PWUP_CTSIEN | SI4713_PWUP_GPO2OEN | SI4713_PWUP_FUNC_TX,
> +               SI4713_PWUP_OPMOD_ANALOG,
> +       };
> +
> +       if (sdev->power_state)
> +               return 0;
> +
> +       err = regulator_bulk_enable(ARRAY_SIZE(sdev->supplies),
> +                                   sdev->supplies);
> +       if (err) {
> +               v4l2_err(&sdev->sd, "Failed to enable supplies: %d\n", err);
> +               return err;
> +       }
> +       if (gpio_is_valid(sdev->gpio_reset)) {
> +               udelay(50);
> +               gpio_set_value(sdev->gpio_reset, 1);
> +       }
> +
> +       err = si4713_send_command(sdev, SI4713_CMD_POWER_UP,
> +                                       args, ARRAY_SIZE(args),
> +                                       resp, ARRAY_SIZE(resp),
> +                                       TIMEOUT_POWER_UP);
> +
> +       if (!err) {
> +               v4l2_dbg(1, debug, &sdev->sd, "Powerup response: 0x%02x\n",
> +                               resp[0]);
> +               v4l2_dbg(1, debug, &sdev->sd, "Device in power up mode\n");
> +               sdev->power_state = POWER_ON;
> +
> +               err = si4713_write_property(sdev, SI4713_GPO_IEN,
> +                                               SI4713_STC_INT | SI4713_CTS);
> +       } else {
> +               if (gpio_is_valid(sdev->gpio_reset))
> +                       gpio_set_value(sdev->gpio_reset, 0);
> +               err = regulator_bulk_disable(ARRAY_SIZE(sdev->supplies),
> +                                            sdev->supplies);
> +               if (err)
> +                       v4l2_err(&sdev->sd,
> +                                "Failed to disable supplies: %d\n", err);
> +       }
> +
> +       return err;
> +}
> +
> +/*
> + * si4713_powerdown - Powers the device down
> + * @sdev: si4713_device structure for the device we are communicating
> + */
> +static int si4713_powerdown(struct si4713_device *sdev)
> +{
> +       int err;
> +       u8 resp[SI4713_PWDN_NRESP];
> +
> +       if (!sdev->power_state)
> +               return 0;
> +
> +       err = si4713_send_command(sdev, SI4713_CMD_POWER_DOWN,
> +                                       NULL, 0,
> +                                       resp, ARRAY_SIZE(resp),
> +                                       DEFAULT_TIMEOUT);
> +
> +       if (!err) {
> +               v4l2_dbg(1, debug, &sdev->sd, "Power down response: 0x%02x\n",
> +                               resp[0]);
> +               v4l2_dbg(1, debug, &sdev->sd, "Device in reset mode\n");
> +               if (gpio_is_valid(sdev->gpio_reset))
> +                       gpio_set_value(sdev->gpio_reset, 0);
> +               err = regulator_bulk_disable(ARRAY_SIZE(sdev->supplies),
> +                                            sdev->supplies);
> +               if (err)
> +                       v4l2_err(&sdev->sd,
> +                                "Failed to disable supplies: %d\n", err);
> +               sdev->power_state = POWER_OFF;
> +       }
> +
> +       return err;
> +}
> +
> +/*
> + * si4713_checkrev - Checks if we are treating a device with the correct rev.
> + * @sdev: si4713_device structure for the device we are communicating
> + */
> +static int si4713_checkrev(struct si4713_device *sdev)
> +{
> +       struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
> +       int rval;
> +       u8 resp[SI4713_GETREV_NRESP];
> +
> +       rval = si4713_send_command(sdev, SI4713_CMD_GET_REV,
> +                                       NULL, 0,
> +                                       resp, ARRAY_SIZE(resp),
> +                                       DEFAULT_TIMEOUT);
> +
> +       if (rval < 0)
> +               return rval;
> +
> +       if (resp[1] == SI4713_PRODUCT_NUMBER) {
> +               v4l2_info(&sdev->sd, "chip found @ 0x%02x (%s)\n",
> +                               client->addr << 1, client->adapter->name);
> +       } else {
> +               v4l2_err(&sdev->sd, "Invalid product number\n");
> +               rval = -EINVAL;
> +       }
> +       return rval;
> +}
> +
> +/*
> + * si4713_wait_stc - Waits STC interrupt and clears status bits. Useful
> + *                  for TX_TUNE_POWER, TX_TUNE_FREQ and TX_TUNE_MEAS
> + * @sdev: si4713_device structure for the device we are communicating
> + * @usecs: timeout to wait for STC interrupt signal
> + */
> +static int si4713_wait_stc(struct si4713_device *sdev, const int usecs)
> +{
> +       int err;
> +       u8 resp[SI4713_GET_STATUS_NRESP];
> +
> +       /* Wait response from STC interrupt */
> +       if (!wait_for_completion_timeout(&sdev->work,
> +                       usecs_to_jiffies(usecs) + 1))
> +               v4l2_warn(&sdev->sd,
> +                       "%s: device took too much time to answer (%d usec).\n",
> +                               __func__, usecs);
> +
> +       /* Clear status bits */
> +       err = si4713_send_command(sdev, SI4713_CMD_GET_INT_STATUS,
> +                                       NULL, 0,
> +                                       resp, ARRAY_SIZE(resp),
> +                                       DEFAULT_TIMEOUT);
> +
> +       if (err < 0)
> +               goto exit;
> +
> +       v4l2_dbg(1, debug, &sdev->sd,
> +                       "%s: status bits: 0x%02x\n", __func__, resp[0]);
> +
> +       if (!(resp[0] & SI4713_STC_INT))
> +               err = -EIO;
> +
> +exit:
> +       return err;
> +}
> +
> +/*
> + * si4713_tx_tune_freq - Sets the state of the RF carrier and sets the tuning
> + *                     frequency between 76 and 108 MHz in 10 kHz units and
> + *                     steps of 50 kHz.
> + * @sdev: si4713_device structure for the device we are communicating
> + * @frequency: desired frequency (76 - 108 MHz, unit 10 KHz, step 50 kHz)
> + */
> +static int si4713_tx_tune_freq(struct si4713_device *sdev, u16 frequency)
> +{
> +       int err;
> +       u8 val[SI4713_TXFREQ_NRESP];
> +       /*
> +        *      .First byte = 0
> +        *      .Second byte = frequency's MSB
> +        *      .Third byte = frequency's LSB
> +        */
> +       const u8 args[SI4713_TXFREQ_NARGS] = {
> +               0x00,
> +               msb(frequency),
> +               lsb(frequency),
> +       };
> +
> +       err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_FREQ,
> +                                 args, ARRAY_SIZE(args), val,
> +                                 ARRAY_SIZE(val), DEFAULT_TIMEOUT);
> +
> +       if (err < 0)
> +               return err;
> +
> +       v4l2_dbg(1, debug, &sdev->sd,
> +                       "%s: frequency=0x%02x status=0x%02x\n", __func__,
> +                       frequency, val[0]);
> +
> +       err = si4713_wait_stc(sdev, TIMEOUT_TX_TUNE);
> +       if (err < 0)
> +               return err;
> +
> +       return compose_u16(args[1], args[2]);
> +}
> +
> +/*
> + * si4713_tx_tune_power - Sets the RF voltage level between 88 and 115 dBuV in
> + *                     1 dB units. A value of 0x00 indicates off. The command
> + *                     also sets the antenna tuning capacitance. A value of 0
> + *                     indicates autotuning, and a value of 1 - 191 indicates
> + *                     a manual override, which results in a tuning
> + *                     capacitance of 0.25 pF x @antcap.
> + * @sdev: si4713_device structure for the device we are communicating
> + * @power: tuning power (88 - 115 dBuV, unit/step 1 dB)
> + * @antcap: value of antenna tuning capacitor (0 - 191)
> + */
> +static int si4713_tx_tune_power(struct si4713_device *sdev, u8 power,
> +                               u8 antcap)
> +{
> +       int err;
> +       u8 val[SI4713_TXPWR_NRESP];
> +       /*
> +        *      .First byte = 0
> +        *      .Second byte = 0
> +        *      .Third byte = power
> +        *      .Fourth byte = antcap
> +        */
> +       const u8 args[SI4713_TXPWR_NARGS] = {
> +               0x00,
> +               0x00,
> +               power,
> +               antcap,
> +       };
> +
> +       if (((power > 0) && (power < SI4713_MIN_POWER)) ||
> +               power > SI4713_MAX_POWER || antcap > SI4713_MAX_ANTCAP)
> +               return -EDOM;
> +
> +       err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_POWER,
> +                                 args, ARRAY_SIZE(args), val,
> +                                 ARRAY_SIZE(val), DEFAULT_TIMEOUT);
> +
> +       if (err < 0)
> +               return err;
> +
> +       v4l2_dbg(1, debug, &sdev->sd,
> +                       "%s: power=0x%02x antcap=0x%02x status=0x%02x\n",
> +                       __func__, power, antcap, val[0]);
> +
> +       return si4713_wait_stc(sdev, TIMEOUT_TX_TUNE_POWER);
> +}
> +
> +/*
> + * si4713_tx_tune_measure - Enters receive mode and measures the received noise
> + *                     level in units of dBuV on the selected frequency.
> + *                     The Frequency must be between 76 and 108 MHz in 10 kHz
> + *                     units and steps of 50 kHz. The command also sets the
> + *                     antenna tuning capacitance. A value of 0 means
> + *                     autotuning, and a value of 1 to 191 indicates manual
> + *                     override.
> + * @sdev: si4713_device structure for the device we are communicating
> + * @frequency: desired frequency (76 - 108 MHz, unit 10 KHz, step 50 kHz)
> + * @antcap: value of antenna tuning capacitor (0 - 191)
> + */
> +static int si4713_tx_tune_measure(struct si4713_device *sdev, u16 frequency,
> +                                       u8 antcap)
> +{
> +       int err;
> +       u8 val[SI4713_TXMEA_NRESP];
> +       /*
> +        *      .First byte = 0
> +        *      .Second byte = frequency's MSB
> +        *      .Third byte = frequency's LSB
> +        *      .Fourth byte = antcap
> +        */
> +       const u8 args[SI4713_TXMEA_NARGS] = {
> +               0x00,
> +               msb(frequency),
> +               lsb(frequency),
> +               antcap,
> +       };
> +
> +       sdev->tune_rnl = DEFAULT_TUNE_RNL;
> +
> +       if (antcap > SI4713_MAX_ANTCAP)
> +               return -EDOM;
> +
> +       err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_MEASURE,
> +                                 args, ARRAY_SIZE(args), val,
> +                                 ARRAY_SIZE(val), DEFAULT_TIMEOUT);
> +
> +       if (err < 0)
> +               return err;
> +
> +       v4l2_dbg(1, debug, &sdev->sd,
> +                       "%s: frequency=0x%02x antcap=0x%02x status=0x%02x\n",
> +                       __func__, frequency, antcap, val[0]);
> +
> +       return si4713_wait_stc(sdev, TIMEOUT_TX_TUNE);
> +}
> +
> +/*
> + * si4713_tx_tune_status- Returns the status of the tx_tune_freq, tx_tune_mea or
> + *                     tx_tune_power commands. This command return the current
> + *                     frequency, output voltage in dBuV, the antenna tunning
> + *                     capacitance value and the received noise level. The
> + *                     command also clears the stcint interrupt bit when the
> + *                     first bit of its arguments is high.
> + * @sdev: si4713_device structure for the device we are communicating
> + * @intack: 0x01 to clear the seek/tune complete interrupt status indicator.
> + * @frequency: returned frequency
> + * @power: returned power
> + * @antcap: returned antenna capacitance
> + * @noise: returned noise level
> + */
> +static int si4713_tx_tune_status(struct si4713_device *sdev, u8 intack,
> +                                       u16 *frequency, u8 *power,
> +                                       u8 *antcap, u8 *noise)
> +{
> +       int err;
> +       u8 val[SI4713_TXSTATUS_NRESP];
> +       /*
> +        *      .First byte = intack bit
> +        */
> +       const u8 args[SI4713_TXSTATUS_NARGS] = {
> +               intack & SI4713_INTACK_MASK,
> +       };
> +
> +       err = si4713_send_command(sdev, SI4713_CMD_TX_TUNE_STATUS,
> +                                 args, ARRAY_SIZE(args), val,
> +                                 ARRAY_SIZE(val), DEFAULT_TIMEOUT);
> +
> +       if (!err) {
> +               v4l2_dbg(1, debug, &sdev->sd,
> +                       "%s: status=0x%02x\n", __func__, val[0]);
> +               *frequency = compose_u16(val[2], val[3]);
> +               sdev->frequency = *frequency;
> +               *power = val[5];
> +               *antcap = val[6];
> +               *noise = val[7];
> +               v4l2_dbg(1, debug, &sdev->sd, "%s: response: %d x 10 kHz "
> +                               "(power %d, antcap %d, rnl %d)\n", __func__,
> +                               *frequency, *power, *antcap, *noise);
> +       }
> +
> +       return err;
> +}
> +
> +/*
> + * si4713_tx_rds_buff - Loads the RDS group buffer FIFO or circular buffer.
> + * @sdev: si4713_device structure for the device we are communicating
> + * @mode: the buffer operation mode.
> + * @rdsb: RDS Block B
> + * @rdsc: RDS Block C
> + * @rdsd: RDS Block D
> + * @cbleft: returns the number of available circular buffer blocks minus the
> + *          number of used circular buffer blocks.
> + */
> +static int si4713_tx_rds_buff(struct si4713_device *sdev, u8 mode, u16 rdsb,
> +                               u16 rdsc, u16 rdsd, s8 *cbleft)
> +{
> +       int err;
> +       u8 val[SI4713_RDSBUFF_NRESP];
> +
> +       const u8 args[SI4713_RDSBUFF_NARGS] = {
> +               mode & SI4713_RDSBUFF_MODE_MASK,
> +               msb(rdsb),
> +               lsb(rdsb),
> +               msb(rdsc),
> +               lsb(rdsc),
> +               msb(rdsd),
> +               lsb(rdsd),
> +       };
> +
> +       err = si4713_send_command(sdev, SI4713_CMD_TX_RDS_BUFF,
> +                                 args, ARRAY_SIZE(args), val,
> +                                 ARRAY_SIZE(val), DEFAULT_TIMEOUT);
> +
> +       if (!err) {
> +               v4l2_dbg(1, debug, &sdev->sd,
> +                       "%s: status=0x%02x\n", __func__, val[0]);
> +               *cbleft = (s8)val[2] - val[3];
> +               v4l2_dbg(1, debug, &sdev->sd, "%s: response: interrupts"
> +                               " 0x%02x cb avail: %d cb used %d fifo avail"
> +                               " %d fifo used %d\n", __func__, val[1],
> +                               val[2], val[3], val[4], val[5]);
> +       }
> +
> +       return err;
> +}
> +
> +/*
> + * si4713_tx_rds_ps - Loads the program service buffer.
> + * @sdev: si4713_device structure for the device we are communicating
> + * @psid: program service id to be loaded.
> + * @pschar: assumed 4 size char array to be loaded into the program service
> + */
> +static int si4713_tx_rds_ps(struct si4713_device *sdev, u8 psid,
> +                               unsigned char *pschar)
> +{
> +       int err;
> +       u8 val[SI4713_RDSPS_NRESP];
> +
> +       const u8 args[SI4713_RDSPS_NARGS] = {
> +               psid & SI4713_RDSPS_PSID_MASK,
> +               pschar[0],
> +               pschar[1],
> +               pschar[2],
> +               pschar[3],
> +       };
> +
> +       err = si4713_send_command(sdev, SI4713_CMD_TX_RDS_PS,
> +                                 args, ARRAY_SIZE(args), val,
> +                                 ARRAY_SIZE(val), DEFAULT_TIMEOUT);
> +
> +       if (err < 0)
> +               return err;
> +
> +       v4l2_dbg(1, debug, &sdev->sd, "%s: status=0x%02x\n", __func__, val[0]);
> +
> +       return err;
> +}
> +
> +static int si4713_set_power_state(struct si4713_device *sdev, u8 value)
> +{
> +       if (value)
> +               return si4713_powerup(sdev);
> +       return si4713_powerdown(sdev);
> +}
> +
> +static int si4713_set_mute(struct si4713_device *sdev, u16 mute)
> +{
> +       int rval = 0;
> +
> +       mute = set_mute(mute);
> +
> +       if (sdev->power_state)
> +               rval = si4713_write_property(sdev,
> +                               SI4713_TX_LINE_INPUT_MUTE, mute);
> +
> +       return rval;
> +}
> +
> +static int si4713_set_rds_ps_name(struct si4713_device *sdev, char *ps_name)
> +{
> +       int rval = 0, i;
> +       u8 len = 0;
> +
> +       /* We want to clear the whole thing */
> +       if (!strlen(ps_name))
> +               memset(ps_name, 0, MAX_RDS_PS_NAME + 1);
> +
> +       if (sdev->power_state) {
> +               /* Write the new ps name and clear the padding */
> +               for (i = 0; i < MAX_RDS_PS_NAME; i += (RDS_BLOCK / 2)) {
> +                       rval = si4713_tx_rds_ps(sdev, (i / (RDS_BLOCK / 2)),
> +                                               ps_name + i);
> +                       if (rval < 0)
> +                               return rval;
> +               }
> +
> +               /* Setup the size to be sent */
> +               if (strlen(ps_name))
> +                       len = strlen(ps_name) - 1;
> +               else
> +                       len = 1;
> +
> +               rval = si4713_write_property(sdev,
> +                               SI4713_TX_RDS_PS_MESSAGE_COUNT,
> +                               rds_ps_nblocks(len));
> +               if (rval < 0)
> +                       return rval;
> +
> +               rval = si4713_write_property(sdev,
> +                               SI4713_TX_RDS_PS_REPEAT_COUNT,
> +                               DEFAULT_RDS_PS_REPEAT_COUNT * 2);
> +               if (rval < 0)
> +                       return rval;
> +       }
> +
> +       return rval;
> +}
> +
> +static int si4713_set_rds_radio_text(struct si4713_device *sdev, char *rt)
> +{
> +       int rval = 0, i;
> +       u16 t_index = 0;
> +       u8 b_index = 0, cr_inserted = 0;
> +       s8 left;
> +
> +       if (!sdev->power_state)
> +               return rval;
> +
> +       rval = si4713_tx_rds_buff(sdev, RDS_BLOCK_CLEAR, 0, 0, 0, &left);
> +       if (rval < 0)
> +               return rval;
> +
> +       if (!strlen(rt))
> +               return rval;
> +
> +       do {
> +               /* RDS spec says that if the last block isn't used,
> +                * then apply a carriage return
> +                */
> +               if (t_index < (RDS_RADIOTEXT_INDEX_MAX * RDS_RADIOTEXT_BLK_SIZE)) {
> +                       for (i = 0; i < RDS_RADIOTEXT_BLK_SIZE; i++) {
> +                               if (!rt[t_index + i] ||
> +                                   rt[t_index + i] == RDS_CARRIAGE_RETURN) {
> +                                       rt[t_index + i] = RDS_CARRIAGE_RETURN;
> +                                       cr_inserted = 1;
> +                                       break;
> +                               }
> +                       }
> +               }
> +
> +               rval = si4713_tx_rds_buff(sdev, RDS_BLOCK_LOAD,
> +                               compose_u16(RDS_RADIOTEXT_2A, b_index++),
> +                               compose_u16(rt[t_index], rt[t_index + 1]),
> +                               compose_u16(rt[t_index + 2], rt[t_index + 3]),
> +                               &left);
> +               if (rval < 0)
> +                       return rval;
> +
> +               t_index += RDS_RADIOTEXT_BLK_SIZE;
> +
> +               if (cr_inserted)
> +                       break;
> +       } while (left > 0);
> +
> +       return rval;
> +}
> +
> +/*
> + * si4713_update_tune_status - update properties from tx_tune_status
> + * command. Must be called with sdev->mutex held.
> + * @sdev: si4713_device structure for the device we are communicating
> + */
> +static int si4713_update_tune_status(struct si4713_device *sdev)
> +{
> +       int rval;
> +       u16 f = 0;
> +       u8 p = 0, a = 0, n = 0;
> +
> +       rval = si4713_tx_tune_status(sdev, 0x00, &f, &p, &a, &n);
> +
> +       if (rval < 0)
> +               goto exit;
> +
> +/*     TODO: check that power_level and antenna_capacitor really are not
> +       changed by the hardware. If they are, then these controls should become
> +       volatiles.
> +       sdev->power_level = p;
> +       sdev->antenna_capacitor = a;*/
> +       sdev->tune_rnl = n;
> +
> +exit:
> +       return rval;
> +}
> +
> +static int si4713_choose_econtrol_action(struct si4713_device *sdev, u32 id,
> +               s32 *bit, s32 *mask, u16 *property, int *mul,
> +               unsigned long **table, int *size)
> +{
> +       s32 rval = 0;
> +
> +       switch (id) {
> +       /* FM_TX class controls */
> +       case V4L2_CID_RDS_TX_PI:
> +               *property = SI4713_TX_RDS_PI;
> +               *mul = 1;
> +               break;
> +       case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD:
> +               *property = SI4713_TX_ACOMP_THRESHOLD;
> +               *mul = 1;
> +               break;
> +       case V4L2_CID_AUDIO_COMPRESSION_GAIN:
> +               *property = SI4713_TX_ACOMP_GAIN;
> +               *mul = 1;
> +               break;
> +       case V4L2_CID_PILOT_TONE_FREQUENCY:
> +               *property = SI4713_TX_PILOT_FREQUENCY;
> +               *mul = 1;
> +               break;
> +       case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME:
> +               *property = SI4713_TX_ACOMP_ATTACK_TIME;
> +               *mul = ATTACK_TIME_UNIT;
> +               break;
> +       case V4L2_CID_PILOT_TONE_DEVIATION:
> +               *property = SI4713_TX_PILOT_DEVIATION;
> +               *mul = 10;
> +               break;
> +       case V4L2_CID_AUDIO_LIMITER_DEVIATION:
> +               *property = SI4713_TX_AUDIO_DEVIATION;
> +               *mul = 10;
> +               break;
> +       case V4L2_CID_RDS_TX_DEVIATION:
> +               *property = SI4713_TX_RDS_DEVIATION;
> +               *mul = 1;
> +               break;
> +
> +       case V4L2_CID_RDS_TX_PTY:
> +               *property = SI4713_TX_RDS_PS_MISC;
> +               *bit = 5;
> +               *mask = 0x1F << 5;
> +               break;
> +       case V4L2_CID_AUDIO_LIMITER_ENABLED:
> +               *property = SI4713_TX_ACOMP_ENABLE;
> +               *bit = 1;
> +               *mask = 1 << 1;
> +               break;
> +       case V4L2_CID_AUDIO_COMPRESSION_ENABLED:
> +               *property = SI4713_TX_ACOMP_ENABLE;
> +               *bit = 0;
> +               *mask = 1 << 0;
> +               break;
> +       case V4L2_CID_PILOT_TONE_ENABLED:
> +               *property = SI4713_TX_COMPONENT_ENABLE;
> +               *bit = 0;
> +               *mask = 1 << 0;
> +               break;
> +
> +       case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME:
> +               *property = SI4713_TX_LIMITER_RELEASE_TIME;
> +               *table = limiter_times;
> +               *size = ARRAY_SIZE(limiter_times);
> +               break;
> +       case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME:
> +               *property = SI4713_TX_ACOMP_RELEASE_TIME;
> +               *table = acomp_rtimes;
> +               *size = ARRAY_SIZE(acomp_rtimes);
> +               break;
> +       case V4L2_CID_TUNE_PREEMPHASIS:
> +               *property = SI4713_TX_PREEMPHASIS;
> +               *table = preemphasis_values;
> +               *size = ARRAY_SIZE(preemphasis_values);
> +               break;
> +
> +       default:
> +               rval = -EINVAL;
> +               break;
> +       }
> +
> +       return rval;
> +}
> +
> +static int si4713_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *f);
> +static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulator *);
> +/*
> + * si4713_setup - Sets the device up with current configuration.
> + * @sdev: si4713_device structure for the device we are communicating
> + */
> +static int si4713_setup(struct si4713_device *sdev)
> +{
> +       struct v4l2_frequency f;
> +       struct v4l2_modulator vm;
> +       int rval;
> +
> +       /* Device procedure needs to set frequency first */
> +       f.tuner = 0;
> +       f.frequency = sdev->frequency ? sdev->frequency : DEFAULT_FREQUENCY;
> +       f.frequency = si4713_to_v4l2(f.frequency);
> +       rval = si4713_s_frequency(&sdev->sd, &f);
> +
> +       vm.index = 0;
> +       if (sdev->stereo)
> +               vm.txsubchans = V4L2_TUNER_SUB_STEREO;
> +       else
> +               vm.txsubchans = V4L2_TUNER_SUB_MONO;
> +       if (sdev->rds_enabled)
> +               vm.txsubchans |= V4L2_TUNER_SUB_RDS;
> +       si4713_s_modulator(&sdev->sd, &vm);
> +
> +       return rval;
> +}
> +
> +/*
> + * si4713_initialize - Sets the device up with default configuration.
> + * @sdev: si4713_device structure for the device we are communicating
> + */
> +static int si4713_initialize(struct si4713_device *sdev)
> +{
> +       int rval;
> +
> +       rval = si4713_set_power_state(sdev, POWER_ON);
> +       if (rval < 0)
> +               return rval;
> +
> +       rval = si4713_checkrev(sdev);
> +       if (rval < 0)
> +               return rval;
> +
> +       rval = si4713_set_power_state(sdev, POWER_OFF);
> +       if (rval < 0)
> +               return rval;
> +
> +
> +       sdev->frequency = DEFAULT_FREQUENCY;
> +       sdev->stereo = 1;
> +       sdev->tune_rnl = DEFAULT_TUNE_RNL;
> +       return 0;
> +}
> +
> +/* si4713_s_ctrl - set the value of a control */
> +static int si4713_s_ctrl(struct v4l2_ctrl *ctrl)
> +{
> +       struct si4713_device *sdev =
> +               container_of(ctrl->handler, struct si4713_device, ctrl_handler);
> +       u32 val = 0;
> +       s32 bit = 0, mask = 0;
> +       u16 property = 0;
> +       int mul = 0;
> +       unsigned long *table = NULL;
> +       int size = 0;
> +       bool force = false;
> +       int c;
> +       int ret = 0;
> +
> +       if (ctrl->id != V4L2_CID_AUDIO_MUTE)
> +               return -EINVAL;
> +       if (ctrl->is_new) {
> +               if (ctrl->val) {
> +                       ret = si4713_set_mute(sdev, ctrl->val);
> +                       if (!ret)
> +                               ret = si4713_set_power_state(sdev, POWER_DOWN);
> +                       return ret;
> +               }
> +               ret = si4713_set_power_state(sdev, POWER_UP);
> +               if (!ret)
> +                       ret = si4713_set_mute(sdev, ctrl->val);
> +               if (!ret)
> +                       ret = si4713_setup(sdev);
> +               if (ret)
> +                       return ret;
> +               force = true;
> +       }
> +
> +       if (!sdev->power_state)
> +               return 0;
> +
> +       for (c = 1; !ret && c < ctrl->ncontrols; c++) {
> +               ctrl = ctrl->cluster[c];
> +
> +               if (!force && !ctrl->is_new)
> +                       continue;
> +
> +               switch (ctrl->id) {
> +               case V4L2_CID_RDS_TX_PS_NAME:
> +                       ret = si4713_set_rds_ps_name(sdev, ctrl->string);
> +                       break;
> +
> +               case V4L2_CID_RDS_TX_RADIO_TEXT:
> +                       ret = si4713_set_rds_radio_text(sdev, ctrl->string);
> +                       break;
> +
> +               case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
> +                       /* don't handle this control if we force setting all
> +                        * controls since in that case it will be handled by
> +                        * V4L2_CID_TUNE_POWER_LEVEL. */
> +                       if (force)
> +                               break;
> +                       /* fall through */
> +               case V4L2_CID_TUNE_POWER_LEVEL:
> +                       ret = si4713_tx_tune_power(sdev,
> +                               sdev->tune_pwr_level->val, sdev->tune_ant_cap->val);
> +                       if (!ret) {
> +                               /* Make sure we don't set this twice */
> +                               sdev->tune_ant_cap->is_new = false;
> +                               sdev->tune_pwr_level->is_new = false;
> +                       }
> +                       break;
> +
> +               default:
> +                       ret = si4713_choose_econtrol_action(sdev, ctrl->id, &bit,
> +                                       &mask, &property, &mul, &table, &size);
> +                       if (ret < 0)
> +                               break;
> +
> +                       val = ctrl->val;
> +                       if (mul) {
> +                               val = val / mul;
> +                       } else if (table) {
> +                               ret = usecs_to_dev(val, table, size);
> +                               if (ret < 0)
> +                                       break;
> +                               val = ret;
> +                               ret = 0;
> +                       }
> +
> +                       if (mask) {
> +                               ret = si4713_read_property(sdev, property, &val);
> +                               if (ret < 0)
> +                                       break;
> +                               val = set_bits(val, ctrl->val, bit, mask);
> +                       }
> +
> +                       ret = si4713_write_property(sdev, property, val);
> +                       if (ret < 0)
> +                               break;
> +                       if (mask)
> +                               val = ctrl->val;
> +                       break;
> +               }
> +       }
> +
> +       return ret;
> +}
> +
> +/* si4713_ioctl - deal with private ioctls (only rnl for now) */
> +static long si4713_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
> +{
> +       struct si4713_device *sdev = to_si4713_device(sd);
> +       struct si4713_rnl *rnl = arg;
> +       u16 frequency;
> +       int rval = 0;
> +
> +       if (!arg)
> +               return -EINVAL;
> +
> +       switch (cmd) {
> +       case SI4713_IOC_MEASURE_RNL:
> +               frequency = v4l2_to_si4713(rnl->frequency);
> +
> +               if (sdev->power_state) {
> +                       /* Set desired measurement frequency */
> +                       rval = si4713_tx_tune_measure(sdev, frequency, 0);
> +                       if (rval < 0)
> +                               return rval;
> +                       /* get results from tune status */
> +                       rval = si4713_update_tune_status(sdev);
> +                       if (rval < 0)
> +                               return rval;
> +               }
> +               rnl->rnl = sdev->tune_rnl;
> +               break;
> +
> +       default:
> +               /* nothing */
> +               rval = -ENOIOCTLCMD;
> +       }
> +
> +       return rval;
> +}
> +
> +/* si4713_g_modulator - get modulator attributes */
> +static int si4713_g_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm)
> +{
> +       struct si4713_device *sdev = to_si4713_device(sd);
> +       int rval = 0;
> +
> +       if (!sdev)
> +               return -ENODEV;
> +
> +       if (vm->index > 0)
> +               return -EINVAL;
> +
> +       strncpy(vm->name, "FM Modulator", 32);
> +       vm->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW |
> +               V4L2_TUNER_CAP_RDS | V4L2_TUNER_CAP_RDS_CONTROLS;
> +
> +       /* Report current frequency range limits */
> +       vm->rangelow = si4713_to_v4l2(FREQ_RANGE_LOW);
> +       vm->rangehigh = si4713_to_v4l2(FREQ_RANGE_HIGH);
> +
> +       if (sdev->power_state) {
> +               u32 comp_en = 0;
> +
> +               rval = si4713_read_property(sdev, SI4713_TX_COMPONENT_ENABLE,
> +                                               &comp_en);
> +               if (rval < 0)
> +                       return rval;
> +
> +               sdev->stereo = get_status_bit(comp_en, 1, 1 << 1);
> +       }
> +
> +       /* Report current audio mode: mono or stereo */
> +       if (sdev->stereo)
> +               vm->txsubchans = V4L2_TUNER_SUB_STEREO;
> +       else
> +               vm->txsubchans = V4L2_TUNER_SUB_MONO;
> +
> +       /* Report rds feature status */
> +       if (sdev->rds_enabled)
> +               vm->txsubchans |= V4L2_TUNER_SUB_RDS;
> +       else
> +               vm->txsubchans &= ~V4L2_TUNER_SUB_RDS;
> +
> +       return rval;
> +}
> +
> +/* si4713_s_modulator - set modulator attributes */
> +static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulator *vm)
> +{
> +       struct si4713_device *sdev = to_si4713_device(sd);
> +       int rval = 0;
> +       u16 stereo, rds;
> +       u32 p;
> +
> +       if (!sdev)
> +               return -ENODEV;
> +
> +       if (vm->index > 0)
> +               return -EINVAL;
> +
> +       /* Set audio mode: mono or stereo */
> +       if (vm->txsubchans & V4L2_TUNER_SUB_STEREO)
> +               stereo = 1;
> +       else if (vm->txsubchans & V4L2_TUNER_SUB_MONO)
> +               stereo = 0;
> +       else
> +               return -EINVAL;
> +
> +       rds = !!(vm->txsubchans & V4L2_TUNER_SUB_RDS);
> +
> +       if (sdev->power_state) {
> +               rval = si4713_read_property(sdev,
> +                                               SI4713_TX_COMPONENT_ENABLE, &p);
> +               if (rval < 0)
> +                       return rval;
> +
> +               p = set_bits(p, stereo, 1, 1 << 1);
> +               p = set_bits(p, rds, 2, 1 << 2);
> +
> +               rval = si4713_write_property(sdev,
> +                                               SI4713_TX_COMPONENT_ENABLE, p);
> +               if (rval < 0)
> +                       return rval;
> +       }
> +
> +       sdev->stereo = stereo;
> +       sdev->rds_enabled = rds;
> +
> +       return rval;
> +}
> +
> +/* si4713_g_frequency - get tuner or modulator radio frequency */
> +static int si4713_g_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
> +{
> +       struct si4713_device *sdev = to_si4713_device(sd);
> +       int rval = 0;
> +
> +       if (f->tuner)
> +               return -EINVAL;
> +
> +       if (sdev->power_state) {
> +               u16 freq;
> +               u8 p, a, n;
> +
> +               rval = si4713_tx_tune_status(sdev, 0x00, &freq, &p, &a, &n);
> +               if (rval < 0)
> +                       return rval;
> +
> +               sdev->frequency = freq;
> +       }
> +
> +       f->frequency = si4713_to_v4l2(sdev->frequency);
> +
> +       return rval;
> +}
> +
> +/* si4713_s_frequency - set tuner or modulator radio frequency */
> +static int si4713_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *f)
> +{
> +       struct si4713_device *sdev = to_si4713_device(sd);
> +       int rval = 0;
> +       u16 frequency = v4l2_to_si4713(f->frequency);
> +
> +       if (f->tuner)
> +               return -EINVAL;
> +
> +       /* Check frequency range */
> +       frequency = clamp_t(u16, frequency, FREQ_RANGE_LOW, FREQ_RANGE_HIGH);
> +
> +       if (sdev->power_state) {
> +               rval = si4713_tx_tune_freq(sdev, frequency);
> +               if (rval < 0)
> +                       return rval;
> +               frequency = rval;
> +               rval = 0;
> +       }
> +       sdev->frequency = frequency;
> +
> +       return rval;
> +}
> +
> +static const struct v4l2_ctrl_ops si4713_ctrl_ops = {
> +       .s_ctrl = si4713_s_ctrl,
> +};
> +
> +static const struct v4l2_subdev_core_ops si4713_subdev_core_ops = {
> +       .ioctl          = si4713_ioctl,
> +};
> +
> +static const struct v4l2_subdev_tuner_ops si4713_subdev_tuner_ops = {
> +       .g_frequency    = si4713_g_frequency,
> +       .s_frequency    = si4713_s_frequency,
> +       .g_modulator    = si4713_g_modulator,
> +       .s_modulator    = si4713_s_modulator,
> +};
> +
> +static const struct v4l2_subdev_ops si4713_subdev_ops = {
> +       .core           = &si4713_subdev_core_ops,
> +       .tuner          = &si4713_subdev_tuner_ops,
> +};
> +
> +/*
> + * I2C driver interface
> + */
> +/* si4713_probe - probe for the device */
> +static int si4713_probe(struct i2c_client *client,
> +                                       const struct i2c_device_id *id)
> +{
> +       struct si4713_device *sdev;
> +       struct si4713_platform_data *pdata = client->dev.platform_data;
> +       struct v4l2_ctrl_handler *hdl;
> +       int rval, i;
> +
> +       sdev = kzalloc(sizeof *sdev, GFP_KERNEL);
> +       if (!sdev) {
> +               dev_err(&client->dev, "Failed to alloc video device.\n");
> +               rval = -ENOMEM;
> +               goto exit;
> +       }
> +
> +       sdev->gpio_reset = -1;
> +       if (pdata && gpio_is_valid(pdata->gpio_reset)) {
> +               rval = gpio_request(pdata->gpio_reset, "si4713 reset");
> +               if (rval) {
> +                       dev_err(&client->dev,
> +                               "Failed to request gpio: %d\n", rval);
> +                       goto free_sdev;
> +               }
> +               sdev->gpio_reset = pdata->gpio_reset;
> +               gpio_direction_output(sdev->gpio_reset, 0);
> +       }
> +
> +       for (i = 0; i < ARRAY_SIZE(sdev->supplies); i++)
> +               sdev->supplies[i].supply = si4713_supply_names[i];
> +
> +       rval = regulator_bulk_get(&client->dev, ARRAY_SIZE(sdev->supplies),
> +                                 sdev->supplies);
> +       if (rval) {
> +               dev_err(&client->dev, "Cannot get regulators: %d\n", rval);
> +               goto free_gpio;
> +       }
> +
> +       v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops);
> +
> +       init_completion(&sdev->work);
> +
> +       hdl = &sdev->ctrl_handler;
> +       v4l2_ctrl_handler_init(hdl, 20);
> +       sdev->mute = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> +                       V4L2_CID_AUDIO_MUTE, 0, 1, 1, DEFAULT_MUTE);
> +
> +       sdev->rds_pi = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> +                       V4L2_CID_RDS_TX_PI, 0, 0xffff, 1, DEFAULT_RDS_PI);
> +       sdev->rds_pty = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> +                       V4L2_CID_RDS_TX_PTY, 0, 31, 1, DEFAULT_RDS_PTY);
> +       sdev->rds_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> +                       V4L2_CID_RDS_TX_DEVIATION, 0, MAX_RDS_DEVIATION,
> +                       10, DEFAULT_RDS_DEVIATION);
> +       /*
> +        * Report step as 8. From RDS spec, psname
> +        * should be 8. But there are receivers which scroll strings
> +        * sized as 8xN.
> +        */
> +       sdev->rds_ps_name = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> +                       V4L2_CID_RDS_TX_PS_NAME, 0, MAX_RDS_PS_NAME, 8, 0);
> +       /*
> +        * Report step as 32 (2A block). From RDS spec,
> +        * radio text should be 32 for 2A block. But there are receivers
> +        * which scroll strings sized as 32xN. Setting default to 32.
> +        */
> +       sdev->rds_radio_text = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> +                       V4L2_CID_RDS_TX_RADIO_TEXT, 0, MAX_RDS_RADIO_TEXT, 32, 0);
> +
> +       sdev->limiter_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> +                       V4L2_CID_AUDIO_LIMITER_ENABLED, 0, 1, 1, 1);
> +       sdev->limiter_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> +                       V4L2_CID_AUDIO_LIMITER_RELEASE_TIME, 250,
> +                       MAX_LIMITER_RELEASE_TIME, 10, DEFAULT_LIMITER_RTIME);
> +       sdev->limiter_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> +                       V4L2_CID_AUDIO_LIMITER_DEVIATION, 0,
> +                       MAX_LIMITER_DEVIATION, 10, DEFAULT_LIMITER_DEV);
> +
> +       sdev->compression_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> +                       V4L2_CID_AUDIO_COMPRESSION_ENABLED, 0, 1, 1, 1);
> +       sdev->compression_gain = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> +                       V4L2_CID_AUDIO_COMPRESSION_GAIN, 0, MAX_ACOMP_GAIN, 1,
> +                       DEFAULT_ACOMP_GAIN);
> +       sdev->compression_threshold = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> +                       V4L2_CID_AUDIO_COMPRESSION_THRESHOLD, MIN_ACOMP_THRESHOLD,
> +                       MAX_ACOMP_THRESHOLD, 1,
> +                       DEFAULT_ACOMP_THRESHOLD);
> +       sdev->compression_attack_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> +                       V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME, 0,
> +                       MAX_ACOMP_ATTACK_TIME, 500, DEFAULT_ACOMP_ATIME);
> +       sdev->compression_release_time = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> +                       V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME, 100000,
> +                       MAX_ACOMP_RELEASE_TIME, 100000, DEFAULT_ACOMP_RTIME);
> +
> +       sdev->pilot_tone_enabled = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> +                       V4L2_CID_PILOT_TONE_ENABLED, 0, 1, 1, 1);
> +       sdev->pilot_tone_deviation = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> +                       V4L2_CID_PILOT_TONE_DEVIATION, 0, MAX_PILOT_DEVIATION,
> +                       10, DEFAULT_PILOT_DEVIATION);
> +       sdev->pilot_tone_freq = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> +                       V4L2_CID_PILOT_TONE_FREQUENCY, 0, MAX_PILOT_FREQUENCY,
> +                       1, DEFAULT_PILOT_FREQUENCY);
> +
> +       sdev->tune_preemphasis = v4l2_ctrl_new_std_menu(hdl, &si4713_ctrl_ops,
> +                       V4L2_CID_TUNE_PREEMPHASIS,
> +                       V4L2_PREEMPHASIS_75_uS, 0, V4L2_PREEMPHASIS_50_uS);
> +       sdev->tune_pwr_level = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> +                       V4L2_CID_TUNE_POWER_LEVEL, 0, 120, 1, DEFAULT_POWER_LEVEL);
> +       sdev->tune_ant_cap = v4l2_ctrl_new_std(hdl, &si4713_ctrl_ops,
> +                       V4L2_CID_TUNE_ANTENNA_CAPACITOR, 0, 191, 1, 0);
> +
> +       if (hdl->error) {
> +               rval = hdl->error;
> +               goto free_ctrls;
> +       }
> +       v4l2_ctrl_cluster(20, &sdev->mute);
> +       sdev->sd.ctrl_handler = hdl;
> +
> +       if (client->irq) {
> +               rval = request_irq(client->irq,
> +                       si4713_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED,
> +                       client->name, sdev);
> +               if (rval < 0) {
> +                       v4l2_err(&sdev->sd, "Could not request IRQ\n");
> +                       goto put_reg;
> +               }
> +               v4l2_dbg(1, debug, &sdev->sd, "IRQ requested.\n");
> +       } else {
> +               v4l2_warn(&sdev->sd, "IRQ not configured. Using timeouts.\n");
> +       }
> +
> +       rval = si4713_initialize(sdev);
> +       if (rval < 0) {
> +               v4l2_err(&sdev->sd, "Failed to probe device information.\n");
> +               goto free_irq;
> +       }
> +
> +       return 0;
> +
> +free_irq:
> +       if (client->irq)
> +               free_irq(client->irq, sdev);
> +free_ctrls:
> +       v4l2_ctrl_handler_free(hdl);
> +put_reg:
> +       regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies);
> +free_gpio:
> +       if (gpio_is_valid(sdev->gpio_reset))
> +               gpio_free(sdev->gpio_reset);
> +free_sdev:
> +       kfree(sdev);
> +exit:
> +       return rval;
> +}
> +
> +/* si4713_remove - remove the device */
> +static int si4713_remove(struct i2c_client *client)
> +{
> +       struct v4l2_subdev *sd = i2c_get_clientdata(client);
> +       struct si4713_device *sdev = to_si4713_device(sd);
> +
> +       if (sdev->power_state)
> +               si4713_set_power_state(sdev, POWER_DOWN);
> +
> +       if (client->irq > 0)
> +               free_irq(client->irq, sdev);
> +
> +       v4l2_device_unregister_subdev(sd);
> +       v4l2_ctrl_handler_free(sd->ctrl_handler);
> +       regulator_bulk_free(ARRAY_SIZE(sdev->supplies), sdev->supplies);
> +       if (gpio_is_valid(sdev->gpio_reset))
> +               gpio_free(sdev->gpio_reset);
> +       kfree(sdev);
> +
> +       return 0;
> +}
> +
> +/* si4713_i2c_driver - i2c driver interface */
> +static const struct i2c_device_id si4713_id[] = {
> +       { "si4713" , 0 },
> +       { },
> +};
> +MODULE_DEVICE_TABLE(i2c, si4713_id);
> +
> +static struct i2c_driver si4713_i2c_driver = {
> +       .driver         = {
> +               .name   = "si4713",
> +       },
> +       .probe          = si4713_probe,
> +       .remove         = si4713_remove,
> +       .id_table       = si4713_id,
> +};
> +
> +module_i2c_driver(si4713_i2c_driver);
> diff --git a/drivers/media/radio/si4713/si4713.h b/drivers/media/radio/si4713/si4713.h
> new file mode 100644
> index 0000000..c274e1f
> --- /dev/null
> +++ b/drivers/media/radio/si4713/si4713.h
> @@ -0,0 +1,238 @@
> +/*
> + * drivers/media/radio/si4713.h
> + *
> + * Property and commands definitions for Si4713 radio transmitter chip.
> + *
> + * Copyright (c) 2008 Instituto Nokia de Tecnologia - INdT
> + * Contact: Eduardo Valentin <eduardo.valentin@xxxxxxxxx>
> + *
> + * This file is licensed under the terms of the GNU General Public License
> + * version 2. This program is licensed "as is" without any warranty of any
> + * kind, whether express or implied.
> + *
> + */
> +
> +#ifndef SI4713_I2C_H
> +#define SI4713_I2C_H
> +
> +#include <media/v4l2-subdev.h>
> +#include <media/v4l2-ctrls.h>
> +#include <media/si4713.h>
> +
> +#define SI4713_PRODUCT_NUMBER          0x0D
> +
> +/* Command Timeouts */
> +#define DEFAULT_TIMEOUT                        500
> +#define TIMEOUT_SET_PROPERTY           20
> +#define TIMEOUT_TX_TUNE_POWER          30000
> +#define TIMEOUT_TX_TUNE                        110000
> +#define TIMEOUT_POWER_UP               200000
> +
> +/*
> + * Command and its arguments definitions
> + */
> +#define SI4713_PWUP_CTSIEN             (1<<7)
> +#define SI4713_PWUP_GPO2OEN            (1<<6)
> +#define SI4713_PWUP_PATCH              (1<<5)
> +#define SI4713_PWUP_XOSCEN             (1<<4)
> +#define SI4713_PWUP_FUNC_TX            0x02
> +#define SI4713_PWUP_FUNC_PATCH         0x0F
> +#define SI4713_PWUP_OPMOD_ANALOG       0x50
> +#define SI4713_PWUP_OPMOD_DIGITAL      0x0F
> +#define SI4713_PWUP_NARGS              2
> +#define SI4713_PWUP_NRESP              1
> +#define SI4713_CMD_POWER_UP            0x01
> +
> +#define SI4713_GETREV_NRESP            9
> +#define SI4713_CMD_GET_REV             0x10
> +
> +#define SI4713_PWDN_NRESP              1
> +#define SI4713_CMD_POWER_DOWN          0x11
> +
> +#define SI4713_SET_PROP_NARGS          5
> +#define SI4713_SET_PROP_NRESP          1
> +#define SI4713_CMD_SET_PROPERTY                0x12
> +
> +#define SI4713_GET_PROP_NARGS          3
> +#define SI4713_GET_PROP_NRESP          4
> +#define SI4713_CMD_GET_PROPERTY                0x13
> +
> +#define SI4713_GET_STATUS_NRESP                1
> +#define SI4713_CMD_GET_INT_STATUS      0x14
> +
> +#define SI4713_CMD_PATCH_ARGS          0x15
> +#define SI4713_CMD_PATCH_DATA          0x16
> +
> +#define SI4713_MAX_FREQ                        10800
> +#define SI4713_MIN_FREQ                        7600
> +#define SI4713_TXFREQ_NARGS            3
> +#define SI4713_TXFREQ_NRESP            1
> +#define SI4713_CMD_TX_TUNE_FREQ                0x30
> +
> +#define SI4713_MAX_POWER               120
> +#define SI4713_MIN_POWER               88
> +#define SI4713_MAX_ANTCAP              191
> +#define SI4713_MIN_ANTCAP              0
> +#define SI4713_TXPWR_NARGS             4
> +#define SI4713_TXPWR_NRESP             1
> +#define SI4713_CMD_TX_TUNE_POWER       0x31
> +
> +#define SI4713_TXMEA_NARGS             4
> +#define SI4713_TXMEA_NRESP             1
> +#define SI4713_CMD_TX_TUNE_MEASURE     0x32
> +
> +#define SI4713_INTACK_MASK             0x01
> +#define SI4713_TXSTATUS_NARGS          1
> +#define SI4713_TXSTATUS_NRESP          8
> +#define SI4713_CMD_TX_TUNE_STATUS      0x33
> +
> +#define SI4713_OVERMOD_BIT             (1 << 2)
> +#define SI4713_IALH_BIT                        (1 << 1)
> +#define SI4713_IALL_BIT                        (1 << 0)
> +#define SI4713_ASQSTATUS_NARGS         1
> +#define SI4713_ASQSTATUS_NRESP         5
> +#define SI4713_CMD_TX_ASQ_STATUS       0x34
> +
> +#define SI4713_RDSBUFF_MODE_MASK       0x87
> +#define SI4713_RDSBUFF_NARGS           7
> +#define SI4713_RDSBUFF_NRESP           6
> +#define SI4713_CMD_TX_RDS_BUFF         0x35
> +
> +#define SI4713_RDSPS_PSID_MASK         0x1F
> +#define SI4713_RDSPS_NARGS             5
> +#define SI4713_RDSPS_NRESP             1
> +#define SI4713_CMD_TX_RDS_PS           0x36
> +
> +#define SI4713_CMD_GPO_CTL             0x80
> +#define SI4713_CMD_GPO_SET             0x81
> +
> +/*
> + * Bits from status response
> + */
> +#define SI4713_CTS                     (1<<7)
> +#define SI4713_ERR                     (1<<6)
> +#define SI4713_RDS_INT                 (1<<2)
> +#define SI4713_ASQ_INT                 (1<<1)
> +#define SI4713_STC_INT                 (1<<0)
> +
> +/*
> + * Property definitions
> + */
> +#define SI4713_GPO_IEN                 0x0001
> +#define SI4713_DIG_INPUT_FORMAT                0x0101
> +#define SI4713_DIG_INPUT_SAMPLE_RATE   0x0103
> +#define SI4713_REFCLK_FREQ             0x0201
> +#define SI4713_REFCLK_PRESCALE         0x0202
> +#define SI4713_TX_COMPONENT_ENABLE     0x2100
> +#define SI4713_TX_AUDIO_DEVIATION      0x2101
> +#define SI4713_TX_PILOT_DEVIATION      0x2102
> +#define SI4713_TX_RDS_DEVIATION                0x2103
> +#define SI4713_TX_LINE_INPUT_LEVEL     0x2104
> +#define SI4713_TX_LINE_INPUT_MUTE      0x2105
> +#define SI4713_TX_PREEMPHASIS          0x2106
> +#define SI4713_TX_PILOT_FREQUENCY      0x2107
> +#define SI4713_TX_ACOMP_ENABLE         0x2200
> +#define SI4713_TX_ACOMP_THRESHOLD      0x2201
> +#define SI4713_TX_ACOMP_ATTACK_TIME    0x2202
> +#define SI4713_TX_ACOMP_RELEASE_TIME   0x2203
> +#define SI4713_TX_ACOMP_GAIN           0x2204
> +#define SI4713_TX_LIMITER_RELEASE_TIME 0x2205
> +#define SI4713_TX_ASQ_INTERRUPT_SOURCE 0x2300
> +#define SI4713_TX_ASQ_LEVEL_LOW                0x2301
> +#define SI4713_TX_ASQ_DURATION_LOW     0x2302
> +#define SI4713_TX_ASQ_LEVEL_HIGH       0x2303
> +#define SI4713_TX_ASQ_DURATION_HIGH    0x2304
> +#define SI4713_TX_RDS_INTERRUPT_SOURCE 0x2C00
> +#define SI4713_TX_RDS_PI               0x2C01
> +#define SI4713_TX_RDS_PS_MIX           0x2C02
> +#define SI4713_TX_RDS_PS_MISC          0x2C03
> +#define SI4713_TX_RDS_PS_REPEAT_COUNT  0x2C04
> +#define SI4713_TX_RDS_PS_MESSAGE_COUNT 0x2C05
> +#define SI4713_TX_RDS_PS_AF            0x2C06
> +#define SI4713_TX_RDS_FIFO_SIZE                0x2C07
> +
> +#define PREEMPHASIS_USA                        75
> +#define PREEMPHASIS_EU                 50
> +#define PREEMPHASIS_DISABLED           0
> +#define FMPE_USA                       0x00
> +#define FMPE_EU                                0x01
> +#define FMPE_DISABLED                  0x02
> +
> +#define POWER_UP                       0x01
> +#define POWER_DOWN                     0x00
> +
> +#define MAX_RDS_PTY                    31
> +#define MAX_RDS_DEVIATION              90000
> +
> +/*
> + * PSNAME is known to be defined as 8 character sized (RDS Spec).
> + * However, there is receivers which scroll PSNAME 8xN sized.
> + */
> +#define MAX_RDS_PS_NAME                        96
> +
> +/*
> + * MAX_RDS_RADIO_TEXT is known to be defined as 32 (2A group) or 64 (2B group)
> + * character sized (RDS Spec).
> + * However, there is receivers which scroll them as well.
> + */
> +#define MAX_RDS_RADIO_TEXT             384
> +
> +#define MAX_LIMITER_RELEASE_TIME       102390
> +#define MAX_LIMITER_DEVIATION          90000
> +
> +#define MAX_PILOT_DEVIATION            90000
> +#define MAX_PILOT_FREQUENCY            19000
> +
> +#define MAX_ACOMP_RELEASE_TIME         1000000
> +#define MAX_ACOMP_ATTACK_TIME          5000
> +#define MAX_ACOMP_THRESHOLD            0
> +#define MIN_ACOMP_THRESHOLD            (-40)
> +#define MAX_ACOMP_GAIN                 20
> +
> +#define SI4713_NUM_SUPPLIES            2
> +
> +/*
> + * si4713_device - private data
> + */
> +struct si4713_device {
> +       /* v4l2_subdev and i2c reference (v4l2_subdev priv data) */
> +       struct v4l2_subdev sd;
> +       struct v4l2_ctrl_handler ctrl_handler;
> +       /* private data structures */
> +       struct { /* si4713 control cluster */
> +               /* This is one big cluster since the mute control
> +                * powers off the device and after unmuting again all
> +                * controls need to be set at once. The only way of doing
> +                * that is by making it one big cluster. */
> +               struct v4l2_ctrl *mute;
> +               struct v4l2_ctrl *rds_ps_name;
> +               struct v4l2_ctrl *rds_radio_text;
> +               struct v4l2_ctrl *rds_pi;
> +               struct v4l2_ctrl *rds_deviation;
> +               struct v4l2_ctrl *rds_pty;
> +               struct v4l2_ctrl *compression_enabled;
> +               struct v4l2_ctrl *compression_threshold;
> +               struct v4l2_ctrl *compression_gain;
> +               struct v4l2_ctrl *compression_attack_time;
> +               struct v4l2_ctrl *compression_release_time;
> +               struct v4l2_ctrl *pilot_tone_enabled;
> +               struct v4l2_ctrl *pilot_tone_freq;
> +               struct v4l2_ctrl *pilot_tone_deviation;
> +               struct v4l2_ctrl *limiter_enabled;
> +               struct v4l2_ctrl *limiter_deviation;
> +               struct v4l2_ctrl *limiter_release_time;
> +               struct v4l2_ctrl *tune_preemphasis;
> +               struct v4l2_ctrl *tune_pwr_level;
> +               struct v4l2_ctrl *tune_ant_cap;
> +       };
> +       struct completion work;
> +       struct regulator_bulk_data supplies[SI4713_NUM_SUPPLIES];
> +       int gpio_reset;
> +       u32 power_state;
> +       u32 rds_enabled;
> +       u32 frequency;
> +       u32 preemphasis;
> +       u32 stereo;
> +       u32 tune_rnl;
> +};
> +#endif /* ifndef SI4713_I2C_H */
> --
> 1.8.4.rc2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Eduardo Bezerra Valentin
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux