diff options
author | Antti Palosaari <crope@iki.fi> | 2012-12-09 13:28:45 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-01-06 09:07:57 -0200 |
commit | 44ff69cd95308c115134f0546317b584fe1bf5b2 (patch) | |
tree | 86990b5113acde11f5e60e3963d2f0696ca851f7 /drivers/media/tuners | |
parent | 3a98477200b44328e50a5c0830f92fd5cdc1ea9b (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>
Diffstat (limited to 'drivers/media/tuners')
-rw-r--r-- | drivers/media/tuners/fc0012.c | 59 |
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 = { struct dvb_frontend *fc0012_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct fc0012_config *cfg) { - struct fc0012_priv *priv = NULL; + struct fc0012_priv *priv; + int ret; + u8 chip_id; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); priv = kzalloc(sizeof(struct fc0012_priv), GFP_KERNEL); - if (priv == NULL) - return NULL; + if (!priv) { + ret = -ENOMEM; + dev_err(&i2c->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); + goto err; + } - priv->i2c = i2c; priv->cfg = cfg; + priv->i2c = i2c; - info("Fitipower FC0012 successfully attached."); + /* check if the tuner is there */ + ret = fc0012_readreg(priv, 0x00, &chip_id); + if (ret < 0) + goto err; - fe->tuner_priv = priv; + dev_dbg(&i2c->dev, "%s: chip_id=%02x\n", __func__, chip_id); - if (priv->cfg->loop_through) - fc0012_writereg(priv, 0x09, 0x6f); + switch (chip_id) { + case 0xa1: + break; + default: + ret = -ENODEV; + goto err; + } + + dev_info(&i2c->dev, "%s: Fitipower FC0012 successfully identified\n", + KBUILD_MODNAME); + + if (priv->cfg->loop_through) { + ret = fc0012_writereg(priv, 0x09, 0x6f); + if (ret < 0) + goto err; + } /* * TODO: Clock out en or div? * For dual tuner configuration clearing bit [0] is required. */ - if (priv->cfg->clock_out) - fc0012_writereg(priv, 0x0b, 0x82); + if (priv->cfg->clock_out) { + ret = fc0012_writereg(priv, 0x0b, 0x82); + if (ret < 0) + goto err; + } + fe->tuner_priv = priv; memcpy(&fe->ops.tuner_ops, &fc0012_tuner_ops, sizeof(struct dvb_tuner_ops)); +err: + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + if (ret) { + dev_dbg(&i2c->dev, "%s: failed: %d\n", __func__, ret); + kfree(priv); + return NULL; + } + return fe; } EXPORT_SYMBOL(fc0012_attach); |