1 /* 2 * Infineon TUA9001 silicon tuner driver 3 * 4 * Copyright (C) 2009 Antti Palosaari <crope@iki.fi> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 */ 16 17 #include "tua9001_priv.h" 18 19 static int tua9001_init(struct dvb_frontend *fe) 20 { 21 struct tua9001_dev *dev = fe->tuner_priv; 22 struct i2c_client *client = dev->client; 23 int ret, i; 24 static const struct tua9001_reg_val data[] = { 25 {0x1e, 0x6512}, 26 {0x25, 0xb888}, 27 {0x39, 0x5460}, 28 {0x3b, 0x00c0}, 29 {0x3a, 0xf000}, 30 {0x08, 0x0000}, 31 {0x32, 0x0030}, 32 {0x41, 0x703a}, 33 {0x40, 0x1c78}, 34 {0x2c, 0x1c00}, 35 {0x36, 0xc013}, 36 {0x37, 0x6f18}, 37 {0x27, 0x0008}, 38 {0x2a, 0x0001}, 39 {0x34, 0x0a40}, 40 }; 41 42 dev_dbg(&client->dev, "\n"); 43 44 if (fe->callback) { 45 ret = fe->callback(client->adapter, 46 DVB_FRONTEND_COMPONENT_TUNER, 47 TUA9001_CMD_RESETN, 0); 48 if (ret) 49 goto err; 50 } 51 52 for (i = 0; i < ARRAY_SIZE(data); i++) { 53 ret = regmap_write(dev->regmap, data[i].reg, data[i].val); 54 if (ret) 55 goto err; 56 } 57 return 0; 58 err: 59 dev_dbg(&client->dev, "failed=%d\n", ret); 60 return ret; 61 } 62 63 static int tua9001_sleep(struct dvb_frontend *fe) 64 { 65 struct tua9001_dev *dev = fe->tuner_priv; 66 struct i2c_client *client = dev->client; 67 int ret; 68 69 dev_dbg(&client->dev, "\n"); 70 71 if (fe->callback) { 72 ret = fe->callback(client->adapter, 73 DVB_FRONTEND_COMPONENT_TUNER, 74 TUA9001_CMD_RESETN, 1); 75 if (ret) 76 goto err; 77 } 78 return 0; 79 err: 80 dev_dbg(&client->dev, "failed=%d\n", ret); 81 return ret; 82 } 83 84 static int tua9001_set_params(struct dvb_frontend *fe) 85 { 86 struct tua9001_dev *dev = fe->tuner_priv; 87 struct i2c_client *client = dev->client; 88 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 89 int ret, i; 90 u16 val; 91 struct tua9001_reg_val data[2]; 92 93 dev_dbg(&client->dev, 94 "delivery_system=%u frequency=%u bandwidth_hz=%u\n", 95 c->delivery_system, c->frequency, c->bandwidth_hz); 96 97 switch (c->delivery_system) { 98 case SYS_DVBT: 99 switch (c->bandwidth_hz) { 100 case 8000000: 101 val = 0x0000; 102 break; 103 case 7000000: 104 val = 0x1000; 105 break; 106 case 6000000: 107 val = 0x2000; 108 break; 109 case 5000000: 110 val = 0x3000; 111 break; 112 default: 113 ret = -EINVAL; 114 goto err; 115 } 116 break; 117 default: 118 ret = -EINVAL; 119 goto err; 120 } 121 122 data[0].reg = 0x04; 123 data[0].val = val; 124 data[1].reg = 0x1f; 125 data[1].val = div_u64((u64) (c->frequency - 150000000) * 48, 1000000); 126 127 if (fe->callback) { 128 ret = fe->callback(client->adapter, 129 DVB_FRONTEND_COMPONENT_TUNER, 130 TUA9001_CMD_RXEN, 0); 131 if (ret) 132 goto err; 133 } 134 135 for (i = 0; i < ARRAY_SIZE(data); i++) { 136 ret = regmap_write(dev->regmap, data[i].reg, data[i].val); 137 if (ret) 138 goto err; 139 } 140 141 if (fe->callback) { 142 ret = fe->callback(client->adapter, 143 DVB_FRONTEND_COMPONENT_TUNER, 144 TUA9001_CMD_RXEN, 1); 145 if (ret) 146 goto err; 147 } 148 return 0; 149 err: 150 dev_dbg(&client->dev, "failed=%d\n", ret); 151 return ret; 152 } 153 154 static int tua9001_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) 155 { 156 struct tua9001_dev *dev = fe->tuner_priv; 157 struct i2c_client *client = dev->client; 158 159 dev_dbg(&client->dev, "\n"); 160 161 *frequency = 0; /* Zero-IF */ 162 return 0; 163 } 164 165 static const struct dvb_tuner_ops tua9001_tuner_ops = { 166 .info = { 167 .name = "Infineon TUA9001", 168 .frequency_min_hz = 170 * MHz, 169 .frequency_max_hz = 862 * MHz, 170 }, 171 172 .init = tua9001_init, 173 .sleep = tua9001_sleep, 174 .set_params = tua9001_set_params, 175 176 .get_if_frequency = tua9001_get_if_frequency, 177 }; 178 179 static int tua9001_probe(struct i2c_client *client, 180 const struct i2c_device_id *id) 181 { 182 struct tua9001_dev *dev; 183 struct tua9001_platform_data *pdata = client->dev.platform_data; 184 struct dvb_frontend *fe = pdata->dvb_frontend; 185 int ret; 186 static const struct regmap_config regmap_config = { 187 .reg_bits = 8, 188 .val_bits = 16, 189 }; 190 191 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 192 if (!dev) { 193 ret = -ENOMEM; 194 goto err; 195 } 196 197 dev->fe = pdata->dvb_frontend; 198 dev->client = client; 199 dev->regmap = devm_regmap_init_i2c(client, ®map_config); 200 if (IS_ERR(dev->regmap)) { 201 ret = PTR_ERR(dev->regmap); 202 goto err_kfree; 203 } 204 205 if (fe->callback) { 206 ret = fe->callback(client->adapter, 207 DVB_FRONTEND_COMPONENT_TUNER, 208 TUA9001_CMD_CEN, 1); 209 if (ret) 210 goto err_kfree; 211 212 ret = fe->callback(client->adapter, 213 DVB_FRONTEND_COMPONENT_TUNER, 214 TUA9001_CMD_RXEN, 0); 215 if (ret) 216 goto err_kfree; 217 218 ret = fe->callback(client->adapter, 219 DVB_FRONTEND_COMPONENT_TUNER, 220 TUA9001_CMD_RESETN, 1); 221 if (ret) 222 goto err_kfree; 223 } 224 225 fe->tuner_priv = dev; 226 memcpy(&fe->ops.tuner_ops, &tua9001_tuner_ops, 227 sizeof(struct dvb_tuner_ops)); 228 i2c_set_clientdata(client, dev); 229 230 dev_info(&client->dev, "Infineon TUA9001 successfully attached\n"); 231 return 0; 232 err_kfree: 233 kfree(dev); 234 err: 235 dev_dbg(&client->dev, "failed=%d\n", ret); 236 return ret; 237 } 238 239 static int tua9001_remove(struct i2c_client *client) 240 { 241 struct tua9001_dev *dev = i2c_get_clientdata(client); 242 struct dvb_frontend *fe = dev->fe; 243 int ret; 244 245 dev_dbg(&client->dev, "\n"); 246 247 if (fe->callback) { 248 ret = fe->callback(client->adapter, 249 DVB_FRONTEND_COMPONENT_TUNER, 250 TUA9001_CMD_CEN, 0); 251 if (ret) 252 goto err_kfree; 253 } 254 kfree(dev); 255 return 0; 256 err_kfree: 257 kfree(dev); 258 dev_dbg(&client->dev, "failed=%d\n", ret); 259 return ret; 260 } 261 262 static const struct i2c_device_id tua9001_id_table[] = { 263 {"tua9001", 0}, 264 {} 265 }; 266 MODULE_DEVICE_TABLE(i2c, tua9001_id_table); 267 268 static struct i2c_driver tua9001_driver = { 269 .driver = { 270 .name = "tua9001", 271 .suppress_bind_attrs = true, 272 }, 273 .probe = tua9001_probe, 274 .remove = tua9001_remove, 275 .id_table = tua9001_id_table, 276 }; 277 278 module_i2c_driver(tua9001_driver); 279 280 MODULE_DESCRIPTION("Infineon TUA9001 silicon tuner driver"); 281 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); 282 MODULE_LICENSE("GPL"); 283