blob: 3954760f2bdee8b34a4c8b7ffa689fd1de1bfb96 [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
Antti Palosaari0485a702011-08-04 20:27:19 -030030/* write multiple hardware registers */
31static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, u8 *val, int len)
Antti Palosaaric0adca72011-07-08 23:34:09 -030032{
33 int ret;
Antti Palosaari0485a702011-08-04 20:27:19 -030034 u8 buf[1+len];
Antti Palosaaric0adca72011-07-08 23:34:09 -030035 struct i2c_msg msg[1] = {
36 {
37 .addr = priv->cfg.i2c_addr,
38 .flags = 0,
Antti Palosaari0485a702011-08-04 20:27:19 -030039 .len = 1+len,
Antti Palosaaric0adca72011-07-08 23:34:09 -030040 .buf = buf,
41 }
42 };
43
Antti Palosaari0485a702011-08-04 20:27:19 -030044 buf[0] = reg;
45 memcpy(&buf[1], val, len);
Antti Palosaaric0adca72011-07-08 23:34:09 -030046
47 ret = i2c_transfer(priv->i2c, msg, 1);
48 if (ret == 1) {
49 ret = 0;
50 } else {
Antti Palosaari86ad0f12012-09-12 20:23:47 -030051 dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
52 "len=%d\n", KBUILD_MODNAME, ret, reg, len);
Antti Palosaaric0adca72011-07-08 23:34:09 -030053 ret = -EREMOTEIO;
54 }
55 return ret;
56}
57
Antti Palosaari0485a702011-08-04 20:27:19 -030058/* read multiple hardware registers */
59static int rtl2830_rd(struct rtl2830_priv *priv, u8 reg, u8 *val, int len)
Antti Palosaaric0adca72011-07-08 23:34:09 -030060{
61 int ret;
Antti Palosaaric0adca72011-07-08 23:34:09 -030062 struct i2c_msg msg[2] = {
63 {
64 .addr = priv->cfg.i2c_addr,
65 .flags = 0,
Antti Palosaari0485a702011-08-04 20:27:19 -030066 .len = 1,
67 .buf = &reg,
Antti Palosaaric0adca72011-07-08 23:34:09 -030068 }, {
69 .addr = priv->cfg.i2c_addr,
70 .flags = I2C_M_RD,
71 .len = len,
72 .buf = val,
73 }
74 };
75
Antti Palosaaric0adca72011-07-08 23:34:09 -030076 ret = i2c_transfer(priv->i2c, msg, 2);
77 if (ret == 2) {
78 ret = 0;
79 } else {
Antti Palosaari86ad0f12012-09-12 20:23:47 -030080 dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
81 "len=%d\n", KBUILD_MODNAME, ret, reg, len);
Antti Palosaaric0adca72011-07-08 23:34:09 -030082 ret = -EREMOTEIO;
83 }
84 return ret;
85}
86
Antti Palosaari0485a702011-08-04 20:27:19 -030087/* write multiple registers */
88static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len)
89{
90 int ret;
91 u8 reg2 = (reg >> 0) & 0xff;
92 u8 page = (reg >> 8) & 0xff;
93
94 /* switch bank if needed */
95 if (page != priv->page) {
96 ret = rtl2830_wr(priv, 0x00, &page, 1);
97 if (ret)
98 return ret;
99
100 priv->page = page;
101 }
102
103 return rtl2830_wr(priv, reg2, val, len);
104}
105
106/* read multiple registers */
107static int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len)
108{
109 int ret;
110 u8 reg2 = (reg >> 0) & 0xff;
111 u8 page = (reg >> 8) & 0xff;
112
113 /* switch bank if needed */
114 if (page != priv->page) {
115 ret = rtl2830_wr(priv, 0x00, &page, 1);
116 if (ret)
117 return ret;
118
119 priv->page = page;
120 }
121
122 return rtl2830_rd(priv, reg2, val, len);
123}
124
Antti Palosaaric0adca72011-07-08 23:34:09 -0300125#if 0 /* currently not used */
126/* write single register */
127static int rtl2830_wr_reg(struct rtl2830_priv *priv, u16 reg, u8 val)
128{
129 return rtl2830_wr_regs(priv, reg, &val, 1);
130}
131#endif
132
133/* read single register */
134static int rtl2830_rd_reg(struct rtl2830_priv *priv, u16 reg, u8 *val)
135{
136 return rtl2830_rd_regs(priv, reg, val, 1);
137}
138
139/* write single register with mask */
140int rtl2830_wr_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 val, u8 mask)
141{
142 int ret;
143 u8 tmp;
144
145 /* no need for read if whole reg is written */
146 if (mask != 0xff) {
147 ret = rtl2830_rd_regs(priv, reg, &tmp, 1);
148 if (ret)
149 return ret;
150
151 val &= mask;
152 tmp &= ~mask;
153 val |= tmp;
154 }
155
156 return rtl2830_wr_regs(priv, reg, &val, 1);
157}
158
159/* read single register with mask */
160int rtl2830_rd_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 *val, u8 mask)
161{
162 int ret, i;
163 u8 tmp;
164
165 ret = rtl2830_rd_regs(priv, reg, &tmp, 1);
166 if (ret)
167 return ret;
168
169 tmp &= mask;
170
171 /* find position of the first bit */
172 for (i = 0; i < 8; i++) {
173 if ((mask >> i) & 0x01)
174 break;
175 }
176 *val = tmp >> i;
177
178 return 0;
179}
180
181static int rtl2830_init(struct dvb_frontend *fe)
182{
183 struct rtl2830_priv *priv = fe->demodulator_priv;
184 int ret, i;
Antti Palosaaric0adca72011-07-08 23:34:09 -0300185 struct rtl2830_reg_val_mask tab[] = {
186 { 0x00d, 0x01, 0x03 },
187 { 0x00d, 0x10, 0x10 },
188 { 0x104, 0x00, 0x1e },
189 { 0x105, 0x80, 0x80 },
190 { 0x110, 0x02, 0x03 },
191 { 0x110, 0x08, 0x0c },
192 { 0x17b, 0x00, 0x40 },
193 { 0x17d, 0x05, 0x0f },
194 { 0x17d, 0x50, 0xf0 },
195 { 0x18c, 0x08, 0x0f },
196 { 0x18d, 0x00, 0xc0 },
197 { 0x188, 0x05, 0x0f },
198 { 0x189, 0x00, 0xfc },
199 { 0x2d5, 0x02, 0x02 },
200 { 0x2f1, 0x02, 0x06 },
201 { 0x2f1, 0x20, 0xf8 },
202 { 0x16d, 0x00, 0x01 },
203 { 0x1a6, 0x00, 0x80 },
204 { 0x106, priv->cfg.vtop, 0x3f },
205 { 0x107, priv->cfg.krf, 0x3f },
206 { 0x112, 0x28, 0xff },
207 { 0x103, priv->cfg.agc_targ_val, 0xff },
208 { 0x00a, 0x02, 0x07 },
209 { 0x140, 0x0c, 0x3c },
210 { 0x140, 0x40, 0xc0 },
211 { 0x15b, 0x05, 0x07 },
212 { 0x15b, 0x28, 0x38 },
213 { 0x15c, 0x05, 0x07 },
214 { 0x15c, 0x28, 0x38 },
215 { 0x115, priv->cfg.spec_inv, 0x01 },
216 { 0x16f, 0x01, 0x07 },
217 { 0x170, 0x18, 0x38 },
218 { 0x172, 0x0f, 0x0f },
219 { 0x173, 0x08, 0x38 },
220 { 0x175, 0x01, 0x07 },
221 { 0x176, 0x00, 0xc0 },
222 };
223
224 for (i = 0; i < ARRAY_SIZE(tab); i++) {
225 ret = rtl2830_wr_reg_mask(priv, tab[i].reg, tab[i].val,
226 tab[i].mask);
227 if (ret)
228 goto err;
229 }
230
231 ret = rtl2830_wr_regs(priv, 0x18f, "\x28\x00", 2);
232 if (ret)
233 goto err;
234
235 ret = rtl2830_wr_regs(priv, 0x195,
236 "\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8);
237 if (ret)
238 goto err;
239
Antti Palosaaric0adca72011-07-08 23:34:09 -0300240 /* TODO: spec init */
241
242 /* soft reset */
243 ret = rtl2830_wr_reg_mask(priv, 0x101, 0x04, 0x04);
244 if (ret)
245 goto err;
246
247 ret = rtl2830_wr_reg_mask(priv, 0x101, 0x00, 0x04);
248 if (ret)
249 goto err;
250
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300251 priv->sleeping = false;
252
Antti Palosaaric0adca72011-07-08 23:34:09 -0300253 return ret;
254err:
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300255 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300256 return ret;
257}
258
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300259static int rtl2830_sleep(struct dvb_frontend *fe)
260{
261 struct rtl2830_priv *priv = fe->demodulator_priv;
262 priv->sleeping = true;
263 return 0;
264}
265
Antti Palosaaric0adca72011-07-08 23:34:09 -0300266int rtl2830_get_tune_settings(struct dvb_frontend *fe,
267 struct dvb_frontend_tune_settings *s)
268{
269 s->min_delay_ms = 500;
270 s->step_size = fe->ops.info.frequency_stepsize * 2;
271 s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
272
273 return 0;
274}
275
276static int rtl2830_set_frontend(struct dvb_frontend *fe)
277{
278 struct rtl2830_priv *priv = fe->demodulator_priv;
279 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
280 int ret, i;
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300281 u64 num;
282 u8 buf[3], tmp;
283 u32 if_ctl, if_frequency;
Antti Palosaaric0adca72011-07-08 23:34:09 -0300284 static u8 bw_params1[3][34] = {
285 {
286 0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0xfa, 0x00, 0x17, 0x00, 0x41,
287 0x00, 0x64, 0x00, 0x67, 0x00, 0x38, 0x1f, 0xde, 0x1f, 0x7a,
288 0x1f, 0x47, 0x1f, 0x7c, 0x00, 0x30, 0x01, 0x4b, 0x02, 0x82,
289 0x03, 0x73, 0x03, 0xcf, /* 6 MHz */
290 }, {
291 0x1f, 0xfa, 0x1f, 0xda, 0x1f, 0xc1, 0x1f, 0xb3, 0x1f, 0xca,
292 0x00, 0x07, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x40, 0x1f, 0xca,
293 0x1f, 0x4d, 0x1f, 0x2a, 0x1f, 0xb2, 0x00, 0xec, 0x02, 0x7e,
294 0x03, 0xd0, 0x04, 0x53, /* 7 MHz */
295 }, {
296 0x00, 0x10, 0x00, 0x0e, 0x1f, 0xf7, 0x1f, 0xc9, 0x1f, 0xa0,
297 0x1f, 0xa6, 0x1f, 0xec, 0x00, 0x4e, 0x00, 0x7d, 0x00, 0x3a,
298 0x1f, 0x98, 0x1f, 0x10, 0x1f, 0x40, 0x00, 0x75, 0x02, 0x5f,
299 0x04, 0x24, 0x04, 0xdb, /* 8 MHz */
300 },
301 };
302 static u8 bw_params2[3][6] = {
303 {0xc3, 0x0c, 0x44, 0x33, 0x33, 0x30,}, /* 6 MHz */
304 {0xb8, 0xe3, 0x93, 0x99, 0x99, 0x98,}, /* 7 MHz */
305 {0xae, 0xba, 0xf3, 0x26, 0x66, 0x64,}, /* 8 MHz */
306 };
307
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300308 dev_dbg(&priv->i2c->dev,
309 "%s: frequency=%d bandwidth_hz=%d inversion=%d\n",
310 __func__, c->frequency, c->bandwidth_hz, c->inversion);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300311
312 /* program tuner */
313 if (fe->ops.tuner_ops.set_params)
314 fe->ops.tuner_ops.set_params(fe);
315
316 switch (c->bandwidth_hz) {
317 case 6000000:
318 i = 0;
319 break;
320 case 7000000:
321 i = 1;
322 break;
323 case 8000000:
324 i = 2;
325 break;
326 default:
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300327 dev_dbg(&priv->i2c->dev, "%s: invalid bandwidth\n", __func__);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300328 return -EINVAL;
329 }
330
331 ret = rtl2830_wr_reg_mask(priv, 0x008, i << 1, 0x06);
332 if (ret)
333 goto err;
334
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300335 /* program if frequency */
336 if (fe->ops.tuner_ops.get_if_frequency)
337 ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
338 else
339 ret = -EINVAL;
340
341 if (ret < 0)
342 goto err;
343
344 num = if_frequency % priv->cfg.xtal;
345 num *= 0x400000;
346 num = div_u64(num, priv->cfg.xtal);
347 num = -num;
348 if_ctl = num & 0x3fffff;
349 dev_dbg(&priv->i2c->dev, "%s: if_frequency=%d if_ctl=%08x\n",
350 __func__, if_frequency, if_ctl);
351
352 ret = rtl2830_rd_reg_mask(priv, 0x119, &tmp, 0xc0); /* b[7:6] */
353 if (ret)
354 goto err;
355
356 buf[0] = tmp << 6;
357 buf[0] |= (if_ctl >> 16) & 0x3f;
358 buf[1] = (if_ctl >> 8) & 0xff;
359 buf[2] = (if_ctl >> 0) & 0xff;
360
361 ret = rtl2830_wr_regs(priv, 0x119, buf, 3);
362 if (ret)
363 goto err;
364
Antti Palosaaric0adca72011-07-08 23:34:09 -0300365 /* 1/2 split I2C write */
366 ret = rtl2830_wr_regs(priv, 0x11c, &bw_params1[i][0], 17);
367 if (ret)
368 goto err;
369
370 /* 2/2 split I2C write */
371 ret = rtl2830_wr_regs(priv, 0x12d, &bw_params1[i][17], 17);
372 if (ret)
373 goto err;
374
375 ret = rtl2830_wr_regs(priv, 0x19d, bw_params2[i], 6);
376 if (ret)
377 goto err;
378
379 return ret;
380err:
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300381 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300382 return ret;
383}
384
Antti Palosaari631a2b62012-05-18 15:58:57 -0300385static int rtl2830_get_frontend(struct dvb_frontend *fe)
386{
387 struct rtl2830_priv *priv = fe->demodulator_priv;
388 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
389 int ret;
390 u8 buf[3];
391
Antti Palosaaric1886372012-05-18 16:02:55 -0300392 if (priv->sleeping)
393 return 0;
394
Antti Palosaari631a2b62012-05-18 15:58:57 -0300395 ret = rtl2830_rd_regs(priv, 0x33c, buf, 2);
396 if (ret)
397 goto err;
398
399 ret = rtl2830_rd_reg(priv, 0x351, &buf[2]);
400 if (ret)
401 goto err;
402
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300403 dev_dbg(&priv->i2c->dev, "%s: TPS=%*ph\n", __func__, 3, buf);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300404
405 switch ((buf[0] >> 2) & 3) {
406 case 0:
407 c->modulation = QPSK;
408 break;
409 case 1:
410 c->modulation = QAM_16;
411 break;
412 case 2:
413 c->modulation = QAM_64;
414 break;
415 }
416
417 switch ((buf[2] >> 2) & 1) {
418 case 0:
419 c->transmission_mode = TRANSMISSION_MODE_2K;
420 break;
421 case 1:
422 c->transmission_mode = TRANSMISSION_MODE_8K;
423 }
424
425 switch ((buf[2] >> 0) & 3) {
426 case 0:
427 c->guard_interval = GUARD_INTERVAL_1_32;
428 break;
429 case 1:
430 c->guard_interval = GUARD_INTERVAL_1_16;
431 break;
432 case 2:
433 c->guard_interval = GUARD_INTERVAL_1_8;
434 break;
435 case 3:
436 c->guard_interval = GUARD_INTERVAL_1_4;
437 break;
438 }
439
440 switch ((buf[0] >> 4) & 7) {
441 case 0:
442 c->hierarchy = HIERARCHY_NONE;
443 break;
444 case 1:
445 c->hierarchy = HIERARCHY_1;
446 break;
447 case 2:
448 c->hierarchy = HIERARCHY_2;
449 break;
450 case 3:
451 c->hierarchy = HIERARCHY_4;
452 break;
453 }
454
455 switch ((buf[1] >> 3) & 7) {
456 case 0:
457 c->code_rate_HP = FEC_1_2;
458 break;
459 case 1:
460 c->code_rate_HP = FEC_2_3;
461 break;
462 case 2:
463 c->code_rate_HP = FEC_3_4;
464 break;
465 case 3:
466 c->code_rate_HP = FEC_5_6;
467 break;
468 case 4:
469 c->code_rate_HP = FEC_7_8;
470 break;
471 }
472
473 switch ((buf[1] >> 0) & 7) {
474 case 0:
475 c->code_rate_LP = FEC_1_2;
476 break;
477 case 1:
478 c->code_rate_LP = FEC_2_3;
479 break;
480 case 2:
481 c->code_rate_LP = FEC_3_4;
482 break;
483 case 3:
484 c->code_rate_LP = FEC_5_6;
485 break;
486 case 4:
487 c->code_rate_LP = FEC_7_8;
488 break;
489 }
490
491 return 0;
492err:
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300493 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300494 return ret;
495}
496
Antti Palosaaric0adca72011-07-08 23:34:09 -0300497static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status)
498{
499 struct rtl2830_priv *priv = fe->demodulator_priv;
500 int ret;
501 u8 tmp;
502 *status = 0;
503
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300504 if (priv->sleeping)
505 return 0;
506
Antti Palosaaric0adca72011-07-08 23:34:09 -0300507 ret = rtl2830_rd_reg_mask(priv, 0x351, &tmp, 0x78); /* [6:3] */
508 if (ret)
509 goto err;
510
511 if (tmp == 11) {
512 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
513 FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
514 } else if (tmp == 10) {
515 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
516 FE_HAS_VITERBI;
517 }
518
519 return ret;
520err:
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300521 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300522 return ret;
523}
524
525static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr)
526{
Antti Palosaarieba672a2012-05-15 18:32:33 -0300527 struct rtl2830_priv *priv = fe->demodulator_priv;
528 int ret, hierarchy, constellation;
529 u8 buf[2], tmp;
530 u16 tmp16;
531#define CONSTELLATION_NUM 3
532#define HIERARCHY_NUM 4
533 static const u32 snr_constant[CONSTELLATION_NUM][HIERARCHY_NUM] = {
534 { 70705899, 70705899, 70705899, 70705899 },
535 { 82433173, 82433173, 87483115, 94445660 },
536 { 92888734, 92888734, 95487525, 99770748 },
537 };
538
Antti Palosaaric1886372012-05-18 16:02:55 -0300539 if (priv->sleeping)
540 return 0;
541
Antti Palosaarieba672a2012-05-15 18:32:33 -0300542 /* reports SNR in resolution of 0.1 dB */
543
544 ret = rtl2830_rd_reg(priv, 0x33c, &tmp);
545 if (ret)
546 goto err;
547
548 constellation = (tmp >> 2) & 0x03; /* [3:2] */
549 if (constellation > CONSTELLATION_NUM - 1)
550 goto err;
551
552 hierarchy = (tmp >> 4) & 0x07; /* [6:4] */
553 if (hierarchy > HIERARCHY_NUM - 1)
554 goto err;
555
556 ret = rtl2830_rd_regs(priv, 0x40c, buf, 2);
557 if (ret)
558 goto err;
559
560 tmp16 = buf[0] << 8 | buf[1];
561
562 if (tmp16)
563 *snr = (snr_constant[constellation][hierarchy] -
564 intlog10(tmp16)) / ((1 << 24) / 100);
565 else
566 *snr = 0;
567
Antti Palosaaric0adca72011-07-08 23:34:09 -0300568 return 0;
Antti Palosaarieba672a2012-05-15 18:32:33 -0300569err:
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300570 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Antti Palosaarieba672a2012-05-15 18:32:33 -0300571 return ret;
Antti Palosaaric0adca72011-07-08 23:34:09 -0300572}
573
574static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber)
575{
Antti Palosaari525ffc12012-05-18 12:23:42 -0300576 struct rtl2830_priv *priv = fe->demodulator_priv;
577 int ret;
578 u8 buf[2];
579
Antti Palosaaric1886372012-05-18 16:02:55 -0300580 if (priv->sleeping)
581 return 0;
582
Antti Palosaari525ffc12012-05-18 12:23:42 -0300583 ret = rtl2830_rd_regs(priv, 0x34e, buf, 2);
584 if (ret)
585 goto err;
586
587 *ber = buf[0] << 8 | buf[1];
588
Antti Palosaaric0adca72011-07-08 23:34:09 -0300589 return 0;
Antti Palosaari525ffc12012-05-18 12:23:42 -0300590err:
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300591 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Antti Palosaari525ffc12012-05-18 12:23:42 -0300592 return ret;
Antti Palosaaric0adca72011-07-08 23:34:09 -0300593}
594
595static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
596{
597 *ucblocks = 0;
598 return 0;
599}
600
601static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
602{
Antti Palosaari78e75072012-05-18 15:17:51 -0300603 struct rtl2830_priv *priv = fe->demodulator_priv;
604 int ret;
605 u8 buf[2];
606 u16 if_agc_raw, if_agc;
607
Antti Palosaaric1886372012-05-18 16:02:55 -0300608 if (priv->sleeping)
609 return 0;
610
Antti Palosaari78e75072012-05-18 15:17:51 -0300611 ret = rtl2830_rd_regs(priv, 0x359, buf, 2);
612 if (ret)
613 goto err;
614
615 if_agc_raw = (buf[0] << 8 | buf[1]) & 0x3fff;
616
617 if (if_agc_raw & (1 << 9))
618 if_agc = -(~(if_agc_raw - 1) & 0x1ff);
619 else
620 if_agc = if_agc_raw;
621
622 *strength = (u8) (55 - if_agc / 182);
623 *strength |= *strength << 8;
624
Antti Palosaaric0adca72011-07-08 23:34:09 -0300625 return 0;
Antti Palosaari78e75072012-05-18 15:17:51 -0300626err:
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300627 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Antti Palosaari78e75072012-05-18 15:17:51 -0300628 return ret;
Antti Palosaaric0adca72011-07-08 23:34:09 -0300629}
630
631static struct dvb_frontend_ops rtl2830_ops;
632
633static u32 rtl2830_tuner_i2c_func(struct i2c_adapter *adapter)
634{
635 return I2C_FUNC_I2C;
636}
637
638static int rtl2830_tuner_i2c_xfer(struct i2c_adapter *i2c_adap,
639 struct i2c_msg msg[], int num)
640{
641 struct rtl2830_priv *priv = i2c_get_adapdata(i2c_adap);
642 int ret;
643
644 /* open i2c-gate */
645 ret = rtl2830_wr_reg_mask(priv, 0x101, 0x08, 0x08);
646 if (ret)
647 goto err;
648
649 ret = i2c_transfer(priv->i2c, msg, num);
650 if (ret < 0)
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300651 dev_warn(&priv->i2c->dev, "%s: tuner i2c failed=%d\n",
652 KBUILD_MODNAME, ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300653
654 return ret;
655err:
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300656 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300657 return ret;
658}
659
660static struct i2c_algorithm rtl2830_tuner_i2c_algo = {
661 .master_xfer = rtl2830_tuner_i2c_xfer,
662 .functionality = rtl2830_tuner_i2c_func,
663};
664
665struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(struct dvb_frontend *fe)
666{
667 struct rtl2830_priv *priv = fe->demodulator_priv;
668 return &priv->tuner_i2c_adapter;
669}
670EXPORT_SYMBOL(rtl2830_get_tuner_i2c_adapter);
671
672static void rtl2830_release(struct dvb_frontend *fe)
673{
674 struct rtl2830_priv *priv = fe->demodulator_priv;
675
676 i2c_del_adapter(&priv->tuner_i2c_adapter);
677 kfree(priv);
678}
679
680struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg,
681 struct i2c_adapter *i2c)
682{
683 struct rtl2830_priv *priv = NULL;
684 int ret = 0;
685 u8 tmp;
686
687 /* allocate memory for the internal state */
688 priv = kzalloc(sizeof(struct rtl2830_priv), GFP_KERNEL);
689 if (priv == NULL)
690 goto err;
691
692 /* setup the priv */
693 priv->i2c = i2c;
694 memcpy(&priv->cfg, cfg, sizeof(struct rtl2830_config));
695
696 /* check if the demod is there */
697 ret = rtl2830_rd_reg(priv, 0x000, &tmp);
698 if (ret)
699 goto err;
700
701 /* create dvb_frontend */
702 memcpy(&priv->fe.ops, &rtl2830_ops, sizeof(struct dvb_frontend_ops));
703 priv->fe.demodulator_priv = priv;
704
705 /* create tuner i2c adapter */
706 strlcpy(priv->tuner_i2c_adapter.name, "RTL2830 tuner I2C adapter",
707 sizeof(priv->tuner_i2c_adapter.name));
708 priv->tuner_i2c_adapter.algo = &rtl2830_tuner_i2c_algo;
709 priv->tuner_i2c_adapter.algo_data = NULL;
710 i2c_set_adapdata(&priv->tuner_i2c_adapter, priv);
711 if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) {
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300712 dev_err(&i2c->dev,
713 "%s: tuner i2c bus could not be initialized\n",
714 KBUILD_MODNAME);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300715 goto err;
716 }
717
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300718 priv->sleeping = true;
719
Antti Palosaaric0adca72011-07-08 23:34:09 -0300720 return &priv->fe;
721err:
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300722 dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300723 kfree(priv);
724 return NULL;
725}
726EXPORT_SYMBOL(rtl2830_attach);
727
728static struct dvb_frontend_ops rtl2830_ops = {
729 .delsys = { SYS_DVBT },
730 .info = {
731 .name = "Realtek RTL2830 (DVB-T)",
732 .caps = FE_CAN_FEC_1_2 |
733 FE_CAN_FEC_2_3 |
734 FE_CAN_FEC_3_4 |
735 FE_CAN_FEC_5_6 |
736 FE_CAN_FEC_7_8 |
737 FE_CAN_FEC_AUTO |
738 FE_CAN_QPSK |
739 FE_CAN_QAM_16 |
740 FE_CAN_QAM_64 |
741 FE_CAN_QAM_AUTO |
742 FE_CAN_TRANSMISSION_MODE_AUTO |
743 FE_CAN_GUARD_INTERVAL_AUTO |
744 FE_CAN_HIERARCHY_AUTO |
745 FE_CAN_RECOVER |
746 FE_CAN_MUTE_TS
747 },
748
749 .release = rtl2830_release,
750
751 .init = rtl2830_init,
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300752 .sleep = rtl2830_sleep,
Antti Palosaaric0adca72011-07-08 23:34:09 -0300753
754 .get_tune_settings = rtl2830_get_tune_settings,
755
756 .set_frontend = rtl2830_set_frontend,
Antti Palosaari631a2b62012-05-18 15:58:57 -0300757 .get_frontend = rtl2830_get_frontend,
Antti Palosaaric0adca72011-07-08 23:34:09 -0300758
759 .read_status = rtl2830_read_status,
760 .read_snr = rtl2830_read_snr,
761 .read_ber = rtl2830_read_ber,
762 .read_ucblocks = rtl2830_read_ucblocks,
763 .read_signal_strength = rtl2830_read_signal_strength,
764};
765
766MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
767MODULE_DESCRIPTION("Realtek RTL2830 DVB-T demodulator driver");
768MODULE_LICENSE("GPL");