[media] radio-si470x: support seek and tune interrupt enable
Joonyoung Shim [Fri, 11 Mar 2011 06:54:46 +0000 (03:54 -0300)]
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>

drivers/media/radio/si470x/radio-si470x-common.c
drivers/media/radio/si470x/radio-si470x-i2c.c
drivers/media/radio/si470x/radio-si470x.h

index 38ae6cd..0e740c9 100644 (file)
@@ -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)
@@ -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)
index 4ce541a..5a2975d 100644 (file)
@@ -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);
@@ -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;
@@ -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) {
index 4a4e908..9ef6716 100644 (file)
@@ -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;