diff options
Diffstat (limited to 'drivers/media/radio/si470x/radio-si470x-i2c.c')
-rw-r--r-- | drivers/media/radio/si470x/radio-si470x-i2c.c | 63 |
1 files changed, 32 insertions, 31 deletions
diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index 4ce541a5eb47..a2a67772c42c 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) | |||
197 | if (retval < 0) | 197 | if (retval < 0) |
198 | goto done; | 198 | goto done; |
199 | 199 | ||
200 | /* enable RDS interrupt */ | 200 | /* enable RDS / STC interrupt */ |
201 | radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDSIEN; | 201 | radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDSIEN; |
202 | radio->registers[SYSCONFIG1] |= SYSCONFIG1_STCIEN; | ||
202 | radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_GPIO2; | 203 | radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_GPIO2; |
203 | radio->registers[SYSCONFIG1] |= 0x1 << 2; | 204 | radio->registers[SYSCONFIG1] |= 0x1 << 2; |
204 | retval = si470x_set_register(radio, SYSCONFIG1); | 205 | retval = si470x_set_register(radio, SYSCONFIG1); |
@@ -261,12 +262,11 @@ int si470x_vidioc_querycap(struct file *file, void *priv, | |||
261 | **************************************************************************/ | 262 | **************************************************************************/ |
262 | 263 | ||
263 | /* | 264 | /* |
264 | * si470x_i2c_interrupt_work - rds processing function | 265 | * si470x_i2c_interrupt - interrupt handler |
265 | */ | 266 | */ |
266 | static void si470x_i2c_interrupt_work(struct work_struct *work) | 267 | static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id) |
267 | { | 268 | { |
268 | struct si470x_device *radio = container_of(work, | 269 | struct si470x_device *radio = dev_id; |
269 | struct si470x_device, radio_work); | ||
270 | unsigned char regnr; | 270 | unsigned char regnr; |
271 | unsigned char blocknum; | 271 | unsigned char blocknum; |
272 | unsigned short bler; /* rds block errors */ | 272 | unsigned short bler; /* rds block errors */ |
@@ -274,21 +274,29 @@ static void si470x_i2c_interrupt_work(struct work_struct *work) | |||
274 | unsigned char tmpbuf[3]; | 274 | unsigned char tmpbuf[3]; |
275 | int retval = 0; | 275 | int retval = 0; |
276 | 276 | ||
277 | /* check Seek/Tune Complete */ | ||
278 | retval = si470x_get_register(radio, STATUSRSSI); | ||
279 | if (retval < 0) | ||
280 | goto end; | ||
281 | |||
282 | if (radio->registers[STATUSRSSI] & STATUSRSSI_STC) | ||
283 | complete(&radio->completion); | ||
284 | |||
277 | /* safety checks */ | 285 | /* safety checks */ |
278 | if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) | 286 | if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) |
279 | return; | 287 | goto end; |
280 | 288 | ||
281 | /* Update RDS registers */ | 289 | /* Update RDS registers */ |
282 | for (regnr = 0; regnr < RDS_REGISTER_NUM; regnr++) { | 290 | for (regnr = 1; regnr < RDS_REGISTER_NUM; regnr++) { |
283 | retval = si470x_get_register(radio, STATUSRSSI + regnr); | 291 | retval = si470x_get_register(radio, STATUSRSSI + regnr); |
284 | if (retval < 0) | 292 | if (retval < 0) |
285 | return; | 293 | goto end; |
286 | } | 294 | } |
287 | 295 | ||
288 | /* get rds blocks */ | 296 | /* get rds blocks */ |
289 | if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0) | 297 | if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0) |
290 | /* No RDS group ready, better luck next time */ | 298 | /* No RDS group ready, better luck next time */ |
291 | return; | 299 | goto end; |
292 | 300 | ||
293 | for (blocknum = 0; blocknum < 4; blocknum++) { | 301 | for (blocknum = 0; blocknum < 4; blocknum++) { |
294 | switch (blocknum) { | 302 | switch (blocknum) { |
@@ -342,19 +350,8 @@ static void si470x_i2c_interrupt_work(struct work_struct *work) | |||
342 | 350 | ||
343 | if (radio->wr_index != radio->rd_index) | 351 | if (radio->wr_index != radio->rd_index) |
344 | wake_up_interruptible(&radio->read_queue); | 352 | wake_up_interruptible(&radio->read_queue); |
345 | } | ||
346 | |||
347 | |||
348 | /* | ||
349 | * si470x_i2c_interrupt - interrupt handler | ||
350 | */ | ||
351 | static irqreturn_t si470x_i2c_interrupt(int irq, void *dev_id) | ||
352 | { | ||
353 | struct si470x_device *radio = dev_id; | ||
354 | |||
355 | if (!work_pending(&radio->radio_work)) | ||
356 | schedule_work(&radio->radio_work); | ||
357 | 353 | ||
354 | end: | ||
358 | return IRQ_HANDLED; | 355 | return IRQ_HANDLED; |
359 | } | 356 | } |
360 | 357 | ||
@@ -376,7 +373,6 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client, | |||
376 | goto err_initial; | 373 | goto err_initial; |
377 | } | 374 | } |
378 | 375 | ||
379 | INIT_WORK(&radio->radio_work, si470x_i2c_interrupt_work); | ||
380 | radio->users = 0; | 376 | radio->users = 0; |
381 | radio->client = client; | 377 | radio->client = client; |
382 | mutex_init(&radio->lock); | 378 | mutex_init(&radio->lock); |
@@ -441,7 +437,11 @@ static int __devinit si470x_i2c_probe(struct i2c_client *client, | |||
441 | radio->rd_index = 0; | 437 | radio->rd_index = 0; |
442 | init_waitqueue_head(&radio->read_queue); | 438 | init_waitqueue_head(&radio->read_queue); |
443 | 439 | ||
444 | retval = request_irq(client->irq, si470x_i2c_interrupt, | 440 | /* mark Seek/Tune Complete Interrupt enabled */ |
441 | radio->stci_enabled = true; | ||
442 | init_completion(&radio->completion); | ||
443 | |||
444 | retval = request_threaded_irq(client->irq, NULL, si470x_i2c_interrupt, | ||
445 | IRQF_TRIGGER_FALLING, DRIVER_NAME, radio); | 445 | IRQF_TRIGGER_FALLING, DRIVER_NAME, radio); |
446 | if (retval) { | 446 | if (retval) { |
447 | dev_err(&client->dev, "Failed to register interrupt\n"); | 447 | dev_err(&client->dev, "Failed to register interrupt\n"); |
@@ -479,7 +479,6 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client) | |||
479 | struct si470x_device *radio = i2c_get_clientdata(client); | 479 | struct si470x_device *radio = i2c_get_clientdata(client); |
480 | 480 | ||
481 | free_irq(client->irq, radio); | 481 | free_irq(client->irq, radio); |
482 | cancel_work_sync(&radio->radio_work); | ||
483 | video_unregister_device(radio->videodev); | 482 | video_unregister_device(radio->videodev); |
484 | kfree(radio); | 483 | kfree(radio); |
485 | 484 | ||
@@ -491,8 +490,9 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client) | |||
491 | /* | 490 | /* |
492 | * si470x_i2c_suspend - suspend the device | 491 | * si470x_i2c_suspend - suspend the device |
493 | */ | 492 | */ |
494 | static int si470x_i2c_suspend(struct i2c_client *client, pm_message_t mesg) | 493 | static int si470x_i2c_suspend(struct device *dev) |
495 | { | 494 | { |
495 | struct i2c_client *client = to_i2c_client(dev); | ||
496 | struct si470x_device *radio = i2c_get_clientdata(client); | 496 | struct si470x_device *radio = i2c_get_clientdata(client); |
497 | 497 | ||
498 | /* power down */ | 498 | /* power down */ |
@@ -507,8 +507,9 @@ static int si470x_i2c_suspend(struct i2c_client *client, pm_message_t mesg) | |||
507 | /* | 507 | /* |
508 | * si470x_i2c_resume - resume the device | 508 | * si470x_i2c_resume - resume the device |
509 | */ | 509 | */ |
510 | static int si470x_i2c_resume(struct i2c_client *client) | 510 | static int si470x_i2c_resume(struct device *dev) |
511 | { | 511 | { |
512 | struct i2c_client *client = to_i2c_client(dev); | ||
512 | struct si470x_device *radio = i2c_get_clientdata(client); | 513 | struct si470x_device *radio = i2c_get_clientdata(client); |
513 | 514 | ||
514 | /* power up : need 110ms */ | 515 | /* power up : need 110ms */ |
@@ -519,9 +520,8 @@ static int si470x_i2c_resume(struct i2c_client *client) | |||
519 | 520 | ||
520 | return 0; | 521 | return 0; |
521 | } | 522 | } |
522 | #else | 523 | |
523 | #define si470x_i2c_suspend NULL | 524 | static SIMPLE_DEV_PM_OPS(si470x_i2c_pm, si470x_i2c_suspend, si470x_i2c_resume); |
524 | #define si470x_i2c_resume NULL | ||
525 | #endif | 525 | #endif |
526 | 526 | ||
527 | 527 | ||
@@ -532,11 +532,12 @@ static struct i2c_driver si470x_i2c_driver = { | |||
532 | .driver = { | 532 | .driver = { |
533 | .name = "si470x", | 533 | .name = "si470x", |
534 | .owner = THIS_MODULE, | 534 | .owner = THIS_MODULE, |
535 | #ifdef CONFIG_PM | ||
536 | .pm = &si470x_i2c_pm, | ||
537 | #endif | ||
535 | }, | 538 | }, |
536 | .probe = si470x_i2c_probe, | 539 | .probe = si470x_i2c_probe, |
537 | .remove = __devexit_p(si470x_i2c_remove), | 540 | .remove = __devexit_p(si470x_i2c_remove), |
538 | .suspend = si470x_i2c_suspend, | ||
539 | .resume = si470x_i2c_resume, | ||
540 | .id_table = si470x_i2c_id, | 541 | .id_table = si470x_i2c_id, |
541 | }; | 542 | }; |
542 | 543 | ||