aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntti Palosaari <crope@iki.fi>2012-12-09 11:28:45 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-01-06 06:07:57 -0500
commit44ff69cd95308c115134f0546317b584fe1bf5b2 (patch)
tree86990b5113acde11f5e60e3963d2f0696ca851f7
parent3a98477200b44328e50a5c0830f92fd5cdc1ea9b (diff)
[media] fc0012: rework attach() to check chip id and I/O errors
Signed-off-by: Antti Palosaari <crope@iki.fi> Acked-by: Hans-Frieder Vogt <hfvogt@gmx.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/tuners/fc0012.c59
1 files changed, 49 insertions, 10 deletions
diff --git a/drivers/media/tuners/fc0012.c b/drivers/media/tuners/fc0012.c
index 01f5e406282c..feb15941cc5b 100644
--- a/drivers/media/tuners/fc0012.c
+++ b/drivers/media/tuners/fc0012.c
@@ -443,32 +443,71 @@ static const struct dvb_tuner_ops fc0012_tuner_ops = {
443struct dvb_frontend *fc0012_attach(struct dvb_frontend *fe, 443struct dvb_frontend *fc0012_attach(struct dvb_frontend *fe,
444 struct i2c_adapter *i2c, const struct fc0012_config *cfg) 444 struct i2c_adapter *i2c, const struct fc0012_config *cfg)
445{ 445{
446 struct fc0012_priv *priv = NULL; 446 struct fc0012_priv *priv;
447 int ret;
448 u8 chip_id;
449
450 if (fe->ops.i2c_gate_ctrl)
451 fe->ops.i2c_gate_ctrl(fe, 1);
447 452
448 priv = kzalloc(sizeof(struct fc0012_priv), GFP_KERNEL); 453 priv = kzalloc(sizeof(struct fc0012_priv), GFP_KERNEL);
449 if (priv == NULL) 454 if (!priv) {
450 return NULL; 455 ret = -ENOMEM;
456 dev_err(&i2c->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME);
457 goto err;
458 }
451 459
452 priv->i2c = i2c;
453 priv->cfg = cfg; 460 priv->cfg = cfg;
461 priv->i2c = i2c;
454 462
455 info("Fitipower FC0012 successfully attached."); 463 /* check if the tuner is there */
464 ret = fc0012_readreg(priv, 0x00, &chip_id);
465 if (ret < 0)
466 goto err;
456 467
457 fe->tuner_priv = priv; 468 dev_dbg(&i2c->dev, "%s: chip_id=%02x\n", __func__, chip_id);
458 469
459 if (priv->cfg->loop_through) 470 switch (chip_id) {
460 fc0012_writereg(priv, 0x09, 0x6f); 471 case 0xa1:
472 break;
473 default:
474 ret = -ENODEV;
475 goto err;
476 }
477
478 dev_info(&i2c->dev, "%s: Fitipower FC0012 successfully identified\n",
479 KBUILD_MODNAME);
480
481 if (priv->cfg->loop_through) {
482 ret = fc0012_writereg(priv, 0x09, 0x6f);
483 if (ret < 0)
484 goto err;
485 }
461 486
462 /* 487 /*
463 * TODO: Clock out en or div? 488 * TODO: Clock out en or div?
464 * For dual tuner configuration clearing bit [0] is required. 489 * For dual tuner configuration clearing bit [0] is required.
465 */ 490 */
466 if (priv->cfg->clock_out) 491 if (priv->cfg->clock_out) {
467 fc0012_writereg(priv, 0x0b, 0x82); 492 ret = fc0012_writereg(priv, 0x0b, 0x82);
493 if (ret < 0)
494 goto err;
495 }
468 496
497 fe->tuner_priv = priv;
469 memcpy(&fe->ops.tuner_ops, &fc0012_tuner_ops, 498 memcpy(&fe->ops.tuner_ops, &fc0012_tuner_ops,
470 sizeof(struct dvb_tuner_ops)); 499 sizeof(struct dvb_tuner_ops));
471 500
501err:
502 if (fe->ops.i2c_gate_ctrl)
503 fe->ops.i2c_gate_ctrl(fe, 0);
504
505 if (ret) {
506 dev_dbg(&i2c->dev, "%s: failed: %d\n", __func__, ret);
507 kfree(priv);
508 return NULL;
509 }
510
472 return fe; 511 return fe;
473} 512}
474EXPORT_SYMBOL(fc0012_attach); 513EXPORT_SYMBOL(fc0012_attach);