1ccae7af2SMauro Carvalho Chehab /* 2ccae7af2SMauro Carvalho Chehab * Infineon TUA 9001 silicon tuner driver 3ccae7af2SMauro Carvalho Chehab * 4ccae7af2SMauro Carvalho Chehab * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> 5ccae7af2SMauro Carvalho Chehab * 6ccae7af2SMauro Carvalho Chehab * This program is free software; you can redistribute it and/or modify 7ccae7af2SMauro Carvalho Chehab * it under the terms of the GNU General Public License as published by 8ccae7af2SMauro Carvalho Chehab * the Free Software Foundation; either version 2 of the License, or 9ccae7af2SMauro Carvalho Chehab * (at your option) any later version. 10ccae7af2SMauro Carvalho Chehab * 11ccae7af2SMauro Carvalho Chehab * This program is distributed in the hope that it will be useful, 12ccae7af2SMauro Carvalho Chehab * but WITHOUT ANY WARRANTY; without even the implied warranty of 13ccae7af2SMauro Carvalho Chehab * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14ccae7af2SMauro Carvalho Chehab * GNU General Public License for more details. 15ccae7af2SMauro Carvalho Chehab * 16ccae7af2SMauro Carvalho Chehab * You should have received a copy of the GNU General Public License along 17ccae7af2SMauro Carvalho Chehab * with this program; if not, write to the Free Software Foundation, Inc., 18ccae7af2SMauro Carvalho Chehab * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19ccae7af2SMauro Carvalho Chehab */ 20ccae7af2SMauro Carvalho Chehab 21ccae7af2SMauro Carvalho Chehab #include "tua9001.h" 22ccae7af2SMauro Carvalho Chehab #include "tua9001_priv.h" 23ccae7af2SMauro Carvalho Chehab 24ccae7af2SMauro Carvalho Chehab /* write register */ 25ccae7af2SMauro Carvalho Chehab static int tua9001_wr_reg(struct tua9001_priv *priv, u8 reg, u16 val) 26ccae7af2SMauro Carvalho Chehab { 27ccae7af2SMauro Carvalho Chehab int ret; 28ccae7af2SMauro Carvalho Chehab u8 buf[3] = { reg, (val >> 8) & 0xff, (val >> 0) & 0xff }; 29ccae7af2SMauro Carvalho Chehab struct i2c_msg msg[1] = { 30ccae7af2SMauro Carvalho Chehab { 31*fc851c66SAntti Palosaari .addr = priv->i2c_addr, 32ccae7af2SMauro Carvalho Chehab .flags = 0, 33ccae7af2SMauro Carvalho Chehab .len = sizeof(buf), 34ccae7af2SMauro Carvalho Chehab .buf = buf, 35ccae7af2SMauro Carvalho Chehab } 36ccae7af2SMauro Carvalho Chehab }; 37ccae7af2SMauro Carvalho Chehab 38ccae7af2SMauro Carvalho Chehab ret = i2c_transfer(priv->i2c, msg, 1); 39ccae7af2SMauro Carvalho Chehab if (ret == 1) { 40ccae7af2SMauro Carvalho Chehab ret = 0; 41ccae7af2SMauro Carvalho Chehab } else { 42e6211c7cSAntti Palosaari dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x\n", 43e6211c7cSAntti Palosaari KBUILD_MODNAME, ret, reg); 44ccae7af2SMauro Carvalho Chehab ret = -EREMOTEIO; 45ccae7af2SMauro Carvalho Chehab } 46ccae7af2SMauro Carvalho Chehab 47ccae7af2SMauro Carvalho Chehab return ret; 48ccae7af2SMauro Carvalho Chehab } 49ccae7af2SMauro Carvalho Chehab 50ccae7af2SMauro Carvalho Chehab static int tua9001_release(struct dvb_frontend *fe) 51ccae7af2SMauro Carvalho Chehab { 5289054e37SAntti Palosaari struct tua9001_priv *priv = fe->tuner_priv; 5389054e37SAntti Palosaari int ret = 0; 5489054e37SAntti Palosaari 55e6211c7cSAntti Palosaari dev_dbg(&priv->i2c->dev, "%s:\n", __func__); 56e6211c7cSAntti Palosaari 5789054e37SAntti Palosaari if (fe->callback) 5889054e37SAntti Palosaari ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, 5989054e37SAntti Palosaari TUA9001_CMD_CEN, 0); 6089054e37SAntti Palosaari 61ccae7af2SMauro Carvalho Chehab kfree(fe->tuner_priv); 62ccae7af2SMauro Carvalho Chehab fe->tuner_priv = NULL; 63ccae7af2SMauro Carvalho Chehab 6489054e37SAntti Palosaari return ret; 65ccae7af2SMauro Carvalho Chehab } 66ccae7af2SMauro Carvalho Chehab 67ccae7af2SMauro Carvalho Chehab static int tua9001_init(struct dvb_frontend *fe) 68ccae7af2SMauro Carvalho Chehab { 69ccae7af2SMauro Carvalho Chehab struct tua9001_priv *priv = fe->tuner_priv; 70ccae7af2SMauro Carvalho Chehab int ret = 0; 71ccae7af2SMauro Carvalho Chehab u8 i; 72ccae7af2SMauro Carvalho Chehab struct reg_val data[] = { 73ccae7af2SMauro Carvalho Chehab { 0x1e, 0x6512 }, 74ccae7af2SMauro Carvalho Chehab { 0x25, 0xb888 }, 75ccae7af2SMauro Carvalho Chehab { 0x39, 0x5460 }, 76ccae7af2SMauro Carvalho Chehab { 0x3b, 0x00c0 }, 77ccae7af2SMauro Carvalho Chehab { 0x3a, 0xf000 }, 78ccae7af2SMauro Carvalho Chehab { 0x08, 0x0000 }, 79ccae7af2SMauro Carvalho Chehab { 0x32, 0x0030 }, 80ccae7af2SMauro Carvalho Chehab { 0x41, 0x703a }, 81ccae7af2SMauro Carvalho Chehab { 0x40, 0x1c78 }, 82ccae7af2SMauro Carvalho Chehab { 0x2c, 0x1c00 }, 83ccae7af2SMauro Carvalho Chehab { 0x36, 0xc013 }, 84ccae7af2SMauro Carvalho Chehab { 0x37, 0x6f18 }, 85ccae7af2SMauro Carvalho Chehab { 0x27, 0x0008 }, 86ccae7af2SMauro Carvalho Chehab { 0x2a, 0x0001 }, 87ccae7af2SMauro Carvalho Chehab { 0x34, 0x0a40 }, 88ccae7af2SMauro Carvalho Chehab }; 89ccae7af2SMauro Carvalho Chehab 90e6211c7cSAntti Palosaari dev_dbg(&priv->i2c->dev, "%s:\n", __func__); 91e6211c7cSAntti Palosaari 9289054e37SAntti Palosaari if (fe->callback) { 9389054e37SAntti Palosaari ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, 9489054e37SAntti Palosaari TUA9001_CMD_RESETN, 0); 9589054e37SAntti Palosaari if (ret < 0) 9689054e37SAntti Palosaari goto err; 9789054e37SAntti Palosaari } 9889054e37SAntti Palosaari 99ccae7af2SMauro Carvalho Chehab if (fe->ops.i2c_gate_ctrl) 100ccae7af2SMauro Carvalho Chehab fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */ 101ccae7af2SMauro Carvalho Chehab 102ccae7af2SMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(data); i++) { 103ccae7af2SMauro Carvalho Chehab ret = tua9001_wr_reg(priv, data[i].reg, data[i].val); 10489054e37SAntti Palosaari if (ret < 0) 10589054e37SAntti Palosaari goto err_i2c_gate_ctrl; 106ccae7af2SMauro Carvalho Chehab } 107ccae7af2SMauro Carvalho Chehab 10889054e37SAntti Palosaari err_i2c_gate_ctrl: 109ccae7af2SMauro Carvalho Chehab if (fe->ops.i2c_gate_ctrl) 110ccae7af2SMauro Carvalho Chehab fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */ 11189054e37SAntti Palosaari err: 11289054e37SAntti Palosaari if (ret < 0) 113e6211c7cSAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); 11489054e37SAntti Palosaari 11589054e37SAntti Palosaari return ret; 11689054e37SAntti Palosaari } 11789054e37SAntti Palosaari 11889054e37SAntti Palosaari static int tua9001_sleep(struct dvb_frontend *fe) 11989054e37SAntti Palosaari { 12089054e37SAntti Palosaari struct tua9001_priv *priv = fe->tuner_priv; 12189054e37SAntti Palosaari int ret = 0; 12289054e37SAntti Palosaari 123e6211c7cSAntti Palosaari dev_dbg(&priv->i2c->dev, "%s:\n", __func__); 124e6211c7cSAntti Palosaari 12589054e37SAntti Palosaari if (fe->callback) 12689054e37SAntti Palosaari ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, 12789054e37SAntti Palosaari TUA9001_CMD_RESETN, 1); 128ccae7af2SMauro Carvalho Chehab 129ccae7af2SMauro Carvalho Chehab if (ret < 0) 130e6211c7cSAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); 131ccae7af2SMauro Carvalho Chehab 132ccae7af2SMauro Carvalho Chehab return ret; 133ccae7af2SMauro Carvalho Chehab } 134ccae7af2SMauro Carvalho Chehab 135ccae7af2SMauro Carvalho Chehab static int tua9001_set_params(struct dvb_frontend *fe) 136ccae7af2SMauro Carvalho Chehab { 137ccae7af2SMauro Carvalho Chehab struct tua9001_priv *priv = fe->tuner_priv; 138ccae7af2SMauro Carvalho Chehab struct dtv_frontend_properties *c = &fe->dtv_property_cache; 13959e54059SMauro Carvalho Chehab int ret = 0, i; 140ccae7af2SMauro Carvalho Chehab u16 val; 141ccae7af2SMauro Carvalho Chehab u32 frequency; 142ccae7af2SMauro Carvalho Chehab struct reg_val data[2]; 143ccae7af2SMauro Carvalho Chehab 144e6211c7cSAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d frequency=%d " \ 145e6211c7cSAntti Palosaari "bandwidth_hz=%d\n", __func__, 146e6211c7cSAntti Palosaari c->delivery_system, c->frequency, c->bandwidth_hz); 147ccae7af2SMauro Carvalho Chehab 148ccae7af2SMauro Carvalho Chehab switch (c->delivery_system) { 149ccae7af2SMauro Carvalho Chehab case SYS_DVBT: 150ccae7af2SMauro Carvalho Chehab switch (c->bandwidth_hz) { 151ccae7af2SMauro Carvalho Chehab case 8000000: 152ccae7af2SMauro Carvalho Chehab val = 0x0000; 153ccae7af2SMauro Carvalho Chehab break; 154ccae7af2SMauro Carvalho Chehab case 7000000: 155ccae7af2SMauro Carvalho Chehab val = 0x1000; 156ccae7af2SMauro Carvalho Chehab break; 157ccae7af2SMauro Carvalho Chehab case 6000000: 158ccae7af2SMauro Carvalho Chehab val = 0x2000; 159ccae7af2SMauro Carvalho Chehab break; 160ccae7af2SMauro Carvalho Chehab case 5000000: 161ccae7af2SMauro Carvalho Chehab val = 0x3000; 162ccae7af2SMauro Carvalho Chehab break; 163ccae7af2SMauro Carvalho Chehab default: 164ccae7af2SMauro Carvalho Chehab ret = -EINVAL; 165ccae7af2SMauro Carvalho Chehab goto err; 166ccae7af2SMauro Carvalho Chehab } 167ccae7af2SMauro Carvalho Chehab break; 168ccae7af2SMauro Carvalho Chehab default: 169ccae7af2SMauro Carvalho Chehab ret = -EINVAL; 170ccae7af2SMauro Carvalho Chehab goto err; 171ccae7af2SMauro Carvalho Chehab } 172ccae7af2SMauro Carvalho Chehab 173ccae7af2SMauro Carvalho Chehab data[0].reg = 0x04; 174ccae7af2SMauro Carvalho Chehab data[0].val = val; 175ccae7af2SMauro Carvalho Chehab 176ccae7af2SMauro Carvalho Chehab frequency = (c->frequency - 150000000); 177ccae7af2SMauro Carvalho Chehab frequency /= 100; 178ccae7af2SMauro Carvalho Chehab frequency *= 48; 179ccae7af2SMauro Carvalho Chehab frequency /= 10000; 180ccae7af2SMauro Carvalho Chehab 181ccae7af2SMauro Carvalho Chehab data[1].reg = 0x1f; 182ccae7af2SMauro Carvalho Chehab data[1].val = frequency; 183ccae7af2SMauro Carvalho Chehab 184ccae7af2SMauro Carvalho Chehab if (fe->ops.i2c_gate_ctrl) 185ccae7af2SMauro Carvalho Chehab fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */ 186ccae7af2SMauro Carvalho Chehab 18789054e37SAntti Palosaari if (fe->callback) { 18889054e37SAntti Palosaari ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, 18989054e37SAntti Palosaari TUA9001_CMD_RXEN, 0); 19089054e37SAntti Palosaari if (ret < 0) 19189054e37SAntti Palosaari goto err_i2c_gate_ctrl; 19289054e37SAntti Palosaari } 19389054e37SAntti Palosaari 194ccae7af2SMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(data); i++) { 195ccae7af2SMauro Carvalho Chehab ret = tua9001_wr_reg(priv, data[i].reg, data[i].val); 196ccae7af2SMauro Carvalho Chehab if (ret < 0) 19789054e37SAntti Palosaari goto err_i2c_gate_ctrl; 198ccae7af2SMauro Carvalho Chehab } 199ccae7af2SMauro Carvalho Chehab 20089054e37SAntti Palosaari if (fe->callback) { 20189054e37SAntti Palosaari ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, 20289054e37SAntti Palosaari TUA9001_CMD_RXEN, 1); 20389054e37SAntti Palosaari if (ret < 0) 20489054e37SAntti Palosaari goto err_i2c_gate_ctrl; 20589054e37SAntti Palosaari } 20689054e37SAntti Palosaari 20789054e37SAntti Palosaari err_i2c_gate_ctrl: 208ccae7af2SMauro Carvalho Chehab if (fe->ops.i2c_gate_ctrl) 209ccae7af2SMauro Carvalho Chehab fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */ 210ccae7af2SMauro Carvalho Chehab err: 211ccae7af2SMauro Carvalho Chehab if (ret < 0) 212e6211c7cSAntti Palosaari dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret); 213ccae7af2SMauro Carvalho Chehab 214ccae7af2SMauro Carvalho Chehab return ret; 215ccae7af2SMauro Carvalho Chehab } 216ccae7af2SMauro Carvalho Chehab 217ccae7af2SMauro Carvalho Chehab static int tua9001_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) 218ccae7af2SMauro Carvalho Chehab { 219e6211c7cSAntti Palosaari struct tua9001_priv *priv = fe->tuner_priv; 220e6211c7cSAntti Palosaari 221e6211c7cSAntti Palosaari dev_dbg(&priv->i2c->dev, "%s:\n", __func__); 222e6211c7cSAntti Palosaari 223ccae7af2SMauro Carvalho Chehab *frequency = 0; /* Zero-IF */ 224ccae7af2SMauro Carvalho Chehab 225ccae7af2SMauro Carvalho Chehab return 0; 226ccae7af2SMauro Carvalho Chehab } 227ccae7af2SMauro Carvalho Chehab 228ccae7af2SMauro Carvalho Chehab static const struct dvb_tuner_ops tua9001_tuner_ops = { 229ccae7af2SMauro Carvalho Chehab .info = { 230ccae7af2SMauro Carvalho Chehab .name = "Infineon TUA 9001", 231ccae7af2SMauro Carvalho Chehab 232ccae7af2SMauro Carvalho Chehab .frequency_min = 170000000, 233ccae7af2SMauro Carvalho Chehab .frequency_max = 862000000, 234ccae7af2SMauro Carvalho Chehab .frequency_step = 0, 235ccae7af2SMauro Carvalho Chehab }, 236ccae7af2SMauro Carvalho Chehab 237ccae7af2SMauro Carvalho Chehab .release = tua9001_release, 238ccae7af2SMauro Carvalho Chehab 239ccae7af2SMauro Carvalho Chehab .init = tua9001_init, 24089054e37SAntti Palosaari .sleep = tua9001_sleep, 241ccae7af2SMauro Carvalho Chehab .set_params = tua9001_set_params, 242ccae7af2SMauro Carvalho Chehab 243ccae7af2SMauro Carvalho Chehab .get_if_frequency = tua9001_get_if_frequency, 244ccae7af2SMauro Carvalho Chehab }; 245ccae7af2SMauro Carvalho Chehab 246ccae7af2SMauro Carvalho Chehab struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe, 247ccae7af2SMauro Carvalho Chehab struct i2c_adapter *i2c, struct tua9001_config *cfg) 248ccae7af2SMauro Carvalho Chehab { 249ccae7af2SMauro Carvalho Chehab struct tua9001_priv *priv = NULL; 25089054e37SAntti Palosaari int ret; 251ccae7af2SMauro Carvalho Chehab 252ccae7af2SMauro Carvalho Chehab priv = kzalloc(sizeof(struct tua9001_priv), GFP_KERNEL); 253ccae7af2SMauro Carvalho Chehab if (priv == NULL) 254ccae7af2SMauro Carvalho Chehab return NULL; 255ccae7af2SMauro Carvalho Chehab 256*fc851c66SAntti Palosaari priv->i2c_addr = cfg->i2c_addr; 257ccae7af2SMauro Carvalho Chehab priv->i2c = i2c; 258ccae7af2SMauro Carvalho Chehab 25989054e37SAntti Palosaari if (fe->callback) { 26089054e37SAntti Palosaari ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, 26189054e37SAntti Palosaari TUA9001_CMD_CEN, 1); 26289054e37SAntti Palosaari if (ret < 0) 26389054e37SAntti Palosaari goto err; 26469504793SAntti Palosaari 26569504793SAntti Palosaari ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, 26669504793SAntti Palosaari TUA9001_CMD_RXEN, 0); 26769504793SAntti Palosaari if (ret < 0) 26869504793SAntti Palosaari goto err; 26969504793SAntti Palosaari 27069504793SAntti Palosaari ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER, 27169504793SAntti Palosaari TUA9001_CMD_RESETN, 1); 27269504793SAntti Palosaari if (ret < 0) 27369504793SAntti Palosaari goto err; 27489054e37SAntti Palosaari } 27589054e37SAntti Palosaari 276e6211c7cSAntti Palosaari dev_info(&priv->i2c->dev, 277e6211c7cSAntti Palosaari "%s: Infineon TUA 9001 successfully attached\n", 278e6211c7cSAntti Palosaari KBUILD_MODNAME); 279ccae7af2SMauro Carvalho Chehab 280ccae7af2SMauro Carvalho Chehab memcpy(&fe->ops.tuner_ops, &tua9001_tuner_ops, 281ccae7af2SMauro Carvalho Chehab sizeof(struct dvb_tuner_ops)); 282ccae7af2SMauro Carvalho Chehab 283ccae7af2SMauro Carvalho Chehab fe->tuner_priv = priv; 284ccae7af2SMauro Carvalho Chehab return fe; 28589054e37SAntti Palosaari err: 286e6211c7cSAntti Palosaari dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret); 28789054e37SAntti Palosaari kfree(priv); 28889054e37SAntti Palosaari return NULL; 289ccae7af2SMauro Carvalho Chehab } 290ccae7af2SMauro Carvalho Chehab EXPORT_SYMBOL(tua9001_attach); 291ccae7af2SMauro Carvalho Chehab 292*fc851c66SAntti Palosaari static int tua9001_probe(struct i2c_client *client, 293*fc851c66SAntti Palosaari const struct i2c_device_id *id) 294*fc851c66SAntti Palosaari { 295*fc851c66SAntti Palosaari struct tua9001_priv *dev; 296*fc851c66SAntti Palosaari struct tua9001_platform_data *pdata = client->dev.platform_data; 297*fc851c66SAntti Palosaari struct dvb_frontend *fe = pdata->dvb_frontend; 298*fc851c66SAntti Palosaari int ret; 299*fc851c66SAntti Palosaari 300*fc851c66SAntti Palosaari dev = kzalloc(sizeof(*dev), GFP_KERNEL); 301*fc851c66SAntti Palosaari if (!dev) { 302*fc851c66SAntti Palosaari ret = -ENOMEM; 303*fc851c66SAntti Palosaari goto err; 304*fc851c66SAntti Palosaari } 305*fc851c66SAntti Palosaari 306*fc851c66SAntti Palosaari dev->client = client; 307*fc851c66SAntti Palosaari dev->i2c_addr = client->addr; 308*fc851c66SAntti Palosaari dev->i2c = client->adapter; 309*fc851c66SAntti Palosaari dev->fe = pdata->dvb_frontend; 310*fc851c66SAntti Palosaari 311*fc851c66SAntti Palosaari if (fe->callback) { 312*fc851c66SAntti Palosaari ret = fe->callback(client->adapter, 313*fc851c66SAntti Palosaari DVB_FRONTEND_COMPONENT_TUNER, 314*fc851c66SAntti Palosaari TUA9001_CMD_CEN, 1); 315*fc851c66SAntti Palosaari if (ret) 316*fc851c66SAntti Palosaari goto err_kfree; 317*fc851c66SAntti Palosaari 318*fc851c66SAntti Palosaari ret = fe->callback(client->adapter, 319*fc851c66SAntti Palosaari DVB_FRONTEND_COMPONENT_TUNER, 320*fc851c66SAntti Palosaari TUA9001_CMD_RXEN, 0); 321*fc851c66SAntti Palosaari if (ret) 322*fc851c66SAntti Palosaari goto err_kfree; 323*fc851c66SAntti Palosaari 324*fc851c66SAntti Palosaari ret = fe->callback(client->adapter, 325*fc851c66SAntti Palosaari DVB_FRONTEND_COMPONENT_TUNER, 326*fc851c66SAntti Palosaari TUA9001_CMD_RESETN, 1); 327*fc851c66SAntti Palosaari if (ret) 328*fc851c66SAntti Palosaari goto err_kfree; 329*fc851c66SAntti Palosaari } 330*fc851c66SAntti Palosaari 331*fc851c66SAntti Palosaari fe->tuner_priv = dev; 332*fc851c66SAntti Palosaari memcpy(&fe->ops.tuner_ops, &tua9001_tuner_ops, 333*fc851c66SAntti Palosaari sizeof(struct dvb_tuner_ops)); 334*fc851c66SAntti Palosaari fe->ops.tuner_ops.release = NULL; 335*fc851c66SAntti Palosaari i2c_set_clientdata(client, dev); 336*fc851c66SAntti Palosaari 337*fc851c66SAntti Palosaari dev_info(&client->dev, "Infineon TUA 9001 successfully attached\n"); 338*fc851c66SAntti Palosaari return 0; 339*fc851c66SAntti Palosaari err_kfree: 340*fc851c66SAntti Palosaari kfree(dev); 341*fc851c66SAntti Palosaari err: 342*fc851c66SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 343*fc851c66SAntti Palosaari return ret; 344*fc851c66SAntti Palosaari } 345*fc851c66SAntti Palosaari 346*fc851c66SAntti Palosaari static int tua9001_remove(struct i2c_client *client) 347*fc851c66SAntti Palosaari { 348*fc851c66SAntti Palosaari struct tua9001_priv *dev = i2c_get_clientdata(client); 349*fc851c66SAntti Palosaari struct dvb_frontend *fe = dev->fe; 350*fc851c66SAntti Palosaari int ret; 351*fc851c66SAntti Palosaari 352*fc851c66SAntti Palosaari dev_dbg(&client->dev, "\n"); 353*fc851c66SAntti Palosaari 354*fc851c66SAntti Palosaari if (fe->callback) { 355*fc851c66SAntti Palosaari ret = fe->callback(client->adapter, 356*fc851c66SAntti Palosaari DVB_FRONTEND_COMPONENT_TUNER, 357*fc851c66SAntti Palosaari TUA9001_CMD_CEN, 0); 358*fc851c66SAntti Palosaari if (ret) 359*fc851c66SAntti Palosaari goto err_kfree; 360*fc851c66SAntti Palosaari } 361*fc851c66SAntti Palosaari kfree(dev); 362*fc851c66SAntti Palosaari return 0; 363*fc851c66SAntti Palosaari err_kfree: 364*fc851c66SAntti Palosaari kfree(dev); 365*fc851c66SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 366*fc851c66SAntti Palosaari return ret; 367*fc851c66SAntti Palosaari } 368*fc851c66SAntti Palosaari 369*fc851c66SAntti Palosaari static const struct i2c_device_id tua9001_id_table[] = { 370*fc851c66SAntti Palosaari {"tua9001", 0}, 371*fc851c66SAntti Palosaari {} 372*fc851c66SAntti Palosaari }; 373*fc851c66SAntti Palosaari MODULE_DEVICE_TABLE(i2c, tua9001_id_table); 374*fc851c66SAntti Palosaari 375*fc851c66SAntti Palosaari static struct i2c_driver tua9001_driver = { 376*fc851c66SAntti Palosaari .driver = { 377*fc851c66SAntti Palosaari .owner = THIS_MODULE, 378*fc851c66SAntti Palosaari .name = "tua9001", 379*fc851c66SAntti Palosaari .suppress_bind_attrs = true, 380*fc851c66SAntti Palosaari }, 381*fc851c66SAntti Palosaari .probe = tua9001_probe, 382*fc851c66SAntti Palosaari .remove = tua9001_remove, 383*fc851c66SAntti Palosaari .id_table = tua9001_id_table, 384*fc851c66SAntti Palosaari }; 385*fc851c66SAntti Palosaari 386*fc851c66SAntti Palosaari module_i2c_driver(tua9001_driver); 387*fc851c66SAntti Palosaari 388ccae7af2SMauro Carvalho Chehab MODULE_DESCRIPTION("Infineon TUA 9001 silicon tuner driver"); 389ccae7af2SMauro Carvalho Chehab MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 390ccae7af2SMauro Carvalho Chehab MODULE_LICENSE("GPL"); 391