Skip to content

Commit

Permalink
[media] radio-si470x: support seek and tune interrupt enable
Browse files Browse the repository at this point in the history
Currently we use busy waiting to seek and tune, it can replace to
interrupt way. SI470X I2C driver supports interrupt way to week and tune
via this patch.

Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Joonyoung Shim authored and Mauro Carvalho Chehab committed May 20, 2011
1 parent cc73b4b commit 0830be3
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 20 deletions.
60 changes: 42 additions & 18 deletions drivers/media/radio/si470x/radio-si470x-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,15 +174,27 @@ static int si470x_set_chan(struct si470x_device *radio, unsigned short chan)
if (retval < 0)
goto done;

/* wait till tune operation has completed */
timeout = jiffies + msecs_to_jiffies(tune_timeout);
do {
retval = si470x_get_register(radio, STATUSRSSI);
if (retval < 0)
goto stop;
timed_out = time_after(jiffies, timeout);
} while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) &&
(!timed_out));
/* currently I2C driver only uses interrupt way to tune */
if (radio->stci_enabled) {
INIT_COMPLETION(radio->completion);

/* wait till tune operation has completed */
retval = wait_for_completion_timeout(&radio->completion,
msecs_to_jiffies(tune_timeout));
if (!retval)
timed_out = true;
} else {
/* wait till tune operation has completed */
timeout = jiffies + msecs_to_jiffies(tune_timeout);
do {
retval = si470x_get_register(radio, STATUSRSSI);
if (retval < 0)
goto stop;
timed_out = time_after(jiffies, timeout);
} while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
&& (!timed_out));
}

if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
dev_warn(&radio->videodev->dev, "tune does not complete\n");
if (timed_out)
Expand Down Expand Up @@ -310,15 +322,27 @@ static int si470x_set_seek(struct si470x_device *radio,
if (retval < 0)
goto done;

/* wait till seek operation has completed */
timeout = jiffies + msecs_to_jiffies(seek_timeout);
do {
retval = si470x_get_register(radio, STATUSRSSI);
if (retval < 0)
goto stop;
timed_out = time_after(jiffies, timeout);
} while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) &&
(!timed_out));
/* currently I2C driver only uses interrupt way to seek */
if (radio->stci_enabled) {
INIT_COMPLETION(radio->completion);

/* wait till seek operation has completed */
retval = wait_for_completion_timeout(&radio->completion,
msecs_to_jiffies(seek_timeout));
if (!retval)
timed_out = true;
} else {
/* wait till seek operation has completed */
timeout = jiffies + msecs_to_jiffies(seek_timeout);
do {
retval = si470x_get_register(radio, STATUSRSSI);
if (retval < 0)
goto stop;
timed_out = time_after(jiffies, timeout);
} while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
&& (!timed_out));
}

if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
dev_warn(&radio->videodev->dev, "seek does not complete\n");
if (radio->registers[STATUSRSSI] & STATUSRSSI_SF)
Expand Down
17 changes: 15 additions & 2 deletions drivers/media/radio/si470x/radio-si470x-i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,9 @@ int si470x_fops_open(struct file *file)
if (retval < 0)
goto done;

/* enable RDS interrupt */
/* enable RDS / STC interrupt */
radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDSIEN;
radio->registers[SYSCONFIG1] |= SYSCONFIG1_STCIEN;
radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_GPIO2;
radio->registers[SYSCONFIG1] |= 0x1 << 2;
retval = si470x_set_register(radio, SYSCONFIG1);
Expand Down Expand Up @@ -274,12 +275,20 @@ static void si470x_i2c_interrupt_work(struct work_struct *work)
unsigned char tmpbuf[3];
int retval = 0;

/* check Seek/Tune Complete */
retval = si470x_get_register(radio, STATUSRSSI);
if (retval < 0)
return;

if (radio->registers[STATUSRSSI] & STATUSRSSI_STC)
complete(&radio->completion);

/* safety checks */
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
return;

/* Update RDS registers */
for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) {
for (regnr = 1; regnr < RDS_REGISTER_NUM; regnr++) {
retval = si470x_get_register(radio, STATUSRSSI + regnr);
if (retval < 0)
return;
Expand Down Expand Up @@ -441,6 +450,10 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client,
radio->rd_index = 0;
init_waitqueue_head(&radio->read_queue);

/* mark Seek/Tune Complete Interrupt enabled */
radio->stci_enabled = true;
init_completion(&radio->completion);

retval = request_irq(client->irq, si470x_i2c_interrupt,
IRQF_TRIGGER_FALLING, DRIVER_NAME, radio);
if (retval) {
Expand Down
3 changes: 3 additions & 0 deletions drivers/media/radio/si470x/radio-si470x.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ struct si470x_device {
unsigned int rd_index;
unsigned int wr_index;

struct completion completion;
bool stci_enabled; /* Seek/Tune Complete Interrupt */

#if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE)
/* reference to USB and video device */
struct usb_device *usbdev;
Expand Down

0 comments on commit 0830be3

Please sign in to comment.