Hello Jarkko,

On Sun, Jun 13, 2010 at 08:09:28PM +0200, Jarkko Nikula wrote:
> Convert the driver to use regulator framework instead of set_power callback.
> This with gpio_reset platform data provide cleaner way to manage chip VIO,
> VDD and reset signal inside the driver.
> 
> Signed-off-by: Jarkko Nikula <jhnik...@gmail.com>
> Cc: Eduardo Valentin <eduardo.valen...@nokia.com>
> ---
> I don't have specifications for this chip so I don't know how long the
> reset signal must be active after power-up. I used 50 us from Maemo
> kernel sources for Nokia N900 and I can successfully enable-disable
> transmitter on N900 with vdd power cycling.
> ---
>  drivers/media/radio/radio-si4713.c |   20 ++++++++++++++-
>  drivers/media/radio/si4713-i2c.c   |   48 ++++++++++++++++++++++++++++-------
>  drivers/media/radio/si4713-i2c.h   |    3 +-
>  include/media/si4713.h             |    3 +-

Could you please elaborate a bit more on the fact that you have put vio on
the platform driver and vdd on the i2c driver?

>  4 files changed, 60 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/media/radio/radio-si4713.c 
> b/drivers/media/radio/radio-si4713.c
> index 0a9fc4d..c666012 100644
> --- a/drivers/media/radio/radio-si4713.c
> +++ b/drivers/media/radio/radio-si4713.c
> @@ -28,6 +28,7 @@
>  #include <linux/i2c.h>
>  #include <linux/videodev2.h>
>  #include <linux/slab.h>
> +#include <linux/regulator/consumer.h>
>  #include <media/v4l2-device.h>
>  #include <media/v4l2-common.h>
>  #include <media/v4l2-ioctl.h>
> @@ -48,6 +49,7 @@ MODULE_VERSION("0.0.1");
>  struct radio_si4713_device {
>       struct v4l2_device              v4l2_dev;
>       struct video_device             *radio_dev;
> +     struct regulator                *reg_vio;
>  };
>  
>  /* radio_si4713_fops - file operations interface */
> @@ -283,12 +285,22 @@ static int radio_si4713_pdriver_probe(struct 
> platform_device *pdev)
>               goto free_rsdev;
>       }
>  
> +     rsdev->reg_vio = regulator_get(&pdev->dev, "vio");
> +     if (IS_ERR(rsdev->reg_vio)) {
> +             dev_err(&pdev->dev, "Cannot get vio regulator\n");
> +             rval = PTR_ERR(rsdev->reg_vio);
> +             goto unregister_v4l2_dev;
> +     }
> +     rval = regulator_enable(rsdev->reg_vio);
> +     if (rval)
> +             goto reg_put;
> +
>       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;
> +             goto reg_disable;
>       }
>  
>       sd = v4l2_i2c_new_subdev_board(&rsdev->v4l2_dev, adapter, "si4713_i2c",
> @@ -322,6 +334,10 @@ free_vdev:
>       video_device_release(rsdev->radio_dev);
>  put_adapter:
>       i2c_put_adapter(adapter);
> +reg_disable:
> +     regulator_disable(rsdev->reg_vio);
> +reg_put:
> +     regulator_put(rsdev->reg_vio);
>  unregister_v4l2_dev:
>       v4l2_device_unregister(&rsdev->v4l2_dev);
>  free_rsdev:
> @@ -343,6 +359,8 @@ static int __exit radio_si4713_pdriver_remove(struct 
> platform_device *pdev)
>  
>       video_unregister_device(rsdev->radio_dev);
>       i2c_put_adapter(client->adapter);
> +     regulator_disable(rsdev->reg_vio);
> +     regulator_put(rsdev->reg_vio);
>       v4l2_device_unregister(&rsdev->v4l2_dev);
>       kfree(rsdev);
>  
> diff --git a/drivers/media/radio/si4713-i2c.c 
> b/drivers/media/radio/si4713-i2c.c
> index ab63dd5..4b5470c 100644
> --- a/drivers/media/radio/si4713-i2c.c
> +++ b/drivers/media/radio/si4713-i2c.c
> @@ -27,6 +27,8 @@
>  #include <linux/interrupt.h>
>  #include <linux/i2c.h>
>  #include <linux/slab.h>
> +#include <linux/gpio.h>
> +#include <linux/regulator/consumer.h>
>  #include <media/v4l2-device.h>
>  #include <media/v4l2-ioctl.h>
>  #include <media/v4l2-common.h>
> @@ -369,7 +371,12 @@ static int si4713_powerup(struct si4713_device *sdev)
>       if (sdev->power_state)
>               return 0;
>  
> -     sdev->platform_data->set_power(1);
> +     regulator_enable(sdev->reg_vdd);
> +     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),
> @@ -384,7 +391,9 @@ static int si4713_powerup(struct si4713_device *sdev)
>               err = si4713_write_property(sdev, SI4713_GPO_IEN,
>                                               SI4713_STC_INT | SI4713_CTS);
>       } else {
> -             sdev->platform_data->set_power(0);
> +             if (gpio_is_valid(sdev->gpio_reset))
> +                     gpio_set_value(sdev->gpio_reset, 0);
> +             regulator_disable(sdev->reg_vdd);
>       }
>  
>       return err;
> @@ -411,7 +420,9 @@ static int si4713_powerdown(struct si4713_device *sdev)
>               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");
> -             sdev->platform_data->set_power(0);
> +             if (gpio_is_valid(sdev->gpio_reset))
> +                     gpio_set_value(sdev->gpio_reset, 0);
> +             regulator_disable(sdev->reg_vdd);
>               sdev->power_state = POWER_OFF;
>       }
>  
> @@ -1959,6 +1970,7 @@ 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;
>       int rval;
>  
>       sdev = kzalloc(sizeof *sdev, GFP_KERNEL);
> @@ -1968,11 +1980,20 @@ static int si4713_probe(struct i2c_client *client,
>               goto exit;
>       }
>  
> -     sdev->platform_data = client->dev.platform_data;
> -     if (!sdev->platform_data) {
> -             v4l2_err(&sdev->sd, "No platform data registered.\n");
> -             rval = -ENODEV;
> -             goto free_sdev;
> +     sdev->gpio_reset = -1;
> +     if (pdata && gpio_is_valid(pdata->gpio_reset)) {
> +             rval = gpio_request(pdata->gpio_reset, "si4713 reset");
> +             if (rval)
> +                     goto free_sdev;
> +             sdev->gpio_reset = pdata->gpio_reset;
> +             gpio_direction_output(sdev->gpio_reset, 0);
> +     }
> +
> +     sdev->reg_vdd = regulator_get(&client->dev, "vdd");
> +     if (IS_ERR(sdev->reg_vdd)) {
> +             dev_err(&client->dev, "Cannot get vdd regulator\n");
> +             rval = PTR_ERR(sdev->reg_vdd);
> +             goto free_gpio;
>       }
>  
>       v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops);
> @@ -1986,7 +2007,7 @@ static int si4713_probe(struct i2c_client *client,
>                       client->name, sdev);
>               if (rval < 0) {
>                       v4l2_err(&sdev->sd, "Could not request IRQ\n");
> -                     goto free_sdev;
> +                     goto put_reg;
>               }
>               v4l2_dbg(1, debug, &sdev->sd, "IRQ requested.\n");
>       } else {
> @@ -2004,6 +2025,11 @@ static int si4713_probe(struct i2c_client *client,
>  free_irq:
>       if (client->irq)
>               free_irq(client->irq, sdev);
> +put_reg:
> +     regulator_put(sdev->reg_vdd);
> +free_gpio:
> +     if (gpio_is_valid(sdev->gpio_reset))
> +             gpio_free(sdev->gpio_reset);
>  free_sdev:
>       kfree(sdev);
>  exit:
> @@ -2023,7 +2049,9 @@ static int si4713_remove(struct i2c_client *client)
>               free_irq(client->irq, sdev);
>  
>       v4l2_device_unregister_subdev(sd);
> -
> +     regulator_put(sdev->reg_vdd);
> +     if (gpio_is_valid(sdev->gpio_reset))
> +             gpio_free(sdev->gpio_reset);
>       kfree(sdev);
>  
>       return 0;
> diff --git a/drivers/media/radio/si4713-i2c.h 
> b/drivers/media/radio/si4713-i2c.h
> index faf8cff..cf79f6e 100644
> --- a/drivers/media/radio/si4713-i2c.h
> +++ b/drivers/media/radio/si4713-i2c.h
> @@ -220,11 +220,12 @@ struct si4713_device {
>       /* private data structures */
>       struct mutex mutex;
>       struct completion work;
> -     struct si4713_platform_data *platform_data;
>       struct rds_info rds_info;
>       struct limiter_info limiter_info;
>       struct pilot_info pilot_info;
>       struct acomp_info acomp_info;
> +     struct regulator *reg_vdd;
> +     int gpio_reset;
>       u32 frequency;
>       u32 preemphasis;
>       u32 mute;
> diff --git a/include/media/si4713.h b/include/media/si4713.h
> index 99850a5..ed7353e 100644
> --- a/include/media/si4713.h
> +++ b/include/media/si4713.h
> @@ -23,8 +23,7 @@
>   * Platform dependent definition
>   */
>  struct si4713_platform_data {
> -     /* Set power state, zero is off, non-zero is on. */
> -     int (*set_power)(int power);
> +     int gpio_reset; /* < 0 if not used */
>  };
>  
>  /*
> -- 
> 1.7.1

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

Reply via email to