blob: f036701c12eeb59372d6f7587d343ed462287457 [file] [log] [blame]
Antti Palosaaric0adca72011-07-08 23:34:09 -03001/*
2 * Realtek RTL2830 DVB-T demodulator driver
3 *
4 * Copyright (C) 2011 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 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21
22/*
23 * Driver implements own I2C-adapter for tuner I2C access. That's since chip
24 * have unusual I2C-gate control which closes gate automatically after each
25 * I2C transfer. Using own I2C adapter we can workaround that.
26 */
27
28#include "rtl2830_priv.h"
29
30int rtl2830_debug;
31module_param_named(debug, rtl2830_debug, int, 0644);
32MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
33
Antti Palosaari0485a702011-08-04 20:27:19 -030034/* write multiple hardware registers */
35static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, u8 *val, int len)
Antti Palosaaric0adca72011-07-08 23:34:09 -030036{
37 int ret;
Antti Palosaari0485a702011-08-04 20:27:19 -030038 u8 buf[1+len];
Antti Palosaaric0adca72011-07-08 23:34:09 -030039 struct i2c_msg msg[1] = {
40 {
41 .addr = priv->cfg.i2c_addr,
42 .flags = 0,
Antti Palosaari0485a702011-08-04 20:27:19 -030043 .len = 1+len,
Antti Palosaaric0adca72011-07-08 23:34:09 -030044 .buf = buf,
45 }
46 };
47
Antti Palosaari0485a702011-08-04 20:27:19 -030048 buf[0] = reg;
49 memcpy(&buf[1], val, len);
Antti Palosaaric0adca72011-07-08 23:34:09 -030050
51 ret = i2c_transfer(priv->i2c, msg, 1);
52 if (ret == 1) {
53 ret = 0;
54 } else {
Antti Palosaari0485a702011-08-04 20:27:19 -030055 warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len);
Antti Palosaaric0adca72011-07-08 23:34:09 -030056 ret = -EREMOTEIO;
57 }
58 return ret;
59}
60
Antti Palosaari0485a702011-08-04 20:27:19 -030061/* read multiple hardware registers */
62static int rtl2830_rd(struct rtl2830_priv *priv, u8 reg, u8 *val, int len)
Antti Palosaaric0adca72011-07-08 23:34:09 -030063{
64 int ret;
Antti Palosaaric0adca72011-07-08 23:34:09 -030065 struct i2c_msg msg[2] = {
66 {
67 .addr = priv->cfg.i2c_addr,
68 .flags = 0,
Antti Palosaari0485a702011-08-04 20:27:19 -030069 .len = 1,
70 .buf = &reg,
Antti Palosaaric0adca72011-07-08 23:34:09 -030071 }, {
72 .addr = priv->cfg.i2c_addr,
73 .flags = I2C_M_RD,
74 .len = len,
75 .buf = val,
76 }
77 };
78
Antti Palosaaric0adca72011-07-08 23:34:09 -030079 ret = i2c_transfer(priv->i2c, msg, 2);
80 if (ret == 2) {
81 ret = 0;
82 } else {
Antti Palosaari0485a702011-08-04 20:27:19 -030083 warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len);
Antti Palosaaric0adca72011-07-08 23:34:09 -030084 ret = -EREMOTEIO;
85 }
86 return ret;
87}
88
Antti Palosaari0485a702011-08-04 20:27:19 -030089/* write multiple registers */
90static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len)
91{
92 int ret;
93 u8 reg2 = (reg >> 0) & 0xff;
94 u8 page = (reg >> 8) & 0xff;
95
96 /* switch bank if needed */
97 if (page != priv->page) {
98 ret = rtl2830_wr(priv, 0x00, &page, 1);
99 if (ret)
100 return ret;
101
102 priv->page = page;
103 }
104
105 return rtl2830_wr(priv, reg2, val, len);
106}
107
108/* read multiple registers */
109static int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len)
110{
111 int ret;
112 u8 reg2 = (reg >> 0) & 0xff;
113 u8 page = (reg >> 8) & 0xff;
114
115 /* switch bank if needed */
116 if (page != priv->page) {
117 ret = rtl2830_wr(priv, 0x00, &page, 1);
118 if (ret)
119 return ret;
120
121 priv->page = page;
122 }
123
124 return rtl2830_rd(priv, reg2, val, len);
125}
126
Antti Palosaaric0adca72011-07-08 23:34:09 -0300127#if 0 /* currently not used */
128/* write single register */
129static int rtl2830_wr_reg(struct rtl2830_priv *priv, u16 reg, u8 val)
130{
131 return rtl2830_wr_regs(priv, reg, &val, 1);
132}
133#endif
134
135/* read single register */
136static int rtl2830_rd_reg(struct rtl2830_priv *priv, u16 reg, u8 *val)
137{
138 return rtl2830_rd_regs(priv, reg, val, 1);
139}
140
141/* write single register with mask */
142int rtl2830_wr_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 val, u8 mask)
143{
144 int ret;
145 u8 tmp;
146
147 /* no need for read if whole reg is written */
148 if (mask != 0xff) {
149 ret = rtl2830_rd_regs(priv, reg, &tmp, 1);
150 if (ret)
151 return ret;
152
153 val &= mask;
154 tmp &= ~mask;
155 val |= tmp;
156 }
157
158 return rtl2830_wr_regs(priv, reg, &val, 1);
159}
160
161/* read single register with mask */
162int rtl2830_rd_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 *val, u8 mask)
163{
164 int ret, i;
165 u8 tmp;
166
167 ret = rtl2830_rd_regs(priv, reg, &tmp, 1);
168 if (ret)
169 return ret;
170
171 tmp &= mask;
172
173 /* find position of the first bit */
174 for (i = 0; i < 8; i++) {
175 if ((mask >> i) & 0x01)
176 break;
177 }
178 *val = tmp >> i;
179
180 return 0;
181}
182
183static int rtl2830_init(struct dvb_frontend *fe)
184{
185 struct rtl2830_priv *priv = fe->demodulator_priv;
186 int ret, i;
187 u64 num;
188 u8 buf[3], tmp;
189 u32 if_ctl;
190 struct rtl2830_reg_val_mask tab[] = {
191 { 0x00d, 0x01, 0x03 },
192 { 0x00d, 0x10, 0x10 },
193 { 0x104, 0x00, 0x1e },
194 { 0x105, 0x80, 0x80 },
195 { 0x110, 0x02, 0x03 },
196 { 0x110, 0x08, 0x0c },
197 { 0x17b, 0x00, 0x40 },
198 { 0x17d, 0x05, 0x0f },
199 { 0x17d, 0x50, 0xf0 },
200 { 0x18c, 0x08, 0x0f },
201 { 0x18d, 0x00, 0xc0 },
202 { 0x188, 0x05, 0x0f },
203 { 0x189, 0x00, 0xfc },
204 { 0x2d5, 0x02, 0x02 },
205 { 0x2f1, 0x02, 0x06 },
206 { 0x2f1, 0x20, 0xf8 },
207 { 0x16d, 0x00, 0x01 },
208 { 0x1a6, 0x00, 0x80 },
209 { 0x106, priv->cfg.vtop, 0x3f },
210 { 0x107, priv->cfg.krf, 0x3f },
211 { 0x112, 0x28, 0xff },
212 { 0x103, priv->cfg.agc_targ_val, 0xff },
213 { 0x00a, 0x02, 0x07 },
214 { 0x140, 0x0c, 0x3c },
215 { 0x140, 0x40, 0xc0 },
216 { 0x15b, 0x05, 0x07 },
217 { 0x15b, 0x28, 0x38 },
218 { 0x15c, 0x05, 0x07 },
219 { 0x15c, 0x28, 0x38 },
220 { 0x115, priv->cfg.spec_inv, 0x01 },
221 { 0x16f, 0x01, 0x07 },
222 { 0x170, 0x18, 0x38 },
223 { 0x172, 0x0f, 0x0f },
224 { 0x173, 0x08, 0x38 },
225 { 0x175, 0x01, 0x07 },
226 { 0x176, 0x00, 0xc0 },
227 };
228
229 for (i = 0; i < ARRAY_SIZE(tab); i++) {
230 ret = rtl2830_wr_reg_mask(priv, tab[i].reg, tab[i].val,
231 tab[i].mask);
232 if (ret)
233 goto err;
234 }
235
236 ret = rtl2830_wr_regs(priv, 0x18f, "\x28\x00", 2);
237 if (ret)
238 goto err;
239
240 ret = rtl2830_wr_regs(priv, 0x195,
241 "\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8);
242 if (ret)
243 goto err;
244
245 num = priv->cfg.if_dvbt % priv->cfg.xtal;
246 num *= 0x400000;
247 num /= priv->cfg.xtal;
248 num = -num;
249 if_ctl = num & 0x3fffff;
250 dbg("%s: if_ctl=%08x", __func__, if_ctl);
251
252 ret = rtl2830_rd_reg_mask(priv, 0x119, &tmp, 0xc0); /* b[7:6] */
253 if (ret)
254 goto err;
255
256 buf[0] = tmp << 6;
257 buf[0] = (if_ctl >> 16) & 0x3f;
258 buf[1] = (if_ctl >> 8) & 0xff;
259 buf[2] = (if_ctl >> 0) & 0xff;
260
261 ret = rtl2830_wr_regs(priv, 0x119, buf, 3);
262 if (ret)
263 goto err;
264
265 /* TODO: spec init */
266
267 /* soft reset */
268 ret = rtl2830_wr_reg_mask(priv, 0x101, 0x04, 0x04);
269 if (ret)
270 goto err;
271
272 ret = rtl2830_wr_reg_mask(priv, 0x101, 0x00, 0x04);
273 if (ret)
274 goto err;
275
276 return ret;
277err:
278 dbg("%s: failed=%d", __func__, ret);
279 return ret;
280}
281
282int rtl2830_get_tune_settings(struct dvb_frontend *fe,
283 struct dvb_frontend_tune_settings *s)
284{
285 s->min_delay_ms = 500;
286 s->step_size = fe->ops.info.frequency_stepsize * 2;
287 s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
288
289 return 0;
290}
291
292static int rtl2830_set_frontend(struct dvb_frontend *fe)
293{
294 struct rtl2830_priv *priv = fe->demodulator_priv;
295 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
296 int ret, i;
297 static u8 bw_params1[3][34] = {
298 {
299 0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0xfa, 0x00, 0x17, 0x00, 0x41,
300 0x00, 0x64, 0x00, 0x67, 0x00, 0x38, 0x1f, 0xde, 0x1f, 0x7a,
301 0x1f, 0x47, 0x1f, 0x7c, 0x00, 0x30, 0x01, 0x4b, 0x02, 0x82,
302 0x03, 0x73, 0x03, 0xcf, /* 6 MHz */
303 }, {
304 0x1f, 0xfa, 0x1f, 0xda, 0x1f, 0xc1, 0x1f, 0xb3, 0x1f, 0xca,
305 0x00, 0x07, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x40, 0x1f, 0xca,
306 0x1f, 0x4d, 0x1f, 0x2a, 0x1f, 0xb2, 0x00, 0xec, 0x02, 0x7e,
307 0x03, 0xd0, 0x04, 0x53, /* 7 MHz */
308 }, {
309 0x00, 0x10, 0x00, 0x0e, 0x1f, 0xf7, 0x1f, 0xc9, 0x1f, 0xa0,
310 0x1f, 0xa6, 0x1f, 0xec, 0x00, 0x4e, 0x00, 0x7d, 0x00, 0x3a,
311 0x1f, 0x98, 0x1f, 0x10, 0x1f, 0x40, 0x00, 0x75, 0x02, 0x5f,
312 0x04, 0x24, 0x04, 0xdb, /* 8 MHz */
313 },
314 };
315 static u8 bw_params2[3][6] = {
316 {0xc3, 0x0c, 0x44, 0x33, 0x33, 0x30,}, /* 6 MHz */
317 {0xb8, 0xe3, 0x93, 0x99, 0x99, 0x98,}, /* 7 MHz */
318 {0xae, 0xba, 0xf3, 0x26, 0x66, 0x64,}, /* 8 MHz */
319 };
320
321
322 dbg("%s: frequency=%d bandwidth_hz=%d inversion=%d", __func__,
323 c->frequency, c->bandwidth_hz, c->inversion);
324
325 /* program tuner */
326 if (fe->ops.tuner_ops.set_params)
327 fe->ops.tuner_ops.set_params(fe);
328
329 switch (c->bandwidth_hz) {
330 case 6000000:
331 i = 0;
332 break;
333 case 7000000:
334 i = 1;
335 break;
336 case 8000000:
337 i = 2;
338 break;
339 default:
340 dbg("invalid bandwidth");
341 return -EINVAL;
342 }
343
344 ret = rtl2830_wr_reg_mask(priv, 0x008, i << 1, 0x06);
345 if (ret)
346 goto err;
347
348 /* 1/2 split I2C write */
349 ret = rtl2830_wr_regs(priv, 0x11c, &bw_params1[i][0], 17);
350 if (ret)
351 goto err;
352
353 /* 2/2 split I2C write */
354 ret = rtl2830_wr_regs(priv, 0x12d, &bw_params1[i][17], 17);
355 if (ret)
356 goto err;
357
358 ret = rtl2830_wr_regs(priv, 0x19d, bw_params2[i], 6);
359 if (ret)
360 goto err;
361
362 return ret;
363err:
364 dbg("%s: failed=%d", __func__, ret);
365 return ret;
366}
367
368static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status)
369{
370 struct rtl2830_priv *priv = fe->demodulator_priv;
371 int ret;
372 u8 tmp;
373 *status = 0;
374
375 ret = rtl2830_rd_reg_mask(priv, 0x351, &tmp, 0x78); /* [6:3] */
376 if (ret)
377 goto err;
378
379 if (tmp == 11) {
380 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
381 FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
382 } else if (tmp == 10) {
383 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
384 FE_HAS_VITERBI;
385 }
386
387 return ret;
388err:
389 dbg("%s: failed=%d", __func__, ret);
390 return ret;
391}
392
393static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr)
394{
395 *snr = 0;
396 return 0;
397}
398
399static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber)
400{
401 *ber = 0;
402 return 0;
403}
404
405static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
406{
407 *ucblocks = 0;
408 return 0;
409}
410
411static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
412{
413 *strength = 0;
414 return 0;
415}
416
417static struct dvb_frontend_ops rtl2830_ops;
418
419static u32 rtl2830_tuner_i2c_func(struct i2c_adapter *adapter)
420{
421 return I2C_FUNC_I2C;
422}
423
424static int rtl2830_tuner_i2c_xfer(struct i2c_adapter *i2c_adap,
425 struct i2c_msg msg[], int num)
426{
427 struct rtl2830_priv *priv = i2c_get_adapdata(i2c_adap);
428 int ret;
429
430 /* open i2c-gate */
431 ret = rtl2830_wr_reg_mask(priv, 0x101, 0x08, 0x08);
432 if (ret)
433 goto err;
434
435 ret = i2c_transfer(priv->i2c, msg, num);
436 if (ret < 0)
437 warn("tuner i2c failed=%d", ret);
438
439 return ret;
440err:
441 dbg("%s: failed=%d", __func__, ret);
442 return ret;
443}
444
445static struct i2c_algorithm rtl2830_tuner_i2c_algo = {
446 .master_xfer = rtl2830_tuner_i2c_xfer,
447 .functionality = rtl2830_tuner_i2c_func,
448};
449
450struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(struct dvb_frontend *fe)
451{
452 struct rtl2830_priv *priv = fe->demodulator_priv;
453 return &priv->tuner_i2c_adapter;
454}
455EXPORT_SYMBOL(rtl2830_get_tuner_i2c_adapter);
456
457static void rtl2830_release(struct dvb_frontend *fe)
458{
459 struct rtl2830_priv *priv = fe->demodulator_priv;
460
461 i2c_del_adapter(&priv->tuner_i2c_adapter);
462 kfree(priv);
463}
464
465struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg,
466 struct i2c_adapter *i2c)
467{
468 struct rtl2830_priv *priv = NULL;
469 int ret = 0;
470 u8 tmp;
471
472 /* allocate memory for the internal state */
473 priv = kzalloc(sizeof(struct rtl2830_priv), GFP_KERNEL);
474 if (priv == NULL)
475 goto err;
476
477 /* setup the priv */
478 priv->i2c = i2c;
479 memcpy(&priv->cfg, cfg, sizeof(struct rtl2830_config));
480
481 /* check if the demod is there */
482 ret = rtl2830_rd_reg(priv, 0x000, &tmp);
483 if (ret)
484 goto err;
485
486 /* create dvb_frontend */
487 memcpy(&priv->fe.ops, &rtl2830_ops, sizeof(struct dvb_frontend_ops));
488 priv->fe.demodulator_priv = priv;
489
490 /* create tuner i2c adapter */
491 strlcpy(priv->tuner_i2c_adapter.name, "RTL2830 tuner I2C adapter",
492 sizeof(priv->tuner_i2c_adapter.name));
493 priv->tuner_i2c_adapter.algo = &rtl2830_tuner_i2c_algo;
494 priv->tuner_i2c_adapter.algo_data = NULL;
495 i2c_set_adapdata(&priv->tuner_i2c_adapter, priv);
496 if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) {
497 err("tuner I2C bus could not be initialized");
498 goto err;
499 }
500
501 return &priv->fe;
502err:
503 dbg("%s: failed=%d", __func__, ret);
504 kfree(priv);
505 return NULL;
506}
507EXPORT_SYMBOL(rtl2830_attach);
508
509static struct dvb_frontend_ops rtl2830_ops = {
510 .delsys = { SYS_DVBT },
511 .info = {
512 .name = "Realtek RTL2830 (DVB-T)",
513 .caps = FE_CAN_FEC_1_2 |
514 FE_CAN_FEC_2_3 |
515 FE_CAN_FEC_3_4 |
516 FE_CAN_FEC_5_6 |
517 FE_CAN_FEC_7_8 |
518 FE_CAN_FEC_AUTO |
519 FE_CAN_QPSK |
520 FE_CAN_QAM_16 |
521 FE_CAN_QAM_64 |
522 FE_CAN_QAM_AUTO |
523 FE_CAN_TRANSMISSION_MODE_AUTO |
524 FE_CAN_GUARD_INTERVAL_AUTO |
525 FE_CAN_HIERARCHY_AUTO |
526 FE_CAN_RECOVER |
527 FE_CAN_MUTE_TS
528 },
529
530 .release = rtl2830_release,
531
532 .init = rtl2830_init,
533
534 .get_tune_settings = rtl2830_get_tune_settings,
535
536 .set_frontend = rtl2830_set_frontend,
537
538 .read_status = rtl2830_read_status,
539 .read_snr = rtl2830_read_snr,
540 .read_ber = rtl2830_read_ber,
541 .read_ucblocks = rtl2830_read_ucblocks,
542 .read_signal_strength = rtl2830_read_signal_strength,
543};
544
545MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
546MODULE_DESCRIPTION("Realtek RTL2830 DVB-T demodulator driver");
547MODULE_LICENSE("GPL");