aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/radio/si4713/si4713.c108
1 files changed, 64 insertions, 44 deletions
diff --git a/drivers/media/radio/si4713/si4713.c b/drivers/media/radio/si4713/si4713.c
index 4f3308f91608..5d26b9ad014d 100644
--- a/drivers/media/radio/si4713/si4713.c
+++ b/drivers/media/radio/si4713/si4713.c
@@ -27,11 +27,11 @@
27#include <linux/i2c.h> 27#include <linux/i2c.h>
28#include <linux/slab.h> 28#include <linux/slab.h>
29#include <linux/gpio.h> 29#include <linux/gpio.h>
30#include <linux/regulator/consumer.h>
31#include <linux/module.h> 30#include <linux/module.h>
32#include <media/v4l2-device.h> 31#include <media/v4l2-device.h>
33#include <media/v4l2-ioctl.h> 32#include <media/v4l2-ioctl.h>
34#include <media/v4l2-common.h> 33#include <media/v4l2-common.h>
34#include <linux/regulator/consumer.h>
35 35
36#include "si4713.h" 36#include "si4713.h"
37 37
@@ -213,6 +213,7 @@ static int si4713_send_command(struct si4713_device *sdev, const u8 command,
213 u8 response[], const int respn, const int usecs) 213 u8 response[], const int respn, const int usecs)
214{ 214{
215 struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd); 215 struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
216 unsigned long until_jiffies;
216 u8 data1[MAX_ARGS + 1]; 217 u8 data1[MAX_ARGS + 1];
217 int err; 218 int err;
218 219
@@ -228,30 +229,39 @@ static int si4713_send_command(struct si4713_device *sdev, const u8 command,
228 if (err != argn + 1) { 229 if (err != argn + 1) {
229 v4l2_err(&sdev->sd, "Error while sending command 0x%02x\n", 230 v4l2_err(&sdev->sd, "Error while sending command 0x%02x\n",
230 command); 231 command);
231 return (err > 0) ? -EIO : err; 232 return err < 0 ? err : -EIO;
232 } 233 }
233 234
235 until_jiffies = jiffies + usecs_to_jiffies(usecs) + 1;
236
234 /* Wait response from interrupt */ 237 /* Wait response from interrupt */
235 if (!wait_for_completion_timeout(&sdev->work, 238 if (client->irq) {
239 if (!wait_for_completion_timeout(&sdev->work,
236 usecs_to_jiffies(usecs) + 1)) 240 usecs_to_jiffies(usecs) + 1))
237 v4l2_warn(&sdev->sd, 241 v4l2_warn(&sdev->sd,
238 "(%s) Device took too much time to answer.\n", 242 "(%s) Device took too much time to answer.\n",
239 __func__); 243 __func__);
240
241 /* Then get the response */
242 err = i2c_master_recv(client, response, respn);
243 if (err != respn) {
244 v4l2_err(&sdev->sd,
245 "Error while reading response for command 0x%02x\n",
246 command);
247 return (err > 0) ? -EIO : err;
248 } 244 }
249 245
250 DBG_BUFFER(&sdev->sd, "Response", response, respn); 246 do {
251 if (check_command_failed(response[0])) 247 err = i2c_master_recv(client, response, respn);
252 return -EBUSY; 248 if (err != respn) {
249 v4l2_err(&sdev->sd,
250 "Error %d while reading response for command 0x%02x\n",
251 err, command);
252 return err < 0 ? err : -EIO;
253 }
254
255 DBG_BUFFER(&sdev->sd, "Response", response, respn);
256 if (!check_command_failed(response[0]))
257 return 0;
253 258
254 return 0; 259 if (client->irq)
260 return -EBUSY;
261 msleep(1);
262 } while (jiffies <= until_jiffies);
263
264 return -EBUSY;
255} 265}
256 266
257/* 267/*
@@ -344,14 +354,15 @@ static int si4713_write_property(struct si4713_device *sdev, u16 prop, u16 val)
344 */ 354 */
345static int si4713_powerup(struct si4713_device *sdev) 355static int si4713_powerup(struct si4713_device *sdev)
346{ 356{
357 struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
347 int err; 358 int err;
348 u8 resp[SI4713_PWUP_NRESP]; 359 u8 resp[SI4713_PWUP_NRESP];
349 /* 360 /*
350 * .First byte = Enabled interrupts and boot function 361 * .First byte = Enabled interrupts and boot function
351 * .Second byte = Input operation mode 362 * .Second byte = Input operation mode
352 */ 363 */
353 const u8 args[SI4713_PWUP_NARGS] = { 364 u8 args[SI4713_PWUP_NARGS] = {
354 SI4713_PWUP_CTSIEN | SI4713_PWUP_GPO2OEN | SI4713_PWUP_FUNC_TX, 365 SI4713_PWUP_GPO2OEN | SI4713_PWUP_FUNC_TX,
355 SI4713_PWUP_OPMOD_ANALOG, 366 SI4713_PWUP_OPMOD_ANALOG,
356 }; 367 };
357 368
@@ -369,6 +380,9 @@ static int si4713_powerup(struct si4713_device *sdev)
369 gpio_set_value(sdev->gpio_reset, 1); 380 gpio_set_value(sdev->gpio_reset, 1);
370 } 381 }
371 382
383 if (client->irq)
384 args[0] |= SI4713_PWUP_CTSIEN;
385
372 err = si4713_send_command(sdev, SI4713_CMD_POWER_UP, 386 err = si4713_send_command(sdev, SI4713_CMD_POWER_UP,
373 args, ARRAY_SIZE(args), 387 args, ARRAY_SIZE(args),
374 resp, ARRAY_SIZE(resp), 388 resp, ARRAY_SIZE(resp),
@@ -380,7 +394,8 @@ static int si4713_powerup(struct si4713_device *sdev)
380 v4l2_dbg(1, debug, &sdev->sd, "Device in power up mode\n"); 394 v4l2_dbg(1, debug, &sdev->sd, "Device in power up mode\n");
381 sdev->power_state = POWER_ON; 395 sdev->power_state = POWER_ON;
382 396
383 err = si4713_write_property(sdev, SI4713_GPO_IEN, 397 if (client->irq)
398 err = si4713_write_property(sdev, SI4713_GPO_IEN,
384 SI4713_STC_INT | SI4713_CTS); 399 SI4713_STC_INT | SI4713_CTS);
385 } else { 400 } else {
386 if (gpio_is_valid(sdev->gpio_reset)) 401 if (gpio_is_valid(sdev->gpio_reset))
@@ -465,33 +480,39 @@ static int si4713_checkrev(struct si4713_device *sdev)
465 */ 480 */
466static int si4713_wait_stc(struct si4713_device *sdev, const int usecs) 481static int si4713_wait_stc(struct si4713_device *sdev, const int usecs)
467{ 482{
468 int err; 483 struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd);
469 u8 resp[SI4713_GET_STATUS_NRESP]; 484 u8 resp[SI4713_GET_STATUS_NRESP];
485 unsigned long start_jiffies = jiffies;
486 int err;
470 487
471 /* Wait response from STC interrupt */ 488 if (client->irq &&
472 if (!wait_for_completion_timeout(&sdev->work, 489 !wait_for_completion_timeout(&sdev->work, usecs_to_jiffies(usecs) + 1))
473 usecs_to_jiffies(usecs) + 1))
474 v4l2_warn(&sdev->sd, 490 v4l2_warn(&sdev->sd,
475 "%s: device took too much time to answer (%d usec).\n", 491 "(%s) Device took too much time to answer.\n", __func__);
476 __func__, usecs); 492
477 493 for (;;) {
478 /* Clear status bits */ 494 /* Clear status bits */
479 err = si4713_send_command(sdev, SI4713_CMD_GET_INT_STATUS, 495 err = si4713_send_command(sdev, SI4713_CMD_GET_INT_STATUS,
480 NULL, 0, 496 NULL, 0,
481 resp, ARRAY_SIZE(resp), 497 resp, ARRAY_SIZE(resp),
482 DEFAULT_TIMEOUT); 498 DEFAULT_TIMEOUT);
483 499 /* The USB device returns errors when it waits for the
484 if (err < 0) 500 * STC bit to be set. Hence polling */
485 goto exit; 501 if (err >= 0) {
486 502 v4l2_dbg(1, debug, &sdev->sd,
487 v4l2_dbg(1, debug, &sdev->sd, 503 "%s: status bits: 0x%02x\n", __func__, resp[0]);
488 "%s: status bits: 0x%02x\n", __func__, resp[0]); 504
489 505 if (resp[0] & SI4713_STC_INT)
490 if (!(resp[0] & SI4713_STC_INT)) 506 return 0;
491 err = -EIO; 507 }
492 508 if (jiffies_to_usecs(jiffies - start_jiffies) > usecs)
493exit: 509 return err < 0 ? err : -EIO;
494 return err; 510 /* We sleep here for 3 ms in order to avoid flooding the device
511 * with USB requests. The si4713 USB driver was developed
512 * by reverse engineering the Windows USB driver. The windows
513 * driver also has a ~2.5 ms delay between responses. */
514 msleep(3);
515 }
495} 516}
496 517
497/* 518/*
@@ -1024,7 +1045,6 @@ static int si4713_initialize(struct si4713_device *sdev)
1024 if (rval < 0) 1045 if (rval < 0)
1025 return rval; 1046 return rval;
1026 1047
1027
1028 sdev->frequency = DEFAULT_FREQUENCY; 1048 sdev->frequency = DEFAULT_FREQUENCY;
1029 sdev->stereo = 1; 1049 sdev->stereo = 1;
1030 sdev->tune_rnl = DEFAULT_TUNE_RNL; 1050 sdev->tune_rnl = DEFAULT_TUNE_RNL;