1ccae7af2SMauro Carvalho Chehab /* 2ccae7af2SMauro Carvalho Chehab * Infineon TUA9001 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 17ccae7af2SMauro Carvalho Chehab #include "tua9001_priv.h" 18ccae7af2SMauro Carvalho Chehab 19ccae7af2SMauro Carvalho Chehab static int tua9001_init(struct dvb_frontend *fe) 20ccae7af2SMauro Carvalho Chehab { 21465433faSAntti Palosaari struct tua9001_dev *dev = fe->tuner_priv; 22465433faSAntti Palosaari struct i2c_client *client = dev->client; 23465433faSAntti Palosaari int ret, i; 24465433faSAntti Palosaari static const struct tua9001_reg_val data[] = { 25ccae7af2SMauro Carvalho Chehab {0x1e, 0x6512}, 26ccae7af2SMauro Carvalho Chehab {0x25, 0xb888}, 27ccae7af2SMauro Carvalho Chehab {0x39, 0x5460}, 28ccae7af2SMauro Carvalho Chehab {0x3b, 0x00c0}, 29ccae7af2SMauro Carvalho Chehab {0x3a, 0xf000}, 30ccae7af2SMauro Carvalho Chehab {0x08, 0x0000}, 31ccae7af2SMauro Carvalho Chehab {0x32, 0x0030}, 32ccae7af2SMauro Carvalho Chehab {0x41, 0x703a}, 33ccae7af2SMauro Carvalho Chehab {0x40, 0x1c78}, 34ccae7af2SMauro Carvalho Chehab {0x2c, 0x1c00}, 35ccae7af2SMauro Carvalho Chehab {0x36, 0xc013}, 36ccae7af2SMauro Carvalho Chehab {0x37, 0x6f18}, 37ccae7af2SMauro Carvalho Chehab {0x27, 0x0008}, 38ccae7af2SMauro Carvalho Chehab {0x2a, 0x0001}, 39ccae7af2SMauro Carvalho Chehab {0x34, 0x0a40}, 40ccae7af2SMauro Carvalho Chehab }; 41ccae7af2SMauro Carvalho Chehab 42465433faSAntti Palosaari dev_dbg(&client->dev, "\n"); 43e6211c7cSAntti Palosaari 4489054e37SAntti Palosaari if (fe->callback) { 45465433faSAntti Palosaari ret = fe->callback(client->adapter, 46465433faSAntti Palosaari DVB_FRONTEND_COMPONENT_TUNER, 4789054e37SAntti Palosaari TUA9001_CMD_RESETN, 0); 48465433faSAntti Palosaari if (ret) 4989054e37SAntti Palosaari goto err; 5089054e37SAntti Palosaari } 5189054e37SAntti Palosaari 52ccae7af2SMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(data); i++) { 53*dd219a87SAntti Palosaari ret = regmap_write(dev->regmap, data[i].reg, data[i].val); 54465433faSAntti Palosaari if (ret) 5596676239SAntti Palosaari goto err; 56ccae7af2SMauro Carvalho Chehab } 57465433faSAntti Palosaari return 0; 5889054e37SAntti Palosaari err: 59465433faSAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 6089054e37SAntti Palosaari return ret; 6189054e37SAntti Palosaari } 6289054e37SAntti Palosaari 6389054e37SAntti Palosaari static int tua9001_sleep(struct dvb_frontend *fe) 6489054e37SAntti Palosaari { 65465433faSAntti Palosaari struct tua9001_dev *dev = fe->tuner_priv; 66465433faSAntti Palosaari struct i2c_client *client = dev->client; 67465433faSAntti Palosaari int ret; 6889054e37SAntti Palosaari 69465433faSAntti Palosaari dev_dbg(&client->dev, "\n"); 70e6211c7cSAntti Palosaari 71465433faSAntti Palosaari if (fe->callback) { 72465433faSAntti Palosaari ret = fe->callback(client->adapter, 73465433faSAntti Palosaari DVB_FRONTEND_COMPONENT_TUNER, 7489054e37SAntti Palosaari TUA9001_CMD_RESETN, 1); 75465433faSAntti Palosaari if (ret) 76465433faSAntti Palosaari goto err; 77465433faSAntti Palosaari } 78465433faSAntti Palosaari return 0; 79465433faSAntti Palosaari err: 80465433faSAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 81ccae7af2SMauro Carvalho Chehab return ret; 82ccae7af2SMauro Carvalho Chehab } 83ccae7af2SMauro Carvalho Chehab 84ccae7af2SMauro Carvalho Chehab static int tua9001_set_params(struct dvb_frontend *fe) 85ccae7af2SMauro Carvalho Chehab { 86465433faSAntti Palosaari struct tua9001_dev *dev = fe->tuner_priv; 87465433faSAntti Palosaari struct i2c_client *client = dev->client; 88ccae7af2SMauro Carvalho Chehab struct dtv_frontend_properties *c = &fe->dtv_property_cache; 89465433faSAntti Palosaari int ret, i; 90ccae7af2SMauro Carvalho Chehab u16 val; 91ccae7af2SMauro Carvalho Chehab u32 frequency; 92465433faSAntti Palosaari struct tua9001_reg_val data[2]; 93ccae7af2SMauro Carvalho Chehab 94465433faSAntti Palosaari dev_dbg(&client->dev, 95465433faSAntti Palosaari "delivery_system=%u frequency=%u bandwidth_hz=%u\n", 96e6211c7cSAntti Palosaari c->delivery_system, c->frequency, c->bandwidth_hz); 97ccae7af2SMauro Carvalho Chehab 98ccae7af2SMauro Carvalho Chehab switch (c->delivery_system) { 99ccae7af2SMauro Carvalho Chehab case SYS_DVBT: 100ccae7af2SMauro Carvalho Chehab switch (c->bandwidth_hz) { 101ccae7af2SMauro Carvalho Chehab case 8000000: 102ccae7af2SMauro Carvalho Chehab val = 0x0000; 103ccae7af2SMauro Carvalho Chehab break; 104ccae7af2SMauro Carvalho Chehab case 7000000: 105ccae7af2SMauro Carvalho Chehab val = 0x1000; 106ccae7af2SMauro Carvalho Chehab break; 107ccae7af2SMauro Carvalho Chehab case 6000000: 108ccae7af2SMauro Carvalho Chehab val = 0x2000; 109ccae7af2SMauro Carvalho Chehab break; 110ccae7af2SMauro Carvalho Chehab case 5000000: 111ccae7af2SMauro Carvalho Chehab val = 0x3000; 112ccae7af2SMauro Carvalho Chehab break; 113ccae7af2SMauro Carvalho Chehab default: 114ccae7af2SMauro Carvalho Chehab ret = -EINVAL; 115ccae7af2SMauro Carvalho Chehab goto err; 116ccae7af2SMauro Carvalho Chehab } 117ccae7af2SMauro Carvalho Chehab break; 118ccae7af2SMauro Carvalho Chehab default: 119ccae7af2SMauro Carvalho Chehab ret = -EINVAL; 120ccae7af2SMauro Carvalho Chehab goto err; 121ccae7af2SMauro Carvalho Chehab } 122ccae7af2SMauro Carvalho Chehab 123ccae7af2SMauro Carvalho Chehab data[0].reg = 0x04; 124ccae7af2SMauro Carvalho Chehab data[0].val = val; 125ccae7af2SMauro Carvalho Chehab 126ccae7af2SMauro Carvalho Chehab frequency = (c->frequency - 150000000); 127ccae7af2SMauro Carvalho Chehab frequency /= 100; 128ccae7af2SMauro Carvalho Chehab frequency *= 48; 129ccae7af2SMauro Carvalho Chehab frequency /= 10000; 130ccae7af2SMauro Carvalho Chehab 131ccae7af2SMauro Carvalho Chehab data[1].reg = 0x1f; 132ccae7af2SMauro Carvalho Chehab data[1].val = frequency; 133ccae7af2SMauro Carvalho Chehab 13489054e37SAntti Palosaari if (fe->callback) { 135465433faSAntti Palosaari ret = fe->callback(client->adapter, 136465433faSAntti Palosaari DVB_FRONTEND_COMPONENT_TUNER, 13789054e37SAntti Palosaari TUA9001_CMD_RXEN, 0); 138465433faSAntti Palosaari if (ret) 13996676239SAntti Palosaari goto err; 14089054e37SAntti Palosaari } 14189054e37SAntti Palosaari 142ccae7af2SMauro Carvalho Chehab for (i = 0; i < ARRAY_SIZE(data); i++) { 143*dd219a87SAntti Palosaari ret = regmap_write(dev->regmap, data[i].reg, data[i].val); 144465433faSAntti Palosaari if (ret) 14596676239SAntti Palosaari goto err; 146ccae7af2SMauro Carvalho Chehab } 147ccae7af2SMauro Carvalho Chehab 14889054e37SAntti Palosaari if (fe->callback) { 149465433faSAntti Palosaari ret = fe->callback(client->adapter, 150465433faSAntti Palosaari DVB_FRONTEND_COMPONENT_TUNER, 15189054e37SAntti Palosaari TUA9001_CMD_RXEN, 1); 152465433faSAntti Palosaari if (ret) 15396676239SAntti Palosaari goto err; 15489054e37SAntti Palosaari } 155465433faSAntti Palosaari return 0; 156ccae7af2SMauro Carvalho Chehab err: 157465433faSAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 158ccae7af2SMauro Carvalho Chehab return ret; 159ccae7af2SMauro Carvalho Chehab } 160ccae7af2SMauro Carvalho Chehab 161ccae7af2SMauro Carvalho Chehab static int tua9001_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) 162ccae7af2SMauro Carvalho Chehab { 163465433faSAntti Palosaari struct tua9001_dev *dev = fe->tuner_priv; 164465433faSAntti Palosaari struct i2c_client *client = dev->client; 165e6211c7cSAntti Palosaari 166465433faSAntti Palosaari dev_dbg(&client->dev, "\n"); 167e6211c7cSAntti Palosaari 168ccae7af2SMauro Carvalho Chehab *frequency = 0; /* Zero-IF */ 169ccae7af2SMauro Carvalho Chehab return 0; 170ccae7af2SMauro Carvalho Chehab } 171ccae7af2SMauro Carvalho Chehab 172ccae7af2SMauro Carvalho Chehab static const struct dvb_tuner_ops tua9001_tuner_ops = { 173ccae7af2SMauro Carvalho Chehab .info = { 174ccae7af2SMauro Carvalho Chehab .name = "Infineon TUA9001", 175ccae7af2SMauro Carvalho Chehab .frequency_min = 170000000, 176ccae7af2SMauro Carvalho Chehab .frequency_max = 862000000, 177ccae7af2SMauro Carvalho Chehab }, 178ccae7af2SMauro Carvalho Chehab 179ccae7af2SMauro Carvalho Chehab .init = tua9001_init, 18089054e37SAntti Palosaari .sleep = tua9001_sleep, 181ccae7af2SMauro Carvalho Chehab .set_params = tua9001_set_params, 182ccae7af2SMauro Carvalho Chehab 183ccae7af2SMauro Carvalho Chehab .get_if_frequency = tua9001_get_if_frequency, 184ccae7af2SMauro Carvalho Chehab }; 185ccae7af2SMauro Carvalho Chehab 186fc851c66SAntti Palosaari static int tua9001_probe(struct i2c_client *client, 187fc851c66SAntti Palosaari const struct i2c_device_id *id) 188fc851c66SAntti Palosaari { 189465433faSAntti Palosaari struct tua9001_dev *dev; 190fc851c66SAntti Palosaari struct tua9001_platform_data *pdata = client->dev.platform_data; 191fc851c66SAntti Palosaari struct dvb_frontend *fe = pdata->dvb_frontend; 192fc851c66SAntti Palosaari int ret; 193*dd219a87SAntti Palosaari static const struct regmap_config regmap_config = { 194*dd219a87SAntti Palosaari .reg_bits = 8, 195*dd219a87SAntti Palosaari .val_bits = 16, 196*dd219a87SAntti Palosaari }; 197fc851c66SAntti Palosaari 198fc851c66SAntti Palosaari dev = kzalloc(sizeof(*dev), GFP_KERNEL); 199fc851c66SAntti Palosaari if (!dev) { 200fc851c66SAntti Palosaari ret = -ENOMEM; 201fc851c66SAntti Palosaari goto err; 202fc851c66SAntti Palosaari } 203fc851c66SAntti Palosaari 204fc851c66SAntti Palosaari dev->fe = pdata->dvb_frontend; 205*dd219a87SAntti Palosaari dev->client = client; 206*dd219a87SAntti Palosaari dev->regmap = devm_regmap_init_i2c(client, ®map_config); 207*dd219a87SAntti Palosaari if (IS_ERR(dev->regmap)) { 208*dd219a87SAntti Palosaari ret = PTR_ERR(dev->regmap); 209*dd219a87SAntti Palosaari goto err_kfree; 210*dd219a87SAntti Palosaari } 211fc851c66SAntti Palosaari 212fc851c66SAntti Palosaari if (fe->callback) { 213fc851c66SAntti Palosaari ret = fe->callback(client->adapter, 214fc851c66SAntti Palosaari DVB_FRONTEND_COMPONENT_TUNER, 215fc851c66SAntti Palosaari TUA9001_CMD_CEN, 1); 216fc851c66SAntti Palosaari if (ret) 217fc851c66SAntti Palosaari goto err_kfree; 218fc851c66SAntti Palosaari 219fc851c66SAntti Palosaari ret = fe->callback(client->adapter, 220fc851c66SAntti Palosaari DVB_FRONTEND_COMPONENT_TUNER, 221fc851c66SAntti Palosaari TUA9001_CMD_RXEN, 0); 222fc851c66SAntti Palosaari if (ret) 223fc851c66SAntti Palosaari goto err_kfree; 224fc851c66SAntti Palosaari 225fc851c66SAntti Palosaari ret = fe->callback(client->adapter, 226fc851c66SAntti Palosaari DVB_FRONTEND_COMPONENT_TUNER, 227fc851c66SAntti Palosaari TUA9001_CMD_RESETN, 1); 228fc851c66SAntti Palosaari if (ret) 229fc851c66SAntti Palosaari goto err_kfree; 230fc851c66SAntti Palosaari } 231fc851c66SAntti Palosaari 232fc851c66SAntti Palosaari fe->tuner_priv = dev; 233fc851c66SAntti Palosaari memcpy(&fe->ops.tuner_ops, &tua9001_tuner_ops, 234fc851c66SAntti Palosaari sizeof(struct dvb_tuner_ops)); 235fc851c66SAntti Palosaari i2c_set_clientdata(client, dev); 236fc851c66SAntti Palosaari 237fc851c66SAntti Palosaari dev_info(&client->dev, "Infineon TUA9001 successfully attached\n"); 238fc851c66SAntti Palosaari return 0; 239fc851c66SAntti Palosaari err_kfree: 240fc851c66SAntti Palosaari kfree(dev); 241fc851c66SAntti Palosaari err: 242fc851c66SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 243fc851c66SAntti Palosaari return ret; 244fc851c66SAntti Palosaari } 245fc851c66SAntti Palosaari 246fc851c66SAntti Palosaari static int tua9001_remove(struct i2c_client *client) 247fc851c66SAntti Palosaari { 248465433faSAntti Palosaari struct tua9001_dev *dev = i2c_get_clientdata(client); 249fc851c66SAntti Palosaari struct dvb_frontend *fe = dev->fe; 250fc851c66SAntti Palosaari int ret; 251fc851c66SAntti Palosaari 252fc851c66SAntti Palosaari dev_dbg(&client->dev, "\n"); 253fc851c66SAntti Palosaari 254fc851c66SAntti Palosaari if (fe->callback) { 255fc851c66SAntti Palosaari ret = fe->callback(client->adapter, 256fc851c66SAntti Palosaari DVB_FRONTEND_COMPONENT_TUNER, 257fc851c66SAntti Palosaari TUA9001_CMD_CEN, 0); 258fc851c66SAntti Palosaari if (ret) 259fc851c66SAntti Palosaari goto err_kfree; 260fc851c66SAntti Palosaari } 261fc851c66SAntti Palosaari kfree(dev); 262fc851c66SAntti Palosaari return 0; 263fc851c66SAntti Palosaari err_kfree: 264fc851c66SAntti Palosaari kfree(dev); 265fc851c66SAntti Palosaari dev_dbg(&client->dev, "failed=%d\n", ret); 266fc851c66SAntti Palosaari return ret; 267fc851c66SAntti Palosaari } 268fc851c66SAntti Palosaari 269fc851c66SAntti Palosaari static const struct i2c_device_id tua9001_id_table[] = { 270fc851c66SAntti Palosaari {"tua9001", 0}, 271fc851c66SAntti Palosaari {} 272fc851c66SAntti Palosaari }; 273fc851c66SAntti Palosaari MODULE_DEVICE_TABLE(i2c, tua9001_id_table); 274fc851c66SAntti Palosaari 275fc851c66SAntti Palosaari static struct i2c_driver tua9001_driver = { 276fc851c66SAntti Palosaari .driver = { 277fc851c66SAntti Palosaari .owner = THIS_MODULE, 278fc851c66SAntti Palosaari .name = "tua9001", 279fc851c66SAntti Palosaari .suppress_bind_attrs = true, 280fc851c66SAntti Palosaari }, 281fc851c66SAntti Palosaari .probe = tua9001_probe, 282fc851c66SAntti Palosaari .remove = tua9001_remove, 283fc851c66SAntti Palosaari .id_table = tua9001_id_table, 284fc851c66SAntti Palosaari }; 285fc851c66SAntti Palosaari 286fc851c66SAntti Palosaari module_i2c_driver(tua9001_driver); 287fc851c66SAntti Palosaari 288ccae7af2SMauro Carvalho Chehab MODULE_DESCRIPTION("Infineon TUA9001 silicon tuner driver"); 289ccae7af2SMauro Carvalho Chehab MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 290ccae7af2SMauro Carvalho Chehab MODULE_LICENSE("GPL"); 291