From 0830be3fe107372b375256c5303cabd85d4be234 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Fri, 11 Mar 2011 03:54:46 -0300 Subject: [media] radio-si470x: support seek and tune interrupt enable 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 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/si470x/radio-si470x-common.c | 60 +++++++++++++++++------- drivers/media/radio/si470x/radio-si470x-i2c.c | 17 ++++++- drivers/media/radio/si470x/radio-si470x.h | 3 ++ 3 files changed, 60 insertions(+), 20 deletions(-) (limited to 'drivers/media/radio') diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c index 38ae6cd65790..0e740c98786c 100644 --- a/drivers/media/radio/si470x/radio-si470x-common.c +++ b/drivers/media/radio/si470x/radio-si470x-common.c @@ -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) diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index 4ce541a5eb47..5a2975ded5d2 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -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) { diff --git a/drivers/media/radio/si470x/radio-si470x.h b/drivers/media/radio/si470x/radio-si470x.h index 4a4e908db04c..9ef671657771 100644 --- a/drivers/media/radio/si470x/radio-si470x.h +++ b/drivers/media/radio/si470x/radio-si470x.h @@ -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; -- cgit v1.2.3-59-g8ed1b From 949cf31cb00c16a1011c73c43f30cd3e2dfb6610 Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Fri, 11 Mar 2011 03:54:47 -0300 Subject: [media] radio-si470x: convert to dev_pm_ops Signed-off-by: Joonyoung Shim Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/si470x/radio-si470x-i2c.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers/media/radio') diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index 5a2975ded5d2..898f68a83611 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -504,8 +504,9 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client) /* * si470x_i2c_suspend - suspend the device */ -static int si470x_i2c_suspend(struct i2c_client *client, pm_message_t mesg) +static int si470x_i2c_suspend(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); struct si470x_device *radio = i2c_get_clientdata(client); /* power down */ @@ -520,8 +521,9 @@ static int si470x_i2c_suspend(struct i2c_client *client, pm_message_t mesg) /* * si470x_i2c_resume - resume the device */ -static int si470x_i2c_resume(struct i2c_client *client) +static int si470x_i2c_resume(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); struct si470x_device *radio = i2c_get_clientdata(client); /* power up : need 110ms */ @@ -532,9 +534,8 @@ static int si470x_i2c_resume(struct i2c_client *client) return 0; } -#else -#define si470x_i2c_suspend NULL -#define si470x_i2c_resume NULL + +static SIMPLE_DEV_PM_OPS(si470x_i2c_pm, si470x_i2c_suspend, si470x_i2c_resume); #endif @@ -545,11 +546,12 @@ static struct i2c_driver si470x_i2c_driver = { .driver = { .name = "si470x", .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &si470x_i2c_pm, +#endif }, .probe = si470x_i2c_probe, .remove = __devexit_p(si470x_i2c_remove), - .suspend = si470x_i2c_suspend, - .resume = si470x_i2c_resume, .id_table = si470x_i2c_id, }; -- cgit v1.2.3-59-g8ed1b From 474fdc0822abd36d38041c0f02513adb5006f6cb Mon Sep 17 00:00:00 2001 From: Joonyoung Shim Date: Fri, 11 Mar 2011 03:54:48 -0300 Subject: [media] radio-si470x: convert to use request_threaded_irq() Signed-off-by: Joonyoung Shim Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/si470x/radio-si470x-i2c.c | 32 ++++++++------------------- drivers/media/radio/si470x/radio-si470x.h | 1 - 2 files changed, 9 insertions(+), 24 deletions(-) (limited to 'drivers/media/radio') diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index 898f68a83611..a2a67772c42c 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -262,12 +262,11 @@ int si470x_vidioc_querycap(struct file *file, void *priv, **************************************************************************/ /* - * si470x_i2c_interrupt_work - rds processing function + * si470x_i2c_interrupt - interrupt handler */ -static void si470x_i2c_interrupt_work(struct work_struct *work) +static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id) { - struct si470x_device *radio = container_of(work, - struct si470x_device, radio_work); + struct si470x_device *radio = dev_id; unsigned char regnr; unsigned char blocknum; unsigned short bler; /* rds block errors */ @@ -278,26 +277,26 @@ static void si470x_i2c_interrupt_work(struct work_struct *work) /* check Seek/Tune Complete */ retval = si470x_get_register(radio, STATUSRSSI); if (retval < 0) - return; + goto end; if (radio->registers[STATUSRSSI] & STATUSRSSI_STC) complete(&radio->completion); /* safety checks */ if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) - return; + goto end; /* Update RDS registers */ for (regnr = 1; regnr < RDS_REGISTER_NUM; regnr++) { retval = si470x_get_register(radio, STATUSRSSI + regnr); if (retval < 0) - return; + goto end; } /* get rds blocks */ if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0) /* No RDS group ready, better luck next time */ - return; + goto end; for (blocknum = 0; blocknum < 4; blocknum++) { switch (blocknum) { @@ -351,19 +350,8 @@ static void si470x_i2c_interrupt_work(struct work_struct *work) if (radio->wr_index != radio->rd_index) wake_up_interruptible(&radio->read_queue); -} - - -/* - * si470x_i2c_interrupt - interrupt handler - */ -static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id) -{ - struct si470x_device *radio = dev_id; - - if (!work_pending(&radio->radio_work)) - schedule_work(&radio->radio_work); +end: return IRQ_HANDLED; } @@ -385,7 +373,6 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client, goto err_initial; } - INIT_WORK(&radio->radio_work, si470x_i2c_interrupt_work); radio->users = 0; radio->client = client; mutex_init(&radio->lock); @@ -454,7 +441,7 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client, radio->stci_enabled = true; init_completion(&radio->completion); - retval = request_irq(client->irq, si470x_i2c_interrupt, + retval = request_threaded_irq(client->irq, NULL, si470x_i2c_interrupt, IRQF_TRIGGER_FALLING, DRIVER_NAME, radio); if (retval) { dev_err(&client->dev, "Failed to register interrupt\n"); @@ -492,7 +479,6 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client) struct si470x_device *radio = i2c_get_clientdata(client); free_irq(client->irq, radio); - cancel_work_sync(&radio->radio_work); video_unregister_device(radio->videodev); kfree(radio); diff --git a/drivers/media/radio/si470x/radio-si470x.h b/drivers/media/radio/si470x/radio-si470x.h index 9ef671657771..68da001b09dc 100644 --- a/drivers/media/radio/si470x/radio-si470x.h +++ b/drivers/media/radio/si470x/radio-si470x.h @@ -182,7 +182,6 @@ struct si470x_device { #if defined(CONFIG_I2C_SI470X) || defined(CONFIG_I2C_SI470X_MODULE) struct i2c_client *client; - struct work_struct radio_work; #endif }; -- cgit v1.2.3-59-g8ed1b From b01ff50035844bf2abac4a7e27b662a92ebb1d7b Mon Sep 17 00:00:00 2001 From: Thiago Farina Date: Sun, 3 Apr 2011 19:50:14 -0300 Subject: [media] wl128x: Remove unused NO_OF_ENTRIES_IN_ARRAY macro Signed-off-by: Thiago Farina Signed-off-by: Mauro Carvalho Chehab --- drivers/media/radio/wl128x/fmdrv.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/media/radio') diff --git a/drivers/media/radio/wl128x/fmdrv.h b/drivers/media/radio/wl128x/fmdrv.h index 5db6fd14cf3c..1a45a5d847b0 100644 --- a/drivers/media/radio/wl128x/fmdrv.h +++ b/drivers/media/radio/wl128x/fmdrv.h @@ -55,8 +55,6 @@ #define FM_DRV_TX_TIMEOUT (5*HZ) /* 5 seconds */ #define FM_DRV_RX_SEEK_TIMEOUT (20*HZ) /* 20 seconds */ -#define NO_OF_ENTRIES_IN_ARRAY(array) (sizeof(array) / sizeof(array[0])) - #define fmerr(format, ...) \ printk(KERN_ERR "fmdrv: " format, ## __VA_ARGS__) #define fmwarn(format, ...) \ -- cgit v1.2.3-59-g8ed1b