aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/radio/si470x
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2012-06-14 08:43:12 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-07-30 17:11:28 -0400
commit779471110c6f0f7f7c223fc696170ec750ac3531 (patch)
tree3c969ef4c615a52f305d55f18405e7f9d1542cea /drivers/media/radio/si470x
parent86ef3f78b8bae808f41f74c506762ac345fdf893 (diff)
[media] radio-si470x: Always use interrupt to wait for tune/seek completion
Since USB receives STATUS_RSSI updates through the interrupt endpoint, there is no need to poll with USB, so get rid of the polling. Note this also changes the order in which the probing of USB devices is done, to avoid si470x_set_chan getting called before the interrupt endpoint is being monitored. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/radio/si470x')
-rw-r--r--drivers/media/radio/si470x/radio-si470x-common.c56
-rw-r--r--drivers/media/radio/si470x/radio-si470x-i2c.c5
-rw-r--r--drivers/media/radio/si470x/radio-si470x-usb.c25
-rw-r--r--drivers/media/radio/si470x/radio-si470x.h1
4 files changed, 28 insertions, 59 deletions
diff --git a/drivers/media/radio/si470x/radio-si470x-common.c b/drivers/media/radio/si470x/radio-si470x-common.c
index 5dbb897e14de..9f8b675944f5 100644
--- a/drivers/media/radio/si470x/radio-si470x-common.c
+++ b/drivers/media/radio/si470x/radio-si470x-common.c
@@ -164,7 +164,6 @@ MODULE_PARM_DESC(seek_timeout, "Seek timeout: *5000*");
164static int si470x_set_chan(struct si470x_device *radio, unsigned short chan) 164static int si470x_set_chan(struct si470x_device *radio, unsigned short chan)
165{ 165{
166 int retval; 166 int retval;
167 unsigned long timeout;
168 bool timed_out = 0; 167 bool timed_out = 0;
169 168
170 /* start tuning */ 169 /* start tuning */
@@ -174,26 +173,12 @@ static int si470x_set_chan(struct si470x_device *radio, unsigned short chan)
174 if (retval < 0) 173 if (retval < 0)
175 goto done; 174 goto done;
176 175
177 /* currently I2C driver only uses interrupt way to tune */ 176 /* wait till tune operation has completed */
178 if (radio->stci_enabled) { 177 INIT_COMPLETION(radio->completion);
179 INIT_COMPLETION(radio->completion); 178 retval = wait_for_completion_timeout(&radio->completion,
180 179 msecs_to_jiffies(tune_timeout));
181 /* wait till tune operation has completed */ 180 if (!retval)
182 retval = wait_for_completion_timeout(&radio->completion, 181 timed_out = true;
183 msecs_to_jiffies(tune_timeout));
184 if (!retval)
185 timed_out = true;
186 } else {
187 /* wait till tune operation has completed */
188 timeout = jiffies + msecs_to_jiffies(tune_timeout);
189 do {
190 retval = si470x_get_register(radio, STATUSRSSI);
191 if (retval < 0)
192 goto stop;
193 timed_out = time_after(jiffies, timeout);
194 } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
195 && (!timed_out));
196 }
197 182
198 if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) 183 if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
199 dev_warn(&radio->videodev.dev, "tune does not complete\n"); 184 dev_warn(&radio->videodev.dev, "tune does not complete\n");
@@ -201,7 +186,6 @@ static int si470x_set_chan(struct si470x_device *radio, unsigned short chan)
201 dev_warn(&radio->videodev.dev, 186 dev_warn(&radio->videodev.dev,
202 "tune timed out after %u ms\n", tune_timeout); 187 "tune timed out after %u ms\n", tune_timeout);
203 188
204stop:
205 /* stop tuning */ 189 /* stop tuning */
206 radio->registers[CHANNEL] &= ~CHANNEL_TUNE; 190 radio->registers[CHANNEL] &= ~CHANNEL_TUNE;
207 retval = si470x_set_register(radio, CHANNEL); 191 retval = si470x_set_register(radio, CHANNEL);
@@ -312,7 +296,6 @@ static int si470x_set_seek(struct si470x_device *radio,
312 unsigned int wrap_around, unsigned int seek_upward) 296 unsigned int wrap_around, unsigned int seek_upward)
313{ 297{
314 int retval = 0; 298 int retval = 0;
315 unsigned long timeout;
316 bool timed_out = 0; 299 bool timed_out = 0;
317 300
318 /* start seeking */ 301 /* start seeking */
@@ -329,26 +312,12 @@ static int si470x_set_seek(struct si470x_device *radio,
329 if (retval < 0) 312 if (retval < 0)
330 return retval; 313 return retval;
331 314
332 /* currently I2C driver only uses interrupt way to seek */ 315 /* wait till tune operation has completed */
333 if (radio->stci_enabled) { 316 INIT_COMPLETION(radio->completion);
334 INIT_COMPLETION(radio->completion); 317 retval = wait_for_completion_timeout(&radio->completion,
335 318 msecs_to_jiffies(seek_timeout));
336 /* wait till seek operation has completed */ 319 if (!retval)
337 retval = wait_for_completion_timeout(&radio->completion, 320 timed_out = true;
338 msecs_to_jiffies(seek_timeout));
339 if (!retval)
340 timed_out = true;
341 } else {
342 /* wait till seek operation has completed */
343 timeout = jiffies + msecs_to_jiffies(seek_timeout);
344 do {
345 retval = si470x_get_register(radio, STATUSRSSI);
346 if (retval < 0)
347 goto stop;
348 timed_out = time_after(jiffies, timeout);
349 } while (((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
350 && (!timed_out));
351 }
352 321
353 if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0) 322 if ((radio->registers[STATUSRSSI] & STATUSRSSI_STC) == 0)
354 dev_warn(&radio->videodev.dev, "seek does not complete\n"); 323 dev_warn(&radio->videodev.dev, "seek does not complete\n");
@@ -356,7 +325,6 @@ static int si470x_set_seek(struct si470x_device *radio,
356 dev_warn(&radio->videodev.dev, 325 dev_warn(&radio->videodev.dev,
357 "seek failed / band limit reached\n"); 326 "seek failed / band limit reached\n");
358 327
359stop:
360 /* stop seeking */ 328 /* stop seeking */
361 radio->registers[POWERCFG] &= ~POWERCFG_SEEK; 329 radio->registers[POWERCFG] &= ~POWERCFG_SEEK;
362 retval = si470x_set_register(radio, POWERCFG); 330 retval = si470x_set_register(radio, POWERCFG);
diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c
index a80044c5874e..fb401a22b033 100644
--- a/drivers/media/radio/si470x/radio-si470x-i2c.c
+++ b/drivers/media/radio/si470x/radio-si470x-i2c.c
@@ -351,6 +351,7 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client,
351 351
352 radio->client = client; 352 radio->client = client;
353 mutex_init(&radio->lock); 353 mutex_init(&radio->lock);
354 init_completion(&radio->completion);
354 355
355 /* video device initialization */ 356 /* video device initialization */
356 radio->videodev = si470x_viddev_template; 357 radio->videodev = si470x_viddev_template;
@@ -406,10 +407,6 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client,
406 radio->rd_index = 0; 407 radio->rd_index = 0;
407 init_waitqueue_head(&radio->read_queue); 408 init_waitqueue_head(&radio->read_queue);
408 409
409 /* mark Seek/Tune Complete Interrupt enabled */
410 radio->stci_enabled = true;
411 init_completion(&radio->completion);
412
413 retval = request_threaded_irq(client->irq, NULL, si470x_i2c_interrupt, 410 retval = request_threaded_irq(client->irq, NULL, si470x_i2c_interrupt,
414 IRQF_TRIGGER_FALLING, DRIVER_NAME, radio); 411 IRQF_TRIGGER_FALLING, DRIVER_NAME, radio);
415 if (retval) { 412 if (retval) {
diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c
index 0da5c986d3a3..66b1ba8c4aaf 100644
--- a/drivers/media/radio/si470x/radio-si470x-usb.c
+++ b/drivers/media/radio/si470x/radio-si470x-usb.c
@@ -406,6 +406,9 @@ static void si470x_int_in_callback(struct urb *urb)
406 radio->registers[STATUSRSSI] = 406 radio->registers[STATUSRSSI] =
407 get_unaligned_be16(&radio->int_in_buffer[1]); 407 get_unaligned_be16(&radio->int_in_buffer[1]);
408 408
409 if (radio->registers[STATUSRSSI] & STATUSRSSI_STC)
410 complete(&radio->completion);
411
409 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS)) { 412 if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS)) {
410 /* Update RDS registers with URB data */ 413 /* Update RDS registers with URB data */
411 for (regnr = 1; regnr < RDS_REGISTER_NUM; regnr++) 414 for (regnr = 1; regnr < RDS_REGISTER_NUM; regnr++)
@@ -539,13 +542,6 @@ static int si470x_start_usb(struct si470x_device *radio)
539{ 542{
540 int retval; 543 int retval;
541 544
542 /* start radio */
543 retval = si470x_start(radio);
544 if (retval < 0)
545 return retval;
546
547 v4l2_ctrl_handler_setup(&radio->hdl);
548
549 /* initialize interrupt urb */ 545 /* initialize interrupt urb */
550 usb_fill_int_urb(radio->int_in_urb, radio->usbdev, 546 usb_fill_int_urb(radio->int_in_urb, radio->usbdev,
551 usb_rcvintpipe(radio->usbdev, 547 usb_rcvintpipe(radio->usbdev,
@@ -566,6 +562,14 @@ static int si470x_start_usb(struct si470x_device *radio)
566 radio->int_in_running = 0; 562 radio->int_in_running = 0;
567 } 563 }
568 radio->status_rssi_auto_update = radio->int_in_running; 564 radio->status_rssi_auto_update = radio->int_in_running;
565
566 /* start radio */
567 retval = si470x_start(radio);
568 if (retval < 0)
569 return retval;
570
571 v4l2_ctrl_handler_setup(&radio->hdl);
572
569 return retval; 573 return retval;
570} 574}
571 575
@@ -594,6 +598,7 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
594 radio->usbdev = interface_to_usbdev(intf); 598 radio->usbdev = interface_to_usbdev(intf);
595 radio->intf = intf; 599 radio->intf = intf;
596 mutex_init(&radio->lock); 600 mutex_init(&radio->lock);
601 init_completion(&radio->completion);
597 602
598 iface_desc = intf->cur_altsetting; 603 iface_desc = intf->cur_altsetting;
599 604
@@ -704,9 +709,6 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
704 "linux-media@vger.kernel.org\n"); 709 "linux-media@vger.kernel.org\n");
705 } 710 }
706 711
707 /* set initial frequency */
708 si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */
709
710 /* set led to connect state */ 712 /* set led to connect state */
711 si470x_set_led_state(radio, BLINK_GREEN_LED); 713 si470x_set_led_state(radio, BLINK_GREEN_LED);
712 714
@@ -729,6 +731,9 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
729 if (retval < 0) 731 if (retval < 0)
730 goto err_all; 732 goto err_all;
731 733
734 /* set initial frequency */
735 si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */
736
732 /* register video device */ 737 /* register video device */
733 retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO, 738 retval = video_register_device(&radio->videodev, VFL_TYPE_RADIO,
734 radio_nr); 739 radio_nr);
diff --git a/drivers/media/radio/si470x/radio-si470x.h b/drivers/media/radio/si470x/radio-si470x.h
index 2a0a46f180f5..fbf713def94d 100644
--- a/drivers/media/radio/si470x/radio-si470x.h
+++ b/drivers/media/radio/si470x/radio-si470x.h
@@ -160,7 +160,6 @@ struct si470x_device {
160 unsigned int wr_index; 160 unsigned int wr_index;
161 161
162 struct completion completion; 162 struct completion completion;
163 bool stci_enabled; /* Seek/Tune Complete Interrupt */
164 bool status_rssi_auto_update; /* Does RSSI get updated automatic? */ 163 bool status_rssi_auto_update; /* Does RSSI get updated automatic? */
165 164
166#if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE) 165#if defined(CONFIG_USB_SI470X) || defined(CONFIG_USB_SI470X_MODULE)