blob: 362d26d11e82a4d1f975db097679c7d4bb7ddb97 [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 */
Antti Palosaari3a2fca22012-09-12 20:23:49 -030031static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, const 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 */
Antti Palosaari3a2fca22012-09-12 20:23:49 -030088static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, const u8 *val,
89 int len)
Antti Palosaari0485a702011-08-04 20:27:19 -030090{
91 int ret;
92 u8 reg2 = (reg >> 0) & 0xff;
93 u8 page = (reg >> 8) & 0xff;
94
95 /* switch bank if needed */
96 if (page != priv->page) {
97 ret = rtl2830_wr(priv, 0x00, &page, 1);
98 if (ret)
99 return ret;
100
101 priv->page = page;
102 }
103
104 return rtl2830_wr(priv, reg2, val, len);
105}
106
107/* read multiple registers */
108static int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len)
109{
110 int ret;
111 u8 reg2 = (reg >> 0) & 0xff;
112 u8 page = (reg >> 8) & 0xff;
113
114 /* switch bank if needed */
115 if (page != priv->page) {
116 ret = rtl2830_wr(priv, 0x00, &page, 1);
117 if (ret)
118 return ret;
119
120 priv->page = page;
121 }
122
123 return rtl2830_rd(priv, reg2, val, len);
124}
125
Antti Palosaaric0adca72011-07-08 23:34:09 -0300126/* read single register */
127static int rtl2830_rd_reg(struct rtl2830_priv *priv, u16 reg, u8 *val)
128{
129 return rtl2830_rd_regs(priv, reg, val, 1);
130}
131
132/* write single register with mask */
Mauro Carvalho Chehaba17ff2e2012-10-27 11:24:08 -0300133static int rtl2830_wr_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 val, u8 mask)
Antti Palosaaric0adca72011-07-08 23:34:09 -0300134{
135 int ret;
136 u8 tmp;
137
138 /* no need for read if whole reg is written */
139 if (mask != 0xff) {
140 ret = rtl2830_rd_regs(priv, reg, &tmp, 1);
141 if (ret)
142 return ret;
143
144 val &= mask;
145 tmp &= ~mask;
146 val |= tmp;
147 }
148
149 return rtl2830_wr_regs(priv, reg, &val, 1);
150}
151
152/* read single register with mask */
Mauro Carvalho Chehaba17ff2e2012-10-27 11:24:08 -0300153static int rtl2830_rd_reg_mask(struct rtl2830_priv *priv, u16 reg, u8 *val, u8 mask)
Antti Palosaaric0adca72011-07-08 23:34:09 -0300154{
155 int ret, i;
156 u8 tmp;
157
158 ret = rtl2830_rd_regs(priv, reg, &tmp, 1);
159 if (ret)
160 return ret;
161
162 tmp &= mask;
163
164 /* find position of the first bit */
165 for (i = 0; i < 8; i++) {
166 if ((mask >> i) & 0x01)
167 break;
168 }
169 *val = tmp >> i;
170
171 return 0;
172}
173
174static int rtl2830_init(struct dvb_frontend *fe)
175{
176 struct rtl2830_priv *priv = fe->demodulator_priv;
177 int ret, i;
Antti Palosaaric0adca72011-07-08 23:34:09 -0300178 struct rtl2830_reg_val_mask tab[] = {
179 { 0x00d, 0x01, 0x03 },
180 { 0x00d, 0x10, 0x10 },
181 { 0x104, 0x00, 0x1e },
182 { 0x105, 0x80, 0x80 },
183 { 0x110, 0x02, 0x03 },
184 { 0x110, 0x08, 0x0c },
185 { 0x17b, 0x00, 0x40 },
186 { 0x17d, 0x05, 0x0f },
187 { 0x17d, 0x50, 0xf0 },
188 { 0x18c, 0x08, 0x0f },
189 { 0x18d, 0x00, 0xc0 },
190 { 0x188, 0x05, 0x0f },
191 { 0x189, 0x00, 0xfc },
192 { 0x2d5, 0x02, 0x02 },
193 { 0x2f1, 0x02, 0x06 },
194 { 0x2f1, 0x20, 0xf8 },
195 { 0x16d, 0x00, 0x01 },
196 { 0x1a6, 0x00, 0x80 },
197 { 0x106, priv->cfg.vtop, 0x3f },
198 { 0x107, priv->cfg.krf, 0x3f },
199 { 0x112, 0x28, 0xff },
200 { 0x103, priv->cfg.agc_targ_val, 0xff },
201 { 0x00a, 0x02, 0x07 },
202 { 0x140, 0x0c, 0x3c },
203 { 0x140, 0x40, 0xc0 },
204 { 0x15b, 0x05, 0x07 },
205 { 0x15b, 0x28, 0x38 },
206 { 0x15c, 0x05, 0x07 },
207 { 0x15c, 0x28, 0x38 },
208 { 0x115, priv->cfg.spec_inv, 0x01 },
209 { 0x16f, 0x01, 0x07 },
210 { 0x170, 0x18, 0x38 },
211 { 0x172, 0x0f, 0x0f },
212 { 0x173, 0x08, 0x38 },
213 { 0x175, 0x01, 0x07 },
214 { 0x176, 0x00, 0xc0 },
215 };
216
217 for (i = 0; i < ARRAY_SIZE(tab); i++) {
218 ret = rtl2830_wr_reg_mask(priv, tab[i].reg, tab[i].val,
219 tab[i].mask);
220 if (ret)
221 goto err;
222 }
223
224 ret = rtl2830_wr_regs(priv, 0x18f, "\x28\x00", 2);
225 if (ret)
226 goto err;
227
228 ret = rtl2830_wr_regs(priv, 0x195,
229 "\x04\x06\x0a\x12\x0a\x12\x1e\x28", 8);
230 if (ret)
231 goto err;
232
Antti Palosaaric0adca72011-07-08 23:34:09 -0300233 /* TODO: spec init */
234
235 /* soft reset */
236 ret = rtl2830_wr_reg_mask(priv, 0x101, 0x04, 0x04);
237 if (ret)
238 goto err;
239
240 ret = rtl2830_wr_reg_mask(priv, 0x101, 0x00, 0x04);
241 if (ret)
242 goto err;
243
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300244 priv->sleeping = false;
245
Antti Palosaaric0adca72011-07-08 23:34:09 -0300246 return ret;
247err:
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300248 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300249 return ret;
250}
251
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300252static int rtl2830_sleep(struct dvb_frontend *fe)
253{
254 struct rtl2830_priv *priv = fe->demodulator_priv;
255 priv->sleeping = true;
256 return 0;
257}
258
Mauro Carvalho Chehaba17ff2e2012-10-27 11:24:08 -0300259static int rtl2830_get_tune_settings(struct dvb_frontend *fe,
Antti Palosaaric0adca72011-07-08 23:34:09 -0300260 struct dvb_frontend_tune_settings *s)
261{
262 s->min_delay_ms = 500;
263 s->step_size = fe->ops.info.frequency_stepsize * 2;
264 s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
265
266 return 0;
267}
268
269static int rtl2830_set_frontend(struct dvb_frontend *fe)
270{
271 struct rtl2830_priv *priv = fe->demodulator_priv;
272 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
273 int ret, i;
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300274 u64 num;
275 u8 buf[3], tmp;
276 u32 if_ctl, if_frequency;
Antti Palosaari3a2fca22012-09-12 20:23:49 -0300277 static const u8 bw_params1[3][34] = {
Antti Palosaaric0adca72011-07-08 23:34:09 -0300278 {
279 0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0xfa, 0x00, 0x17, 0x00, 0x41,
280 0x00, 0x64, 0x00, 0x67, 0x00, 0x38, 0x1f, 0xde, 0x1f, 0x7a,
281 0x1f, 0x47, 0x1f, 0x7c, 0x00, 0x30, 0x01, 0x4b, 0x02, 0x82,
282 0x03, 0x73, 0x03, 0xcf, /* 6 MHz */
283 }, {
284 0x1f, 0xfa, 0x1f, 0xda, 0x1f, 0xc1, 0x1f, 0xb3, 0x1f, 0xca,
285 0x00, 0x07, 0x00, 0x4d, 0x00, 0x6d, 0x00, 0x40, 0x1f, 0xca,
286 0x1f, 0x4d, 0x1f, 0x2a, 0x1f, 0xb2, 0x00, 0xec, 0x02, 0x7e,
287 0x03, 0xd0, 0x04, 0x53, /* 7 MHz */
288 }, {
289 0x00, 0x10, 0x00, 0x0e, 0x1f, 0xf7, 0x1f, 0xc9, 0x1f, 0xa0,
290 0x1f, 0xa6, 0x1f, 0xec, 0x00, 0x4e, 0x00, 0x7d, 0x00, 0x3a,
291 0x1f, 0x98, 0x1f, 0x10, 0x1f, 0x40, 0x00, 0x75, 0x02, 0x5f,
292 0x04, 0x24, 0x04, 0xdb, /* 8 MHz */
293 },
294 };
Antti Palosaari3a2fca22012-09-12 20:23:49 -0300295 static const u8 bw_params2[3][6] = {
296 {0xc3, 0x0c, 0x44, 0x33, 0x33, 0x30}, /* 6 MHz */
297 {0xb8, 0xe3, 0x93, 0x99, 0x99, 0x98}, /* 7 MHz */
298 {0xae, 0xba, 0xf3, 0x26, 0x66, 0x64}, /* 8 MHz */
Antti Palosaaric0adca72011-07-08 23:34:09 -0300299 };
300
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300301 dev_dbg(&priv->i2c->dev,
302 "%s: frequency=%d bandwidth_hz=%d inversion=%d\n",
303 __func__, c->frequency, c->bandwidth_hz, c->inversion);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300304
305 /* program tuner */
306 if (fe->ops.tuner_ops.set_params)
307 fe->ops.tuner_ops.set_params(fe);
308
309 switch (c->bandwidth_hz) {
310 case 6000000:
311 i = 0;
312 break;
313 case 7000000:
314 i = 1;
315 break;
316 case 8000000:
317 i = 2;
318 break;
319 default:
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300320 dev_dbg(&priv->i2c->dev, "%s: invalid bandwidth\n", __func__);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300321 return -EINVAL;
322 }
323
324 ret = rtl2830_wr_reg_mask(priv, 0x008, i << 1, 0x06);
325 if (ret)
326 goto err;
327
Antti Palosaari66b3c4d2012-09-12 20:23:48 -0300328 /* program if frequency */
329 if (fe->ops.tuner_ops.get_if_frequency)
330 ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
331 else
332 ret = -EINVAL;
333
334 if (ret < 0)
335 goto err;
336
337 num = if_frequency % priv->cfg.xtal;
338 num *= 0x400000;
339 num = div_u64(num, priv->cfg.xtal);
340 num = -num;
341 if_ctl = num & 0x3fffff;
342 dev_dbg(&priv->i2c->dev, "%s: if_frequency=%d if_ctl=%08x\n",
343 __func__, if_frequency, if_ctl);
344
345 ret = rtl2830_rd_reg_mask(priv, 0x119, &tmp, 0xc0); /* b[7:6] */
346 if (ret)
347 goto err;
348
349 buf[0] = tmp << 6;
350 buf[0] |= (if_ctl >> 16) & 0x3f;
351 buf[1] = (if_ctl >> 8) & 0xff;
352 buf[2] = (if_ctl >> 0) & 0xff;
353
354 ret = rtl2830_wr_regs(priv, 0x119, buf, 3);
355 if (ret)
356 goto err;
357
Antti Palosaaric0adca72011-07-08 23:34:09 -0300358 /* 1/2 split I2C write */
359 ret = rtl2830_wr_regs(priv, 0x11c, &bw_params1[i][0], 17);
360 if (ret)
361 goto err;
362
363 /* 2/2 split I2C write */
364 ret = rtl2830_wr_regs(priv, 0x12d, &bw_params1[i][17], 17);
365 if (ret)
366 goto err;
367
368 ret = rtl2830_wr_regs(priv, 0x19d, bw_params2[i], 6);
369 if (ret)
370 goto err;
371
372 return ret;
373err:
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300374 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300375 return ret;
376}
377
Antti Palosaari631a2b62012-05-18 15:58:57 -0300378static int rtl2830_get_frontend(struct dvb_frontend *fe)
379{
380 struct rtl2830_priv *priv = fe->demodulator_priv;
381 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
382 int ret;
383 u8 buf[3];
384
Antti Palosaaric1886372012-05-18 16:02:55 -0300385 if (priv->sleeping)
386 return 0;
387
Antti Palosaari631a2b62012-05-18 15:58:57 -0300388 ret = rtl2830_rd_regs(priv, 0x33c, buf, 2);
389 if (ret)
390 goto err;
391
392 ret = rtl2830_rd_reg(priv, 0x351, &buf[2]);
393 if (ret)
394 goto err;
395
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300396 dev_dbg(&priv->i2c->dev, "%s: TPS=%*ph\n", __func__, 3, buf);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300397
398 switch ((buf[0] >> 2) & 3) {
399 case 0:
400 c->modulation = QPSK;
401 break;
402 case 1:
403 c->modulation = QAM_16;
404 break;
405 case 2:
406 c->modulation = QAM_64;
407 break;
408 }
409
410 switch ((buf[2] >> 2) & 1) {
411 case 0:
412 c->transmission_mode = TRANSMISSION_MODE_2K;
413 break;
414 case 1:
415 c->transmission_mode = TRANSMISSION_MODE_8K;
416 }
417
418 switch ((buf[2] >> 0) & 3) {
419 case 0:
420 c->guard_interval = GUARD_INTERVAL_1_32;
421 break;
422 case 1:
423 c->guard_interval = GUARD_INTERVAL_1_16;
424 break;
425 case 2:
426 c->guard_interval = GUARD_INTERVAL_1_8;
427 break;
428 case 3:
429 c->guard_interval = GUARD_INTERVAL_1_4;
430 break;
431 }
432
433 switch ((buf[0] >> 4) & 7) {
434 case 0:
435 c->hierarchy = HIERARCHY_NONE;
436 break;
437 case 1:
438 c->hierarchy = HIERARCHY_1;
439 break;
440 case 2:
441 c->hierarchy = HIERARCHY_2;
442 break;
443 case 3:
444 c->hierarchy = HIERARCHY_4;
445 break;
446 }
447
448 switch ((buf[1] >> 3) & 7) {
449 case 0:
450 c->code_rate_HP = FEC_1_2;
451 break;
452 case 1:
453 c->code_rate_HP = FEC_2_3;
454 break;
455 case 2:
456 c->code_rate_HP = FEC_3_4;
457 break;
458 case 3:
459 c->code_rate_HP = FEC_5_6;
460 break;
461 case 4:
462 c->code_rate_HP = FEC_7_8;
463 break;
464 }
465
466 switch ((buf[1] >> 0) & 7) {
467 case 0:
468 c->code_rate_LP = FEC_1_2;
469 break;
470 case 1:
471 c->code_rate_LP = FEC_2_3;
472 break;
473 case 2:
474 c->code_rate_LP = FEC_3_4;
475 break;
476 case 3:
477 c->code_rate_LP = FEC_5_6;
478 break;
479 case 4:
480 c->code_rate_LP = FEC_7_8;
481 break;
482 }
483
484 return 0;
485err:
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300486 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Antti Palosaari631a2b62012-05-18 15:58:57 -0300487 return ret;
488}
489
Antti Palosaaric0adca72011-07-08 23:34:09 -0300490static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status)
491{
492 struct rtl2830_priv *priv = fe->demodulator_priv;
493 int ret;
494 u8 tmp;
495 *status = 0;
496
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300497 if (priv->sleeping)
498 return 0;
499
Antti Palosaaric0adca72011-07-08 23:34:09 -0300500 ret = rtl2830_rd_reg_mask(priv, 0x351, &tmp, 0x78); /* [6:3] */
501 if (ret)
502 goto err;
503
504 if (tmp == 11) {
505 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
506 FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
507 } else if (tmp == 10) {
508 *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
509 FE_HAS_VITERBI;
510 }
511
512 return ret;
513err:
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300514 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300515 return ret;
516}
517
518static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr)
519{
Antti Palosaarieba672a2012-05-15 18:32:33 -0300520 struct rtl2830_priv *priv = fe->demodulator_priv;
521 int ret, hierarchy, constellation;
522 u8 buf[2], tmp;
523 u16 tmp16;
524#define CONSTELLATION_NUM 3
525#define HIERARCHY_NUM 4
526 static const u32 snr_constant[CONSTELLATION_NUM][HIERARCHY_NUM] = {
527 { 70705899, 70705899, 70705899, 70705899 },
528 { 82433173, 82433173, 87483115, 94445660 },
529 { 92888734, 92888734, 95487525, 99770748 },
530 };
531
Antti Palosaaric1886372012-05-18 16:02:55 -0300532 if (priv->sleeping)
533 return 0;
534
Antti Palosaarieba672a2012-05-15 18:32:33 -0300535 /* reports SNR in resolution of 0.1 dB */
536
537 ret = rtl2830_rd_reg(priv, 0x33c, &tmp);
538 if (ret)
539 goto err;
540
541 constellation = (tmp >> 2) & 0x03; /* [3:2] */
542 if (constellation > CONSTELLATION_NUM - 1)
543 goto err;
544
545 hierarchy = (tmp >> 4) & 0x07; /* [6:4] */
546 if (hierarchy > HIERARCHY_NUM - 1)
547 goto err;
548
549 ret = rtl2830_rd_regs(priv, 0x40c, buf, 2);
550 if (ret)
551 goto err;
552
553 tmp16 = buf[0] << 8 | buf[1];
554
555 if (tmp16)
556 *snr = (snr_constant[constellation][hierarchy] -
557 intlog10(tmp16)) / ((1 << 24) / 100);
558 else
559 *snr = 0;
560
Antti Palosaaric0adca72011-07-08 23:34:09 -0300561 return 0;
Antti Palosaarieba672a2012-05-15 18:32:33 -0300562err:
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300563 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Antti Palosaarieba672a2012-05-15 18:32:33 -0300564 return ret;
Antti Palosaaric0adca72011-07-08 23:34:09 -0300565}
566
567static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber)
568{
Antti Palosaari525ffc12012-05-18 12:23:42 -0300569 struct rtl2830_priv *priv = fe->demodulator_priv;
570 int ret;
571 u8 buf[2];
572
Antti Palosaaric1886372012-05-18 16:02:55 -0300573 if (priv->sleeping)
574 return 0;
575
Antti Palosaari525ffc12012-05-18 12:23:42 -0300576 ret = rtl2830_rd_regs(priv, 0x34e, buf, 2);
577 if (ret)
578 goto err;
579
580 *ber = buf[0] << 8 | buf[1];
581
Antti Palosaaric0adca72011-07-08 23:34:09 -0300582 return 0;
Antti Palosaari525ffc12012-05-18 12:23:42 -0300583err:
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300584 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Antti Palosaari525ffc12012-05-18 12:23:42 -0300585 return ret;
Antti Palosaaric0adca72011-07-08 23:34:09 -0300586}
587
588static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
589{
590 *ucblocks = 0;
591 return 0;
592}
593
594static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
595{
Antti Palosaari78e75072012-05-18 15:17:51 -0300596 struct rtl2830_priv *priv = fe->demodulator_priv;
597 int ret;
598 u8 buf[2];
599 u16 if_agc_raw, if_agc;
600
Antti Palosaaric1886372012-05-18 16:02:55 -0300601 if (priv->sleeping)
602 return 0;
603
Antti Palosaari78e75072012-05-18 15:17:51 -0300604 ret = rtl2830_rd_regs(priv, 0x359, buf, 2);
605 if (ret)
606 goto err;
607
608 if_agc_raw = (buf[0] << 8 | buf[1]) & 0x3fff;
609
610 if (if_agc_raw & (1 << 9))
611 if_agc = -(~(if_agc_raw - 1) & 0x1ff);
612 else
613 if_agc = if_agc_raw;
614
615 *strength = (u8) (55 - if_agc / 182);
616 *strength |= *strength << 8;
617
Antti Palosaaric0adca72011-07-08 23:34:09 -0300618 return 0;
Antti Palosaari78e75072012-05-18 15:17:51 -0300619err:
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300620 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Antti Palosaari78e75072012-05-18 15:17:51 -0300621 return ret;
Antti Palosaaric0adca72011-07-08 23:34:09 -0300622}
623
624static struct dvb_frontend_ops rtl2830_ops;
625
626static u32 rtl2830_tuner_i2c_func(struct i2c_adapter *adapter)
627{
628 return I2C_FUNC_I2C;
629}
630
631static int rtl2830_tuner_i2c_xfer(struct i2c_adapter *i2c_adap,
632 struct i2c_msg msg[], int num)
633{
634 struct rtl2830_priv *priv = i2c_get_adapdata(i2c_adap);
635 int ret;
636
637 /* open i2c-gate */
638 ret = rtl2830_wr_reg_mask(priv, 0x101, 0x08, 0x08);
639 if (ret)
640 goto err;
641
642 ret = i2c_transfer(priv->i2c, msg, num);
643 if (ret < 0)
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300644 dev_warn(&priv->i2c->dev, "%s: tuner i2c failed=%d\n",
645 KBUILD_MODNAME, ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300646
647 return ret;
648err:
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300649 dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300650 return ret;
651}
652
653static struct i2c_algorithm rtl2830_tuner_i2c_algo = {
654 .master_xfer = rtl2830_tuner_i2c_xfer,
655 .functionality = rtl2830_tuner_i2c_func,
656};
657
658struct i2c_adapter *rtl2830_get_tuner_i2c_adapter(struct dvb_frontend *fe)
659{
660 struct rtl2830_priv *priv = fe->demodulator_priv;
661 return &priv->tuner_i2c_adapter;
662}
663EXPORT_SYMBOL(rtl2830_get_tuner_i2c_adapter);
664
665static void rtl2830_release(struct dvb_frontend *fe)
666{
667 struct rtl2830_priv *priv = fe->demodulator_priv;
668
669 i2c_del_adapter(&priv->tuner_i2c_adapter);
670 kfree(priv);
671}
672
673struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg,
674 struct i2c_adapter *i2c)
675{
676 struct rtl2830_priv *priv = NULL;
677 int ret = 0;
678 u8 tmp;
679
680 /* allocate memory for the internal state */
681 priv = kzalloc(sizeof(struct rtl2830_priv), GFP_KERNEL);
682 if (priv == NULL)
683 goto err;
684
685 /* setup the priv */
686 priv->i2c = i2c;
687 memcpy(&priv->cfg, cfg, sizeof(struct rtl2830_config));
688
689 /* check if the demod is there */
690 ret = rtl2830_rd_reg(priv, 0x000, &tmp);
691 if (ret)
692 goto err;
693
694 /* create dvb_frontend */
695 memcpy(&priv->fe.ops, &rtl2830_ops, sizeof(struct dvb_frontend_ops));
696 priv->fe.demodulator_priv = priv;
697
698 /* create tuner i2c adapter */
699 strlcpy(priv->tuner_i2c_adapter.name, "RTL2830 tuner I2C adapter",
700 sizeof(priv->tuner_i2c_adapter.name));
701 priv->tuner_i2c_adapter.algo = &rtl2830_tuner_i2c_algo;
702 priv->tuner_i2c_adapter.algo_data = NULL;
703 i2c_set_adapdata(&priv->tuner_i2c_adapter, priv);
704 if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) {
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300705 dev_err(&i2c->dev,
706 "%s: tuner i2c bus could not be initialized\n",
707 KBUILD_MODNAME);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300708 goto err;
709 }
710
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300711 priv->sleeping = true;
712
Antti Palosaaric0adca72011-07-08 23:34:09 -0300713 return &priv->fe;
714err:
Antti Palosaari86ad0f12012-09-12 20:23:47 -0300715 dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
Antti Palosaaric0adca72011-07-08 23:34:09 -0300716 kfree(priv);
717 return NULL;
718}
719EXPORT_SYMBOL(rtl2830_attach);
720
721static struct dvb_frontend_ops rtl2830_ops = {
722 .delsys = { SYS_DVBT },
723 .info = {
724 .name = "Realtek RTL2830 (DVB-T)",
725 .caps = FE_CAN_FEC_1_2 |
726 FE_CAN_FEC_2_3 |
727 FE_CAN_FEC_3_4 |
728 FE_CAN_FEC_5_6 |
729 FE_CAN_FEC_7_8 |
730 FE_CAN_FEC_AUTO |
731 FE_CAN_QPSK |
732 FE_CAN_QAM_16 |
733 FE_CAN_QAM_64 |
734 FE_CAN_QAM_AUTO |
735 FE_CAN_TRANSMISSION_MODE_AUTO |
736 FE_CAN_GUARD_INTERVAL_AUTO |
737 FE_CAN_HIERARCHY_AUTO |
738 FE_CAN_RECOVER |
739 FE_CAN_MUTE_TS
740 },
741
742 .release = rtl2830_release,
743
744 .init = rtl2830_init,
Antti Palosaaria8567cf2012-01-21 22:40:58 -0300745 .sleep = rtl2830_sleep,
Antti Palosaaric0adca72011-07-08 23:34:09 -0300746
747 .get_tune_settings = rtl2830_get_tune_settings,
748
749 .set_frontend = rtl2830_set_frontend,
Antti Palosaari631a2b62012-05-18 15:58:57 -0300750 .get_frontend = rtl2830_get_frontend,
Antti Palosaaric0adca72011-07-08 23:34:09 -0300751
752 .read_status = rtl2830_read_status,
753 .read_snr = rtl2830_read_snr,
754 .read_ber = rtl2830_read_ber,
755 .read_ucblocks = rtl2830_read_ucblocks,
756 .read_signal_strength = rtl2830_read_signal_strength,
757};
758
759MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
760MODULE_DESCRIPTION("Realtek RTL2830 DVB-T demodulator driver");
761MODULE_LICENSE("GPL");