aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2011-01-14 09:10:05 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-01-19 08:45:25 -0500
commitc736a5f28e81299b05ad14e892bdfb414daa9f5f (patch)
treee93e5f989e35866a9aab826af065630c91ee263e
parent7570800c9de39c718f84ec4ea820a788556cde4b (diff)
[media] mb86a20s: Be sure that device is initialized before starting DVB
Due to a hard to track bug between tda829x/tda18271/saa7134, tda829x wants to go to analog mode during DVB initialization, causing some I2C errors. The analog failure doesn't cause any harm, as the device were already properly initialized in analog mode. However, the failure at the digital mode causes the frontend mb86a20s to not initialize. Fortunately, at least on my tests, it was possible to detect that the device is a mb86a20s before the failure. What happens is that tda8290 is a very bad boy: during DVB setup, it keeps insisting to call tda18271 analog_set_params, that calls tune_agc code. The tune_agc code calls saa7134 driver, changing the value of GPIO 27, switching from digital to analog mode and disabling the access to mb86a20s, as, on Kworld SBTVD, the same GPIO used to switch the hardware AGC mode seems to be used to enable the I2C switch that allows access to the frontend (mb86a20s). So, a call to analog_set_params ultimately disables the access to the frontend, and causes a failure at the init frontend logic. This patch is a workaround for this issue: it simply checks if the frontend init had any failure. If so, it will init the frontend when some DTV application will try to set DVB mode. Even being a hack for Kworld SBTVD to work, and assumning that we could teach tda8290 to be a good boy, this is actually an improvement at the frontend driver, as it will be more reliable to initialization failures. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/dvb/frontends/mb86a20s.c32
1 files changed, 28 insertions, 4 deletions
diff --git a/drivers/media/dvb/frontends/mb86a20s.c b/drivers/media/dvb/frontends/mb86a20s.c
index e06507d2c3b2..cc4acd2f920d 100644
--- a/drivers/media/dvb/frontends/mb86a20s.c
+++ b/drivers/media/dvb/frontends/mb86a20s.c
@@ -43,6 +43,8 @@ struct mb86a20s_state {
43 const struct mb86a20s_config *config; 43 const struct mb86a20s_config *config;
44 44
45 struct dvb_frontend frontend; 45 struct dvb_frontend frontend;
46
47 bool need_init;
46}; 48};
47 49
48struct regdata { 50struct regdata {
@@ -382,23 +384,31 @@ static int mb86a20s_initfe(struct dvb_frontend *fe)
382 /* Initialize the frontend */ 384 /* Initialize the frontend */
383 rc = mb86a20s_writeregdata(state, mb86a20s_init); 385 rc = mb86a20s_writeregdata(state, mb86a20s_init);
384 if (rc < 0) 386 if (rc < 0)
385 return rc; 387 goto err;
386 388
387 if (!state->config->is_serial) { 389 if (!state->config->is_serial) {
388 regD5 &= ~1; 390 regD5 &= ~1;
389 391
390 rc = mb86a20s_writereg(state, 0x50, 0xd5); 392 rc = mb86a20s_writereg(state, 0x50, 0xd5);
391 if (rc < 0) 393 if (rc < 0)
392 return rc; 394 goto err;
393 rc = mb86a20s_writereg(state, 0x51, regD5); 395 rc = mb86a20s_writereg(state, 0x51, regD5);
394 if (rc < 0) 396 if (rc < 0)
395 return rc; 397 goto err;
396 } 398 }
397 399
398 if (fe->ops.i2c_gate_ctrl) 400 if (fe->ops.i2c_gate_ctrl)
399 fe->ops.i2c_gate_ctrl(fe, 1); 401 fe->ops.i2c_gate_ctrl(fe, 1);
400 402
401 return 0; 403err:
404 if (rc < 0) {
405 state->need_init = true;
406 printk(KERN_INFO "mb86a20s: Init failed. Will try again later\n");
407 } else {
408 state->need_init = false;
409 dprintk("Initialization succeded.\n");
410 }
411 return rc;
402} 412}
403 413
404static int mb86a20s_read_signal_strength(struct dvb_frontend *fe, u16 *strength) 414static int mb86a20s_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
@@ -485,8 +495,22 @@ static int mb86a20s_set_frontend(struct dvb_frontend *fe,
485 495
486 if (fe->ops.i2c_gate_ctrl) 496 if (fe->ops.i2c_gate_ctrl)
487 fe->ops.i2c_gate_ctrl(fe, 1); 497 fe->ops.i2c_gate_ctrl(fe, 1);
498 dprintk("Calling tuner set parameters\n");
488 fe->ops.tuner_ops.set_params(fe, p); 499 fe->ops.tuner_ops.set_params(fe, p);
489 500
501 /*
502 * Make it more reliable: if, for some reason, the initial
503 * device initialization doesn't happen, initialize it when
504 * a SBTVD parameters are adjusted.
505 *
506 * Unfortunately, due to a hard to track bug at tda829x/tda18271,
507 * the agc callback logic is not called during DVB attach time,
508 * causing mb86a20s to not be initialized with Kworld SBTVD.
509 * So, this hack is needed, in order to make Kworld SBTVD to work.
510 */
511 if (state->need_init)
512 mb86a20s_initfe(fe);
513
490 if (fe->ops.i2c_gate_ctrl) 514 if (fe->ops.i2c_gate_ctrl)
491 fe->ops.i2c_gate_ctrl(fe, 0); 515 fe->ops.i2c_gate_ctrl(fe, 0);
492 rc = mb86a20s_writeregdata(state, mb86a20s_reset_reception); 516 rc = mb86a20s_writeregdata(state, mb86a20s_reset_reception);