On Fri, Aug 30, 2013 at 7:28 AM, Dinesh Ram <din...@cisco.com> wrote:
> Checks have been introduced at several places in the code to test if an 
> interrupt is set or not.
> For devices which do not use the interrupt, to get a valid response, within a 
> specified timeout,
> the device is polled instead.
>
> Signed-off-by: Dinesh Ram <din...@cisco.com>
> ---
>  drivers/media/radio/si4713/si4713.c | 110 
> ++++++++++++++++++++----------------
>  drivers/media/radio/si4713/si4713.h |   1 +
>  2 files changed, 63 insertions(+), 48 deletions(-)
>
> diff --git a/drivers/media/radio/si4713/si4713.c 
> b/drivers/media/radio/si4713/si4713.c
> index ac727e3..55c4d27 100644
> --- a/drivers/media/radio/si4713/si4713.c
> +++ b/drivers/media/radio/si4713/si4713.c
> @@ -27,7 +27,6 @@
>  #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>
> @@ -213,6 +212,7 @@ static int si4713_send_command(struct si4713_device 
> *sdev, const u8 command,
>                                 u8 response[], const int respn, const int 
> usecs)
>  {
>         struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
> +       unsigned long until_jiffies;
>         u8 data1[MAX_ARGS + 1];
>         int err;
>
> @@ -228,30 +228,39 @@ static int si4713_send_command(struct si4713_device 
> *sdev, const u8 command,
>         if (err != argn + 1) {
>                 v4l2_err(&sdev->sd, "Error while sending command 0x%02x\n",
>                         command);
> -               return (err > 0) ? -EIO : err;
> +               return err < 0 ? err : -EIO;
>         }
>
> +       until_jiffies = jiffies + usecs_to_jiffies(usecs) + 1;
> +
>         /* Wait response from interrupt */
> -       if (!wait_for_completion_timeout(&sdev->work,
> +       if (client->irq) {
> +               if (!wait_for_completion_timeout(&sdev->work,
>                                 usecs_to_jiffies(usecs) + 1))
> -               v4l2_warn(&sdev->sd,
> +                       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;
> +       do {
> +               err = i2c_master_recv(client, response, respn);
> +               if (err != respn) {
> +                       v4l2_err(&sdev->sd,
> +                                       "Error %d while reading response for 
> command 0x%02x\n",
> +                                       err, command);
> +                       return err < 0 ? err : -EIO;
> +               }
>
> -       return 0;
> +               DBG_BUFFER(&sdev->sd, "Response", response, respn);
> +               if (!check_command_failed(response[0]))
> +                       return 0;
> +
> +               if (client->irq)
> +                       return -EBUSY;
> +               msleep(1);
> +       } while (jiffies <= until_jiffies);
> +
> +       return -EBUSY;
>  }
>
>  /*
> @@ -344,14 +353,15 @@ static int si4713_write_property(struct si4713_device 
> *sdev, u16 prop, u16 val)
>   */
>  static int si4713_powerup(struct si4713_device *sdev)
>  {
> +       struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
>         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,
> +       u8 args[SI4713_PWUP_NARGS] = {
> +               SI4713_PWUP_GPO2OEN | SI4713_PWUP_FUNC_TX,
>                 SI4713_PWUP_OPMOD_ANALOG,
>         };
>
> @@ -369,18 +379,22 @@ static int si4713_powerup(struct si4713_device *sdev)
>                 gpio_set_value(sdev->gpio_reset, 1);
>         }
>
> +       if (client->irq)
> +               args[0] |= SI4713_PWUP_CTSIEN;
> +
>         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,
> +               if (client->irq)
> +                       err = si4713_write_property(sdev, SI4713_GPO_IEN,
>                                                 SI4713_STC_INT | SI4713_CTS);
>         } else {
>                 if (gpio_is_valid(sdev->gpio_reset))
> @@ -447,7 +461,7 @@ static int si4713_checkrev(struct si4713_device *sdev)
>         if (rval < 0)
>                 return rval;
>
> -       if (resp[1] == SI4713_PRODUCT_NUMBER) {
> +       if (resp[1] == SI4713_PRODUCT_NUMBER) {
>                 v4l2_info(&sdev->sd, "chip found @ 0x%02x (%s)\n",
>                                 client->addr << 1, client->adapter->name);
>         } else {
> @@ -465,33 +479,34 @@ static int si4713_checkrev(struct si4713_device *sdev)
>   */
>  static int si4713_wait_stc(struct si4713_device *sdev, const int usecs)
>  {
> -       int err;
> +       struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
>         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;
> +       unsigned long start_jiffies = jiffies;
> +       int err;
> +
> +       if (client->irq &&
> +           !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__);
> +
> +       for (;;) {
> +               /* Clear status bits */
> +               err = si4713_send_command(sdev, SI4713_CMD_GET_INT_STATUS,
> +                               NULL, 0,
> +                               resp, ARRAY_SIZE(resp),
> +                               DEFAULT_TIMEOUT);
> +
> +               if (err >= 0) {
> +                       v4l2_dbg(1, debug, &sdev->sd,
> +                                       "%s: status bits: 0x%02x\n", 
> __func__, resp[0]);
> +
> +                       if (resp[0] & SI4713_STC_INT)
> +                               return 0;
> +               }
> +               if (jiffies_to_usecs(jiffies - start_jiffies) > usecs)
> +                       return -EIO;
> +               msleep(3);
> +       }
>  }
>
>  /*
> @@ -1024,7 +1039,6 @@ static int si4713_initialize(struct si4713_device *sdev)
>         if (rval < 0)
>                 return rval;
>
> -
>         sdev->frequency = DEFAULT_FREQUENCY;
>         sdev->stereo = 1;
>         sdev->tune_rnl = DEFAULT_TUNE_RNL;
> diff --git a/drivers/media/radio/si4713/si4713.h 
> b/drivers/media/radio/si4713/si4713.h
> index c274e1f..dc0ce66 100644
> --- a/drivers/media/radio/si4713/si4713.h
> +++ b/drivers/media/radio/si4713/si4713.h
> @@ -15,6 +15,7 @@
>  #ifndef SI4713_I2C_H
>  #define SI4713_I2C_H
>
> +#include <linux/regulator/consumer.h>

Forgot to ask, why do you need to have regulator/consumer.h in this
header to add polling mode to this driver.

>  #include <media/v4l2-subdev.h>
>  #include <media/v4l2-ctrls.h>
>  #include <media/si4713.h>
> --
> 1.8.4.rc2
>
> --
> 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



-- 
Eduardo Bezerra 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