From: Mauro Carvalho Chehab <m.chehab@samsung.com>
To: Hans Verkuil <hverkuil@xs4all.nl>
Cc: linux-media@vger.kernel.org, Dinesh.Ram@cern.ch,
edubezval@gmail.com, Hans Verkuil <hans.verkuil@cisco.com>
Subject: Re: [PATCHv2 02/11] si4713: Modified i2c driver to handle cases where interrupts are not used
Date: Mon, 09 Dec 2013 13:58:00 -0200 [thread overview]
Message-ID: <20131209135800.51421970@samsung.com> (raw)
In-Reply-To: <1386325034-19344-3-git-send-email-hverkuil@xs4all.nl>
Em Fri, 6 Dec 2013 11:17:05 +0100
Hans Verkuil <hverkuil@xs4all.nl> escreveu:
> From: Dinesh Ram <Dinesh.Ram@cern.ch>
>
> 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 <dinesh.ram@cern.ch>
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> Tested-by: Eduardo Valentin <edubezval@gmail.com>
> Acked-by: Eduardo Valentin <edubezval@gmail.com>
> ---
> drivers/media/radio/si4713/si4713.c | 108 +++++++++++++++++++++---------------
> 1 file changed, 64 insertions(+), 44 deletions(-)
>
> diff --git a/drivers/media/radio/si4713/si4713.c b/drivers/media/radio/si4713/si4713.c
> index 4f3308f..5d26b9a 100644
> --- a/drivers/media/radio/si4713/si4713.c
> +++ b/drivers/media/radio/si4713/si4713.c
> @@ -27,11 +27,11 @@
> #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 <linux/regulator/consumer.h>
>
> #include "si4713.h"
>
> @@ -213,6 +213,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 +229,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;
> + }
> +
> + DBG_BUFFER(&sdev->sd, "Response", response, respn);
> + if (!check_command_failed(response[0]))
> + return 0;
>
> - return 0;
> + if (client->irq)
> + return -EBUSY;
> + msleep(1);
> + } while (jiffies <= until_jiffies);
> +
> + return -EBUSY;
> }
>
> /*
> @@ -344,14 +354,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,6 +380,9 @@ 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),
> @@ -380,7 +394,8 @@ static int si4713_powerup(struct si4713_device *sdev)
> 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))
> @@ -465,33 +480,39 @@ 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];
> + unsigned long start_jiffies = jiffies;
> + int err;
>
> - /* Wait response from STC interrupt */
> - if (!wait_for_completion_timeout(&sdev->work,
> - usecs_to_jiffies(usecs) + 1))
> + 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 (%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;
> + "(%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);
> + /* The USB device returns errors when it waits for the
> + * STC bit to be set. Hence polling */
> + 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)
Please use time_is_after_jiffies() here too.
> + return err < 0 ? err : -EIO;
> + /* We sleep here for 3 ms in order to avoid flooding the device
> + * with USB requests. The si4713 USB driver was developed
> + * by reverse engineering the Windows USB driver. The windows
> + * driver also has a ~2.5 ms delay between responses. */
> + msleep(3);
> + }
> }
>
> /*
> @@ -1024,7 +1045,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;
--
Cheers,
Mauro
next prev parent reply other threads:[~2013-12-09 15:58 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-12-06 10:17 [PATCHv2 00/11] si4713: add si4713 usb driver Hans Verkuil
2013-12-06 10:17 ` [PATCHv2 01/11] si4713: Reorganized drivers/media/radio directory Hans Verkuil
2013-12-06 10:17 ` [PATCHv2 02/11] si4713: Modified i2c driver to handle cases where interrupts are not used Hans Verkuil
2013-12-09 15:58 ` Mauro Carvalho Chehab [this message]
2013-12-06 10:17 ` [PATCHv2 03/11] si4713: Reorganized includes in si4713.c/h Hans Verkuil
2013-12-06 10:17 ` [PATCHv2 04/11] si4713: Bug fix for si4713_tx_tune_power() method in the i2c driver Hans Verkuil
2013-12-06 10:17 ` [PATCHv2 05/11] si4713: HID blacklist Si4713 USB development board Hans Verkuil
2013-12-06 10:17 ` [PATCHv2 06/11] si4713: Added the USB driver for Si4713 Hans Verkuil
2013-12-09 15:47 ` Mauro Carvalho Chehab
2013-12-09 16:22 ` Hans Verkuil
2013-12-13 13:26 ` Hans Verkuil
2013-12-06 10:17 ` [PATCHv2 07/11] si4713: Added MAINTAINERS entry for radio-usb-si4713 driver Hans Verkuil
2013-12-06 10:17 ` [PATCHv2 08/11] si4713: move supply list to si4713_platform_data Hans Verkuil
2013-12-06 10:17 ` [PATCHv2 09/11] si4713: si4713_set_rds_radio_text overwrites terminating \0 Hans Verkuil
2013-12-06 10:17 ` [PATCHv2 10/11] si4713: print product number Hans Verkuil
2013-12-06 10:17 ` [PATCHv2 11/11] si4713: coding style cleanups Hans Verkuil
2013-12-06 13:26 ` edubezval
2013-12-09 15:51 ` Mauro Carvalho Chehab
2013-12-09 16:17 ` Hans Verkuil
2013-12-09 18:37 ` Mauro Carvalho Chehab
2013-12-09 15:59 ` [PATCHv2 00/11] si4713: add si4713 usb driver Mauro Carvalho Chehab
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20131209135800.51421970@samsung.com \
--to=m.chehab@samsung.com \
--cc=Dinesh.Ram@cern.ch \
--cc=edubezval@gmail.com \
--cc=hans.verkuil@cisco.com \
--cc=hverkuil@xs4all.nl \
--cc=linux-media@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox