blob: 11d391a5d5c63193d500a2ea1eb9c0bbe7a67756 [file] [log] [blame]
Antti Palosaari88b38be2013-01-07 09:37:30 -03001/*
2 * ITE Tech IT9137 silicon tuner driver
3 *
4 * Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com)
5 * IT9137 Copyright (C) ITE Tech Inc.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 *
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
21 */
22
Antti Palosaaric2ba9722014-08-26 00:08:16 -030023#include "it913x_priv.h"
Antti Palosaari88b38be2013-01-07 09:37:30 -030024
Antti Palosaaria71b65e2014-08-26 20:11:08 -030025struct it913x_dev {
Antti Palosaari3b2a5e82014-08-26 17:14:16 -030026 struct i2c_client *client;
Antti Palosaarid2dbc002014-08-26 21:45:33 -030027 struct regmap *regmap;
Antti Palosaari3b2a5e82014-08-26 17:14:16 -030028 struct dvb_frontend *fe;
Antti Palosaari676c3502014-08-27 03:59:27 -030029 u8 chip_ver:2;
30 u8 role:2;
Antti Palosaari10859792013-02-28 19:02:19 -030031 u8 firmware_ver;
Antti Palosaari88b38be2013-01-07 09:37:30 -030032 u16 tun_xtal;
33 u8 tun_fdiv;
34 u8 tun_clk_mode;
35 u32 tun_fn_min;
Antti Palosaari88b38be2013-01-07 09:37:30 -030036};
37
Antti Palosaaria71b65e2014-08-26 20:11:08 -030038static int it913x_script_loader(struct it913x_dev *dev,
Antti Palosaari88b38be2013-01-07 09:37:30 -030039 struct it913xset *loadscript)
40{
41 int ret, i;
Antti Palosaarid1113242014-08-09 15:02:14 -030042
Antti Palosaari88b38be2013-01-07 09:37:30 -030043 if (loadscript == NULL)
44 return -EINVAL;
45
46 for (i = 0; i < 1000; ++i) {
Antti Palosaari8da55c92014-08-26 18:56:46 -030047 if (loadscript[i].address == 0x000000)
Antti Palosaari88b38be2013-01-07 09:37:30 -030048 break;
Antti Palosaarid2dbc002014-08-26 21:45:33 -030049 ret = regmap_bulk_write(dev->regmap, loadscript[i].address,
Antti Palosaari88b38be2013-01-07 09:37:30 -030050 loadscript[i].reg, loadscript[i].count);
51 if (ret < 0)
52 return -ENODEV;
53 }
54 return 0;
55}
56
Antti Palosaari42432b32013-02-26 20:57:01 -030057static int it913x_init(struct dvb_frontend *fe)
Antti Palosaari88b38be2013-01-07 09:37:30 -030058{
Antti Palosaaria71b65e2014-08-26 20:11:08 -030059 struct it913x_dev *dev = fe->tuner_priv;
Antti Palosaari8da55c92014-08-26 18:56:46 -030060 int ret, i;
Antti Palosaarid2dbc002014-08-26 21:45:33 -030061 unsigned int reg;
Antti Palosaari88b38be2013-01-07 09:37:30 -030062 u8 val, nv_val;
63 u8 nv[] = {48, 32, 24, 16, 12, 8, 6, 4, 2};
64 u8 b[2];
65
Antti Palosaarid2dbc002014-08-26 21:45:33 -030066 ret = regmap_read(dev->regmap, 0x80ec86, &reg);
Antti Palosaari88b38be2013-01-07 09:37:30 -030067 switch (reg) {
68 case 0:
Antti Palosaaria71b65e2014-08-26 20:11:08 -030069 dev->tun_clk_mode = reg;
70 dev->tun_xtal = 2000;
71 dev->tun_fdiv = 3;
Antti Palosaari88b38be2013-01-07 09:37:30 -030072 val = 16;
73 break;
Antti Palosaari88b38be2013-01-07 09:37:30 -030074 case 1:
Antti Palosaari8da55c92014-08-26 18:56:46 -030075 default: /* I/O error too */
Antti Palosaaria71b65e2014-08-26 20:11:08 -030076 dev->tun_clk_mode = reg;
77 dev->tun_xtal = 640;
78 dev->tun_fdiv = 1;
Antti Palosaari88b38be2013-01-07 09:37:30 -030079 val = 6;
80 break;
81 }
82
Antti Palosaarid2dbc002014-08-26 21:45:33 -030083 ret = regmap_read(dev->regmap, 0x80ed03, &reg);
Antti Palosaari88b38be2013-01-07 09:37:30 -030084
85 if (reg < 0)
86 return -ENODEV;
87 else if (reg < ARRAY_SIZE(nv))
88 nv_val = nv[reg];
89 else
90 nv_val = 2;
91
92 for (i = 0; i < 50; i++) {
Antti Palosaarid2dbc002014-08-26 21:45:33 -030093 ret = regmap_bulk_read(dev->regmap, 0x80ed23, &b[0], sizeof(b));
Antti Palosaari88b38be2013-01-07 09:37:30 -030094 reg = (b[1] << 8) + b[0];
95 if (reg > 0)
96 break;
Antti Palosaarid2dbc002014-08-26 21:45:33 -030097 if (ret)
Antti Palosaari88b38be2013-01-07 09:37:30 -030098 return -ENODEV;
99 udelay(2000);
100 }
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300101 dev->tun_fn_min = dev->tun_xtal * reg;
102 dev->tun_fn_min /= (dev->tun_fdiv * nv_val);
103 dev_dbg(&dev->client->dev, "Tuner fn_min %d\n", dev->tun_fn_min);
Antti Palosaari88b38be2013-01-07 09:37:30 -0300104
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300105 if (dev->chip_ver > 1)
Antti Palosaari88b38be2013-01-07 09:37:30 -0300106 msleep(50);
107 else {
108 for (i = 0; i < 50; i++) {
Antti Palosaarid2dbc002014-08-26 21:45:33 -0300109 ret = regmap_read(dev->regmap, 0x80ec82, &reg);
Antti Palosaari8da55c92014-08-26 18:56:46 -0300110 if (ret < 0)
111 return -ENODEV;
Antti Palosaari88b38be2013-01-07 09:37:30 -0300112 if (reg > 0)
113 break;
Antti Palosaari88b38be2013-01-07 09:37:30 -0300114 udelay(2000);
115 }
116 }
117
Antti Palosaarid19812e2013-02-27 23:29:02 -0300118 /* Power Up Tuner - common all versions */
Antti Palosaarid2dbc002014-08-26 21:45:33 -0300119 ret = regmap_write(dev->regmap, 0x80ec40, 0x1);
120 ret |= regmap_write(dev->regmap, 0x80ec57, 0x0);
121 ret |= regmap_write(dev->regmap, 0x80ec58, 0x0);
Antti Palosaarid19812e2013-02-27 23:29:02 -0300122
Antti Palosaarid2dbc002014-08-26 21:45:33 -0300123 return regmap_write(dev->regmap, 0x80ed81, val);
Antti Palosaari88b38be2013-01-07 09:37:30 -0300124}
125
Antti Palosaari676c3502014-08-27 03:59:27 -0300126static int it913x_sleep(struct dvb_frontend *fe)
127{
128 struct it913x_dev *dev = fe->tuner_priv;
129 int ret, len;
130
131 dev_dbg(&dev->client->dev, "role=%u\n", dev->role);
132
133 ret = regmap_bulk_write(dev->regmap, 0x80ec40, "\x00", 1);
134 if (ret)
135 goto err;
136
137 /*
138 * Writing '0x00' to master tuner register '0x80ec08' causes slave tuner
139 * communication lost. Due to that, we cannot put master full sleep.
140 */
141 if (dev->role == IT913X_ROLE_DUAL_MASTER)
142 len = 4;
143 else
144 len = 15;
145
146 dev_dbg(&dev->client->dev, "role=%u len=%d\n", dev->role, len);
147
148 ret = regmap_bulk_write(dev->regmap, 0x80ec02,
149 "\x3f\x1f\x3f\x3e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
150 len);
151 if (ret)
152 goto err;
153
154 ret = regmap_bulk_write(dev->regmap, 0x80ec12, "\x00\x00\x00\x00", 4);
155 if (ret)
156 goto err;
157
158 ret = regmap_bulk_write(dev->regmap, 0x80ec17,
159 "\x00\x00\x00\x00\x00\x00\x00\x00\x00", 9);
160 if (ret)
161 goto err;
162
163 ret = regmap_bulk_write(dev->regmap, 0x80ec22,
164 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 10);
165 if (ret)
166 goto err;
167
168 ret = regmap_bulk_write(dev->regmap, 0x80ec20, "\x00", 1);
169 if (ret)
170 goto err;
171
172 ret = regmap_bulk_write(dev->regmap, 0x80ec3f, "\x01", 1);
173 if (ret)
174 goto err;
175
176 return 0;
177err:
178 dev_dbg(&dev->client->dev, "failed %d\n", ret);
179 return ret;
180}
181
Antti Palosaari42432b32013-02-26 20:57:01 -0300182static int it9137_set_params(struct dvb_frontend *fe)
Antti Palosaari88b38be2013-01-07 09:37:30 -0300183{
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300184 struct it913x_dev *dev = fe->tuner_priv;
Antti Palosaari88b38be2013-01-07 09:37:30 -0300185 struct it913xset *set_tuner = set_it9137_template;
186 struct dtv_frontend_properties *p = &fe->dtv_property_cache;
187 u32 bandwidth = p->bandwidth_hz;
188 u32 frequency_m = p->frequency;
Antti Palosaari8da55c92014-08-26 18:56:46 -0300189 int ret;
Antti Palosaarid2dbc002014-08-26 21:45:33 -0300190 unsigned int reg;
Antti Palosaari88b38be2013-01-07 09:37:30 -0300191 u32 frequency = frequency_m / 1000;
192 u32 freq, temp_f, tmp;
193 u16 iqik_m_cal;
194 u16 n_div;
195 u8 n;
196 u8 l_band;
197 u8 lna_band;
198 u8 bw;
199
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300200 if (dev->firmware_ver == 1)
Antti Palosaari88b38be2013-01-07 09:37:30 -0300201 set_tuner = set_it9135_template;
202 else
203 set_tuner = set_it9137_template;
204
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300205 dev_dbg(&dev->client->dev, "Tuner Frequency %d Bandwidth %d\n",
Antti Palosaari3b2a5e82014-08-26 17:14:16 -0300206 frequency, bandwidth);
Antti Palosaari88b38be2013-01-07 09:37:30 -0300207
208 if (frequency >= 51000 && frequency <= 440000) {
209 l_band = 0;
210 lna_band = 0;
211 } else if (frequency > 440000 && frequency <= 484000) {
212 l_band = 1;
213 lna_band = 1;
214 } else if (frequency > 484000 && frequency <= 533000) {
215 l_band = 1;
216 lna_band = 2;
217 } else if (frequency > 533000 && frequency <= 587000) {
218 l_band = 1;
219 lna_band = 3;
220 } else if (frequency > 587000 && frequency <= 645000) {
221 l_band = 1;
222 lna_band = 4;
223 } else if (frequency > 645000 && frequency <= 710000) {
224 l_band = 1;
225 lna_band = 5;
226 } else if (frequency > 710000 && frequency <= 782000) {
227 l_band = 1;
228 lna_band = 6;
229 } else if (frequency > 782000 && frequency <= 860000) {
230 l_band = 1;
231 lna_band = 7;
232 } else if (frequency > 1450000 && frequency <= 1492000) {
233 l_band = 1;
234 lna_band = 0;
235 } else if (frequency > 1660000 && frequency <= 1685000) {
236 l_band = 1;
237 lna_band = 1;
238 } else
239 return -EINVAL;
240 set_tuner[0].reg[0] = lna_band;
241
242 switch (bandwidth) {
243 case 5000000:
244 bw = 0;
245 break;
246 case 6000000:
247 bw = 2;
248 break;
249 case 7000000:
250 bw = 4;
251 break;
252 default:
253 case 8000000:
254 bw = 6;
255 break;
256 }
257
258 set_tuner[1].reg[0] = bw;
259 set_tuner[2].reg[0] = 0xa0 | (l_band << 3);
260
261 if (frequency > 53000 && frequency <= 74000) {
262 n_div = 48;
263 n = 0;
264 } else if (frequency > 74000 && frequency <= 111000) {
265 n_div = 32;
266 n = 1;
267 } else if (frequency > 111000 && frequency <= 148000) {
268 n_div = 24;
269 n = 2;
270 } else if (frequency > 148000 && frequency <= 222000) {
271 n_div = 16;
272 n = 3;
273 } else if (frequency > 222000 && frequency <= 296000) {
274 n_div = 12;
275 n = 4;
276 } else if (frequency > 296000 && frequency <= 445000) {
277 n_div = 8;
278 n = 5;
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300279 } else if (frequency > 445000 && frequency <= dev->tun_fn_min) {
Antti Palosaari88b38be2013-01-07 09:37:30 -0300280 n_div = 6;
281 n = 6;
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300282 } else if (frequency > dev->tun_fn_min && frequency <= 950000) {
Antti Palosaari88b38be2013-01-07 09:37:30 -0300283 n_div = 4;
284 n = 7;
285 } else if (frequency > 1450000 && frequency <= 1680000) {
286 n_div = 2;
287 n = 0;
288 } else
289 return -EINVAL;
290
Antti Palosaarid2dbc002014-08-26 21:45:33 -0300291 ret = regmap_read(dev->regmap, 0x80ed81, &reg);
Antti Palosaari88b38be2013-01-07 09:37:30 -0300292 iqik_m_cal = (u16)reg * n_div;
293
294 if (reg < 0x20) {
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300295 if (dev->tun_clk_mode == 0)
Antti Palosaari88b38be2013-01-07 09:37:30 -0300296 iqik_m_cal = (iqik_m_cal * 9) >> 5;
297 else
298 iqik_m_cal >>= 1;
299 } else {
300 iqik_m_cal = 0x40 - iqik_m_cal;
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300301 if (dev->tun_clk_mode == 0)
Antti Palosaari88b38be2013-01-07 09:37:30 -0300302 iqik_m_cal = ~((iqik_m_cal * 9) >> 5);
303 else
304 iqik_m_cal = ~(iqik_m_cal >> 1);
305 }
306
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300307 temp_f = frequency * (u32)n_div * (u32)dev->tun_fdiv;
308 freq = temp_f / dev->tun_xtal;
309 tmp = freq * dev->tun_xtal;
Antti Palosaari88b38be2013-01-07 09:37:30 -0300310
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300311 if ((temp_f - tmp) >= (dev->tun_xtal >> 1))
Antti Palosaari88b38be2013-01-07 09:37:30 -0300312 freq++;
313
314 freq += (u32) n << 13;
315 /* Frequency OMEGA_IQIK_M_CAL_MID*/
316 temp_f = freq + (u32)iqik_m_cal;
317
318 set_tuner[3].reg[0] = temp_f & 0xff;
319 set_tuner[4].reg[0] = (temp_f >> 8) & 0xff;
320
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300321 dev_dbg(&dev->client->dev, "High Frequency = %04x\n", temp_f);
Antti Palosaari88b38be2013-01-07 09:37:30 -0300322
323 /* Lower frequency */
324 set_tuner[5].reg[0] = freq & 0xff;
325 set_tuner[6].reg[0] = (freq >> 8) & 0xff;
326
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300327 dev_dbg(&dev->client->dev, "low Frequency = %04x\n", freq);
Antti Palosaari88b38be2013-01-07 09:37:30 -0300328
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300329 ret = it913x_script_loader(dev, set_tuner);
Antti Palosaari88b38be2013-01-07 09:37:30 -0300330
331 return (ret < 0) ? -ENODEV : 0;
332}
333
Antti Palosaari88b38be2013-01-07 09:37:30 -0300334static const struct dvb_tuner_ops it913x_tuner_ops = {
335 .info = {
336 .name = "ITE Tech IT913X",
337 .frequency_min = 174000000,
338 .frequency_max = 862000000,
339 },
340
Antti Palosaari42432b32013-02-26 20:57:01 -0300341 .init = it913x_init,
342 .sleep = it913x_sleep,
343 .set_params = it9137_set_params,
Antti Palosaari88b38be2013-01-07 09:37:30 -0300344};
345
Antti Palosaari3b2a5e82014-08-26 17:14:16 -0300346static int it913x_probe(struct i2c_client *client,
347 const struct i2c_device_id *id)
Antti Palosaari88b38be2013-01-07 09:37:30 -0300348{
Antti Palosaari3b2a5e82014-08-26 17:14:16 -0300349 struct it913x_config *cfg = client->dev.platform_data;
350 struct dvb_frontend *fe = cfg->fe;
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300351 struct it913x_dev *dev;
Bimow Chen01b461b2014-08-05 00:14:47 -0300352 int ret;
Antti Palosaari3b2a5e82014-08-26 17:14:16 -0300353 char *chip_ver_str;
Antti Palosaarid2dbc002014-08-26 21:45:33 -0300354 static const struct regmap_config regmap_config = {
355 .reg_bits = 24,
356 .val_bits = 8,
357 };
Antti Palosaari88b38be2013-01-07 09:37:30 -0300358
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300359 dev = kzalloc(sizeof(struct it913x_dev), GFP_KERNEL);
360 if (dev == NULL) {
Antti Palosaari3b2a5e82014-08-26 17:14:16 -0300361 ret = -ENOMEM;
362 dev_err(&client->dev, "kzalloc() failed\n");
363 goto err;
Antti Palosaari88b38be2013-01-07 09:37:30 -0300364 }
365
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300366 dev->client = client;
367 dev->fe = cfg->fe;
368 dev->chip_ver = cfg->chip_ver;
Antti Palosaari676c3502014-08-27 03:59:27 -0300369 dev->role = cfg->role;
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300370 dev->firmware_ver = 1;
Antti Palosaarid2dbc002014-08-26 21:45:33 -0300371 dev->regmap = regmap_init_i2c(client, &regmap_config);
372 if (IS_ERR(dev->regmap)) {
373 ret = PTR_ERR(dev->regmap);
374 goto err_kfree;
375 }
Antti Palosaari44af7472013-02-28 00:14:06 -0300376
Bimow Chen01b461b2014-08-05 00:14:47 -0300377 /* tuner RF initial */
Antti Palosaarid2dbc002014-08-26 21:45:33 -0300378 ret = regmap_write(dev->regmap, 0x80ec4c, 0x68);
379 if (ret)
380 goto err_regmap_exit;
Bimow Chen01b461b2014-08-05 00:14:47 -0300381
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300382 fe->tuner_priv = dev;
Antti Palosaari88b38be2013-01-07 09:37:30 -0300383 memcpy(&fe->ops.tuner_ops, &it913x_tuner_ops,
384 sizeof(struct dvb_tuner_ops));
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300385 i2c_set_clientdata(client, dev);
Antti Palosaari88b38be2013-01-07 09:37:30 -0300386
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300387 if (dev->chip_ver == 1)
Antti Palosaari3b2a5e82014-08-26 17:14:16 -0300388 chip_ver_str = "AX";
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300389 else if (dev->chip_ver == 2)
Antti Palosaari3b2a5e82014-08-26 17:14:16 -0300390 chip_ver_str = "BX";
391 else
392 chip_ver_str = "??";
Antti Palosaari88b38be2013-01-07 09:37:30 -0300393
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300394 dev_info(&dev->client->dev, "ITE IT913X %s successfully attached\n",
Antti Palosaari3b2a5e82014-08-26 17:14:16 -0300395 chip_ver_str);
Antti Palosaari676c3502014-08-27 03:59:27 -0300396 dev_dbg(&dev->client->dev, "chip_ver=%u role=%u\n", dev->chip_ver, dev->role);
Antti Palosaari3b2a5e82014-08-26 17:14:16 -0300397 return 0;
Antti Palosaarid2dbc002014-08-26 21:45:33 -0300398
399err_regmap_exit:
400 regmap_exit(dev->regmap);
401err_kfree:
402 kfree(dev);
Antti Palosaari3b2a5e82014-08-26 17:14:16 -0300403err:
404 dev_dbg(&client->dev, "failed %d\n", ret);
Antti Palosaari3b2a5e82014-08-26 17:14:16 -0300405 return ret;
Antti Palosaari88b38be2013-01-07 09:37:30 -0300406}
Antti Palosaari3b2a5e82014-08-26 17:14:16 -0300407
408static int it913x_remove(struct i2c_client *client)
409{
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300410 struct it913x_dev *dev = i2c_get_clientdata(client);
411 struct dvb_frontend *fe = dev->fe;
Antti Palosaari3b2a5e82014-08-26 17:14:16 -0300412
413 dev_dbg(&client->dev, "\n");
414
415 memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
416 fe->tuner_priv = NULL;
Antti Palosaarid2dbc002014-08-26 21:45:33 -0300417 regmap_exit(dev->regmap);
Antti Palosaaria71b65e2014-08-26 20:11:08 -0300418 kfree(dev);
Antti Palosaari3b2a5e82014-08-26 17:14:16 -0300419
420 return 0;
421}
422
423static const struct i2c_device_id it913x_id_table[] = {
424 {"it913x", 0},
425 {}
426};
427MODULE_DEVICE_TABLE(i2c, it913x_id_table);
428
429static struct i2c_driver it913x_driver = {
430 .driver = {
431 .owner = THIS_MODULE,
432 .name = "it913x",
433 },
434 .probe = it913x_probe,
435 .remove = it913x_remove,
436 .id_table = it913x_id_table,
437};
438
439module_i2c_driver(it913x_driver);
Antti Palosaari88b38be2013-01-07 09:37:30 -0300440
441MODULE_DESCRIPTION("ITE Tech IT913X silicon tuner driver");
442MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
443MODULE_LICENSE("GPL");