aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/frontends/cxd2820r.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/frontends/cxd2820r.c')
-rw-r--r--drivers/media/dvb/frontends/cxd2820r.c886
1 files changed, 886 insertions, 0 deletions
diff --git a/drivers/media/dvb/frontends/cxd2820r.c b/drivers/media/dvb/frontends/cxd2820r.c
new file mode 100644
index 000000000000..b58f92c75116
--- /dev/null
+++ b/drivers/media/dvb/frontends/cxd2820r.c
@@ -0,0 +1,886 @@
1/*
2 * Sony CXD2820R demodulator driver
3 *
4 * Copyright (C) 2010 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#include "cxd2820r_priv.h"
23
24int cxd2820r_debug;
25module_param_named(debug, cxd2820r_debug, int, 0644);
26MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
27
28/* TODO: temporary hack, will be removed later when there is app support */
29unsigned int cxd2820r_dvbt2_freq[5];
30int cxd2820r_dvbt2_count;
31module_param_array_named(dvbt2_freq, cxd2820r_dvbt2_freq, int,
32 &cxd2820r_dvbt2_count, 0644);
33MODULE_PARM_DESC(dvbt2_freq, "RF frequencies forced to DVB-T2 (unit Hz)");
34
35/* write multiple registers */
36static int cxd2820r_wr_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg,
37 u8 *val, int len)
38{
39 int ret;
40 u8 buf[len+1];
41 struct i2c_msg msg[1] = {
42 {
43 .addr = i2c,
44 .flags = 0,
45 .len = sizeof(buf),
46 .buf = buf,
47 }
48 };
49
50 buf[0] = reg;
51 memcpy(&buf[1], val, len);
52
53 ret = i2c_transfer(priv->i2c, msg, 1);
54 if (ret == 1) {
55 ret = 0;
56 } else {
57 warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len);
58 ret = -EREMOTEIO;
59 }
60 return ret;
61}
62
63/* read multiple registers */
64static int cxd2820r_rd_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg,
65 u8 *val, int len)
66{
67 int ret;
68 u8 buf[len];
69 struct i2c_msg msg[2] = {
70 {
71 .addr = i2c,
72 .flags = 0,
73 .len = 1,
74 .buf = &reg,
75 }, {
76 .addr = i2c,
77 .flags = I2C_M_RD,
78 .len = sizeof(buf),
79 .buf = buf,
80 }
81 };
82
83 ret = i2c_transfer(priv->i2c, msg, 2);
84 if (ret == 2) {
85 memcpy(val, buf, len);
86 ret = 0;
87 } else {
88 warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len);
89 ret = -EREMOTEIO;
90 }
91
92 return ret;
93}
94
95/* write multiple registers */
96static int cxd2820r_wr_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
97 int len)
98{
99 int ret;
100 u8 i2c_addr;
101 u8 reg = (reginfo >> 0) & 0xff;
102 u8 bank = (reginfo >> 8) & 0xff;
103 u8 i2c = (reginfo >> 16) & 0x01;
104
105 /* select I2C */
106 if (i2c)
107 i2c_addr = priv->cfg.i2c_address | (1 << 1); /* DVB-C */
108 else
109 i2c_addr = priv->cfg.i2c_address; /* DVB-T/T2 */
110
111 /* switch bank if needed */
112 if (bank != priv->bank[i2c]) {
113 ret = cxd2820r_wr_regs_i2c(priv, i2c_addr, 0x00, &bank, 1);
114 if (ret)
115 return ret;
116 priv->bank[i2c] = bank;
117 }
118 return cxd2820r_wr_regs_i2c(priv, i2c_addr, reg, val, len);
119}
120
121/* read multiple registers */
122static int cxd2820r_rd_regs(struct cxd2820r_priv *priv, u32 reginfo, u8 *val,
123 int len)
124{
125 int ret;
126 u8 i2c_addr;
127 u8 reg = (reginfo >> 0) & 0xff;
128 u8 bank = (reginfo >> 8) & 0xff;
129 u8 i2c = (reginfo >> 16) & 0x01;
130
131 /* select I2C */
132 if (i2c)
133 i2c_addr = priv->cfg.i2c_address | (1 << 1); /* DVB-C */
134 else
135 i2c_addr = priv->cfg.i2c_address; /* DVB-T/T2 */
136
137 /* switch bank if needed */
138 if (bank != priv->bank[i2c]) {
139 ret = cxd2820r_wr_regs_i2c(priv, i2c_addr, 0x00, &bank, 1);
140 if (ret)
141 return ret;
142 priv->bank[i2c] = bank;
143 }
144 return cxd2820r_rd_regs_i2c(priv, i2c_addr, reg, val, len);
145}
146
147/* write single register */
148static int cxd2820r_wr_reg(struct cxd2820r_priv *priv, u32 reg, u8 val)
149{
150 return cxd2820r_wr_regs(priv, reg, &val, 1);
151}
152
153/* read single register */
154static int cxd2820r_rd_reg(struct cxd2820r_priv *priv, u32 reg, u8 *val)
155{
156 return cxd2820r_rd_regs(priv, reg, val, 1);
157}
158
159/* write single register with mask */
160static int cxd2820r_wr_reg_mask(struct cxd2820r_priv *priv, u32 reg, u8 val,
161 u8 mask)
162{
163 int ret;
164 u8 tmp;
165
166 /* no need for read if whole reg is written */
167 if (mask != 0xff) {
168 ret = cxd2820r_rd_reg(priv, reg, &tmp);
169 if (ret)
170 return ret;
171
172 val &= mask;
173 tmp &= ~mask;
174 val |= tmp;
175 }
176
177 return cxd2820r_wr_reg(priv, reg, val);
178}
179
180static int cxd2820r_gpio(struct dvb_frontend *fe)
181{
182 struct cxd2820r_priv *priv = fe->demodulator_priv;
183 int ret, i;
184 u8 *gpio, tmp0, tmp1;
185 dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
186
187 switch (fe->dtv_property_cache.delivery_system) {
188 case SYS_DVBT:
189 gpio = priv->cfg.gpio_dvbt;
190 break;
191 case SYS_DVBT2:
192 gpio = priv->cfg.gpio_dvbt2;
193 break;
194 case SYS_DVBC_ANNEX_AC:
195 gpio = priv->cfg.gpio_dvbc;
196 break;
197 default:
198 ret = -EINVAL;
199 goto error;
200 }
201
202 /* update GPIOs only when needed */
203 if (!memcmp(gpio, priv->gpio, sizeof(priv->gpio)))
204 return 0;
205
206 tmp0 = 0x00;
207 tmp1 = 0x00;
208 for (i = 0; i < sizeof(priv->gpio); i++) {
209 /* enable / disable */
210 if (gpio[i] & CXD2820R_GPIO_E)
211 tmp0 |= (2 << 6) >> (2 * i);
212 else
213 tmp0 |= (1 << 6) >> (2 * i);
214
215 /* input / output */
216 if (gpio[i] & CXD2820R_GPIO_I)
217 tmp1 |= (1 << (3 + i));
218 else
219 tmp1 |= (0 << (3 + i));
220
221 /* high / low */
222 if (gpio[i] & CXD2820R_GPIO_H)
223 tmp1 |= (1 << (0 + i));
224 else
225 tmp1 |= (0 << (0 + i));
226
227 dbg("%s: GPIO i=%d %02x %02x", __func__, i, tmp0, tmp1);
228 }
229
230 dbg("%s: wr gpio=%02x %02x", __func__, tmp0, tmp1);
231
232 /* write bits [7:2] */
233 ret = cxd2820r_wr_reg_mask(priv, 0x00089, tmp0, 0xfc);
234 if (ret)
235 goto error;
236
237 /* write bits [5:0] */
238 ret = cxd2820r_wr_reg_mask(priv, 0x0008e, tmp1, 0x3f);
239 if (ret)
240 goto error;
241
242 memcpy(priv->gpio, gpio, sizeof(priv->gpio));
243
244 return ret;
245error:
246 dbg("%s: failed:%d", __func__, ret);
247 return ret;
248}
249
250/* lock FE */
251static int cxd2820r_lock(struct cxd2820r_priv *priv, int active_fe)
252{
253 int ret = 0;
254 dbg("%s: active_fe=%d", __func__, active_fe);
255
256 mutex_lock(&priv->fe_lock);
257
258 /* -1=NONE, 0=DVB-T/T2, 1=DVB-C */
259 if (priv->active_fe == active_fe)
260 ;
261 else if (priv->active_fe == -1)
262 priv->active_fe = active_fe;
263 else
264 ret = -EBUSY;
265
266 mutex_unlock(&priv->fe_lock);
267
268 return ret;
269}
270
271/* unlock FE */
272static void cxd2820r_unlock(struct cxd2820r_priv *priv, int active_fe)
273{
274 dbg("%s: active_fe=%d", __func__, active_fe);
275
276 mutex_lock(&priv->fe_lock);
277
278 /* -1=NONE, 0=DVB-T/T2, 1=DVB-C */
279 if (priv->active_fe == active_fe)
280 priv->active_fe = -1;
281
282 mutex_unlock(&priv->fe_lock);
283
284 return;
285}
286
287/* 64 bit div with round closest, like DIV_ROUND_CLOSEST but 64 bit */
288static u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor)
289{
290 return div_u64(dividend + (divisor / 2), divisor);
291}
292
293/* TODO: ... */
294#include "cxd2820r_t.c"
295#include "cxd2820r_c.c"
296#include "cxd2820r_t2.c"
297
298static int cxd2820r_set_frontend(struct dvb_frontend *fe,
299 struct dvb_frontend_parameters *p)
300{
301 struct cxd2820r_priv *priv = fe->demodulator_priv;
302 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
303 int ret;
304 dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
305
306 if (fe->ops.info.type == FE_OFDM) {
307 /* DVB-T/T2 */
308 ret = cxd2820r_lock(priv, 0);
309 if (ret)
310 return ret;
311
312 switch (priv->delivery_system) {
313 case SYS_UNDEFINED:
314 if (c->delivery_system == SYS_DVBT) {
315 /* SLEEP => DVB-T */
316 ret = cxd2820r_set_frontend_t(fe, p);
317 } else {
318 /* SLEEP => DVB-T2 */
319 ret = cxd2820r_set_frontend_t2(fe, p);
320 }
321 break;
322 case SYS_DVBT:
323 if (c->delivery_system == SYS_DVBT) {
324 /* DVB-T => DVB-T */
325 ret = cxd2820r_set_frontend_t(fe, p);
326 } else if (c->delivery_system == SYS_DVBT2) {
327 /* DVB-T => DVB-T2 */
328 ret = cxd2820r_sleep_t(fe);
329 ret = cxd2820r_set_frontend_t2(fe, p);
330 }
331 break;
332 case SYS_DVBT2:
333 if (c->delivery_system == SYS_DVBT2) {
334 /* DVB-T2 => DVB-T2 */
335 ret = cxd2820r_set_frontend_t2(fe, p);
336 } else if (c->delivery_system == SYS_DVBT) {
337 /* DVB-T2 => DVB-T */
338 ret = cxd2820r_sleep_t2(fe);
339 ret = cxd2820r_set_frontend_t(fe, p);
340 }
341 break;
342 default:
343 dbg("%s: error state=%d", __func__,
344 priv->delivery_system);
345 ret = -EINVAL;
346 }
347 } else {
348 /* DVB-C */
349 ret = cxd2820r_lock(priv, 1);
350 if (ret)
351 return ret;
352
353 ret = cxd2820r_set_frontend_c(fe, p);
354 }
355
356 return ret;
357}
358
359static int cxd2820r_read_status(struct dvb_frontend *fe, fe_status_t *status)
360{
361 struct cxd2820r_priv *priv = fe->demodulator_priv;
362 int ret;
363 dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
364
365 if (fe->ops.info.type == FE_OFDM) {
366 /* DVB-T/T2 */
367 ret = cxd2820r_lock(priv, 0);
368 if (ret)
369 return ret;
370
371 switch (fe->dtv_property_cache.delivery_system) {
372 case SYS_DVBT:
373 ret = cxd2820r_read_status_t(fe, status);
374 break;
375 case SYS_DVBT2:
376 ret = cxd2820r_read_status_t2(fe, status);
377 break;
378 default:
379 ret = -EINVAL;
380 }
381 } else {
382 /* DVB-C */
383 ret = cxd2820r_lock(priv, 1);
384 if (ret)
385 return ret;
386
387 ret = cxd2820r_read_status_c(fe, status);
388 }
389
390 return ret;
391}
392
393static int cxd2820r_get_frontend(struct dvb_frontend *fe,
394 struct dvb_frontend_parameters *p)
395{
396 struct cxd2820r_priv *priv = fe->demodulator_priv;
397 int ret;
398 dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
399
400 if (fe->ops.info.type == FE_OFDM) {
401 /* DVB-T/T2 */
402 ret = cxd2820r_lock(priv, 0);
403 if (ret)
404 return ret;
405
406 switch (fe->dtv_property_cache.delivery_system) {
407 case SYS_DVBT:
408 ret = cxd2820r_get_frontend_t(fe, p);
409 break;
410 case SYS_DVBT2:
411 ret = cxd2820r_get_frontend_t2(fe, p);
412 break;
413 default:
414 ret = -EINVAL;
415 }
416 } else {
417 /* DVB-C */
418 ret = cxd2820r_lock(priv, 1);
419 if (ret)
420 return ret;
421
422 ret = cxd2820r_get_frontend_c(fe, p);
423 }
424
425 return ret;
426}
427
428static int cxd2820r_read_ber(struct dvb_frontend *fe, u32 *ber)
429{
430 struct cxd2820r_priv *priv = fe->demodulator_priv;
431 int ret;
432 dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
433
434 if (fe->ops.info.type == FE_OFDM) {
435 /* DVB-T/T2 */
436 ret = cxd2820r_lock(priv, 0);
437 if (ret)
438 return ret;
439
440 switch (fe->dtv_property_cache.delivery_system) {
441 case SYS_DVBT:
442 ret = cxd2820r_read_ber_t(fe, ber);
443 break;
444 case SYS_DVBT2:
445 ret = cxd2820r_read_ber_t2(fe, ber);
446 break;
447 default:
448 ret = -EINVAL;
449 }
450 } else {
451 /* DVB-C */
452 ret = cxd2820r_lock(priv, 1);
453 if (ret)
454 return ret;
455
456 ret = cxd2820r_read_ber_c(fe, ber);
457 }
458
459 return ret;
460}
461
462static int cxd2820r_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
463{
464 struct cxd2820r_priv *priv = fe->demodulator_priv;
465 int ret;
466 dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
467
468 if (fe->ops.info.type == FE_OFDM) {
469 /* DVB-T/T2 */
470 ret = cxd2820r_lock(priv, 0);
471 if (ret)
472 return ret;
473
474 switch (fe->dtv_property_cache.delivery_system) {
475 case SYS_DVBT:
476 ret = cxd2820r_read_signal_strength_t(fe, strength);
477 break;
478 case SYS_DVBT2:
479 ret = cxd2820r_read_signal_strength_t2(fe, strength);
480 break;
481 default:
482 ret = -EINVAL;
483 }
484 } else {
485 /* DVB-C */
486 ret = cxd2820r_lock(priv, 1);
487 if (ret)
488 return ret;
489
490 ret = cxd2820r_read_signal_strength_c(fe, strength);
491 }
492
493 return ret;
494}
495
496static int cxd2820r_read_snr(struct dvb_frontend *fe, u16 *snr)
497{
498 struct cxd2820r_priv *priv = fe->demodulator_priv;
499 int ret;
500 dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
501
502 if (fe->ops.info.type == FE_OFDM) {
503 /* DVB-T/T2 */
504 ret = cxd2820r_lock(priv, 0);
505 if (ret)
506 return ret;
507
508 switch (fe->dtv_property_cache.delivery_system) {
509 case SYS_DVBT:
510 ret = cxd2820r_read_snr_t(fe, snr);
511 break;
512 case SYS_DVBT2:
513 ret = cxd2820r_read_snr_t2(fe, snr);
514 break;
515 default:
516 ret = -EINVAL;
517 }
518 } else {
519 /* DVB-C */
520 ret = cxd2820r_lock(priv, 1);
521 if (ret)
522 return ret;
523
524 ret = cxd2820r_read_snr_c(fe, snr);
525 }
526
527 return ret;
528}
529
530static int cxd2820r_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
531{
532 struct cxd2820r_priv *priv = fe->demodulator_priv;
533 int ret;
534 dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
535
536 if (fe->ops.info.type == FE_OFDM) {
537 /* DVB-T/T2 */
538 ret = cxd2820r_lock(priv, 0);
539 if (ret)
540 return ret;
541
542 switch (fe->dtv_property_cache.delivery_system) {
543 case SYS_DVBT:
544 ret = cxd2820r_read_ucblocks_t(fe, ucblocks);
545 break;
546 case SYS_DVBT2:
547 ret = cxd2820r_read_ucblocks_t2(fe, ucblocks);
548 break;
549 default:
550 ret = -EINVAL;
551 }
552 } else {
553 /* DVB-C */
554 ret = cxd2820r_lock(priv, 1);
555 if (ret)
556 return ret;
557
558 ret = cxd2820r_read_ucblocks_c(fe, ucblocks);
559 }
560
561 return ret;
562}
563
564static int cxd2820r_init(struct dvb_frontend *fe)
565{
566 struct cxd2820r_priv *priv = fe->demodulator_priv;
567 int ret;
568 dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
569
570 priv->delivery_system = SYS_UNDEFINED;
571 /* delivery system is unknown at that (init) phase */
572
573 if (fe->ops.info.type == FE_OFDM) {
574 /* DVB-T/T2 */
575 ret = cxd2820r_lock(priv, 0);
576 if (ret)
577 return ret;
578
579 ret = cxd2820r_init_t(fe);
580 } else {
581 /* DVB-C */
582 ret = cxd2820r_lock(priv, 1);
583 if (ret)
584 return ret;
585
586 ret = cxd2820r_init_c(fe);
587 }
588
589 return ret;
590}
591
592static int cxd2820r_sleep(struct dvb_frontend *fe)
593{
594 struct cxd2820r_priv *priv = fe->demodulator_priv;
595 int ret;
596 dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
597
598 if (fe->ops.info.type == FE_OFDM) {
599 /* DVB-T/T2 */
600 ret = cxd2820r_lock(priv, 0);
601 if (ret)
602 return ret;
603
604 switch (fe->dtv_property_cache.delivery_system) {
605 case SYS_DVBT:
606 ret = cxd2820r_sleep_t(fe);
607 break;
608 case SYS_DVBT2:
609 ret = cxd2820r_sleep_t2(fe);
610 break;
611 default:
612 ret = -EINVAL;
613 }
614
615 cxd2820r_unlock(priv, 0);
616 } else {
617 /* DVB-C */
618 ret = cxd2820r_lock(priv, 1);
619 if (ret)
620 return ret;
621
622 ret = cxd2820r_sleep_c(fe);
623
624 cxd2820r_unlock(priv, 1);
625 }
626
627 return ret;
628}
629
630static int cxd2820r_get_tune_settings(struct dvb_frontend *fe,
631 struct dvb_frontend_tune_settings *s)
632{
633 struct cxd2820r_priv *priv = fe->demodulator_priv;
634 int ret, i;
635 unsigned int rf1, rf2;
636 dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
637
638 if (fe->ops.info.type == FE_OFDM) {
639 /* DVB-T/T2 */
640 ret = cxd2820r_lock(priv, 0);
641 if (ret)
642 return ret;
643
644 /* TODO: hack! This will be removed later when there is better
645 * app support for DVB-T2... */
646
647 /* Hz => MHz */
648 rf1 = DIV_ROUND_CLOSEST(fe->dtv_property_cache.frequency,
649 1000000);
650 for (i = 0; i < cxd2820r_dvbt2_count; i++) {
651 if (cxd2820r_dvbt2_freq[i] > 100000000) {
652 /* Hz => MHz */
653 rf2 = DIV_ROUND_CLOSEST(cxd2820r_dvbt2_freq[i],
654 1000000);
655 } else if (cxd2820r_dvbt2_freq[i] > 100000) {
656 /* kHz => MHz */
657 rf2 = DIV_ROUND_CLOSEST(cxd2820r_dvbt2_freq[i],
658 1000);
659 } else {
660 rf2 = cxd2820r_dvbt2_freq[i];
661 }
662
663 dbg("%s: rf1=%d rf2=%d", __func__, rf1, rf2);
664
665 if (rf1 == rf2) {
666 dbg("%s: forcing DVB-T2, frequency=%d",
667 __func__, fe->dtv_property_cache.frequency);
668 fe->dtv_property_cache.delivery_system =
669 SYS_DVBT2;
670 }
671 }
672
673 switch (fe->dtv_property_cache.delivery_system) {
674 case SYS_DVBT:
675 ret = cxd2820r_get_tune_settings_t(fe, s);
676 break;
677 case SYS_DVBT2:
678 ret = cxd2820r_get_tune_settings_t2(fe, s);
679 break;
680 default:
681 ret = -EINVAL;
682 }
683 } else {
684 /* DVB-C */
685 ret = cxd2820r_lock(priv, 1);
686 if (ret)
687 return ret;
688
689 ret = cxd2820r_get_tune_settings_c(fe, s);
690 }
691
692 return ret;
693}
694
695static void cxd2820r_release(struct dvb_frontend *fe)
696{
697 struct cxd2820r_priv *priv = fe->demodulator_priv;
698 dbg("%s", __func__);
699
700 if (fe->ops.info.type == FE_OFDM) {
701 i2c_del_adapter(&priv->tuner_i2c_adapter);
702 kfree(priv);
703 }
704
705 return;
706}
707
708static u32 cxd2820r_tuner_i2c_func(struct i2c_adapter *adapter)
709{
710 return I2C_FUNC_I2C;
711}
712
713static int cxd2820r_tuner_i2c_xfer(struct i2c_adapter *i2c_adap,
714 struct i2c_msg msg[], int num)
715{
716 struct cxd2820r_priv *priv = i2c_get_adapdata(i2c_adap);
717 u8 obuf[msg[0].len + 2];
718 struct i2c_msg msg2[2] = {
719 {
720 .addr = priv->cfg.i2c_address,
721 .flags = 0,
722 .len = sizeof(obuf),
723 .buf = obuf,
724 }, {
725 .addr = priv->cfg.i2c_address,
726 .flags = I2C_M_RD,
727 .len = msg[1].len,
728 .buf = msg[1].buf,
729 }
730 };
731
732 obuf[0] = 0x09;
733 obuf[1] = (msg[0].addr << 1);
734 if (num == 2) { /* I2C read */
735 obuf[1] = (msg[0].addr << 1) | I2C_M_RD; /* I2C RD flag */
736 msg2[0].len = sizeof(obuf) - 1; /* maybe HW bug ? */
737 }
738 memcpy(&obuf[2], msg[0].buf, msg[0].len);
739
740 return i2c_transfer(priv->i2c, msg2, num);
741}
742
743static struct i2c_algorithm cxd2820r_tuner_i2c_algo = {
744 .master_xfer = cxd2820r_tuner_i2c_xfer,
745 .functionality = cxd2820r_tuner_i2c_func,
746};
747
748struct i2c_adapter *cxd2820r_get_tuner_i2c_adapter(struct dvb_frontend *fe)
749{
750 struct cxd2820r_priv *priv = fe->demodulator_priv;
751 return &priv->tuner_i2c_adapter;
752}
753EXPORT_SYMBOL(cxd2820r_get_tuner_i2c_adapter);
754
755static struct dvb_frontend_ops cxd2820r_ops[2];
756
757struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
758 struct i2c_adapter *i2c, struct dvb_frontend *fe)
759{
760 int ret;
761 struct cxd2820r_priv *priv = NULL;
762 u8 tmp;
763
764 if (fe == NULL) {
765 /* FE0 */
766 /* allocate memory for the internal priv */
767 priv = kzalloc(sizeof(struct cxd2820r_priv), GFP_KERNEL);
768 if (priv == NULL)
769 goto error;
770
771 /* setup the priv */
772 priv->i2c = i2c;
773 memcpy(&priv->cfg, cfg, sizeof(struct cxd2820r_config));
774 mutex_init(&priv->fe_lock);
775
776 priv->active_fe = -1; /* NONE */
777
778 /* check if the demod is there */
779 priv->bank[0] = priv->bank[1] = 0xff;
780 ret = cxd2820r_rd_reg(priv, 0x000fd, &tmp);
781 dbg("%s: chip id=%02x", __func__, tmp);
782 if (ret || tmp != 0xe1)
783 goto error;
784
785 /* create frontends */
786 memcpy(&priv->fe[0].ops, &cxd2820r_ops[0],
787 sizeof(struct dvb_frontend_ops));
788 memcpy(&priv->fe[1].ops, &cxd2820r_ops[1],
789 sizeof(struct dvb_frontend_ops));
790
791 priv->fe[0].demodulator_priv = priv;
792 priv->fe[1].demodulator_priv = priv;
793
794 /* create tuner i2c adapter */
795 strlcpy(priv->tuner_i2c_adapter.name,
796 "CXD2820R tuner I2C adapter",
797 sizeof(priv->tuner_i2c_adapter.name));
798 priv->tuner_i2c_adapter.algo = &cxd2820r_tuner_i2c_algo;
799 priv->tuner_i2c_adapter.algo_data = NULL;
800 i2c_set_adapdata(&priv->tuner_i2c_adapter, priv);
801 if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) {
802 err("tuner I2C bus could not be initialized");
803 goto error;
804 }
805
806 return &priv->fe[0];
807
808 } else {
809 /* FE1: FE0 given as pointer, just return FE1 we have
810 * already created */
811 priv = fe->demodulator_priv;
812 return &priv->fe[1];
813 }
814
815error:
816 kfree(priv);
817 return NULL;
818}
819EXPORT_SYMBOL(cxd2820r_attach);
820
821static struct dvb_frontend_ops cxd2820r_ops[2] = {
822 {
823 /* DVB-T/T2 */
824 .info = {
825 .name = "Sony CXD2820R (DVB-T/T2)",
826 .type = FE_OFDM,
827 .caps =
828 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
829 FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 |
830 FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
831 FE_CAN_QPSK | FE_CAN_QAM_16 |
832 FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
833 FE_CAN_TRANSMISSION_MODE_AUTO |
834 FE_CAN_GUARD_INTERVAL_AUTO |
835 FE_CAN_HIERARCHY_AUTO |
836 FE_CAN_MUTE_TS |
837 FE_CAN_2G_MODULATION
838 },
839
840 .release = cxd2820r_release,
841 .init = cxd2820r_init,
842 .sleep = cxd2820r_sleep,
843
844 .get_tune_settings = cxd2820r_get_tune_settings,
845
846 .set_frontend = cxd2820r_set_frontend,
847 .get_frontend = cxd2820r_get_frontend,
848
849 .read_status = cxd2820r_read_status,
850 .read_snr = cxd2820r_read_snr,
851 .read_ber = cxd2820r_read_ber,
852 .read_ucblocks = cxd2820r_read_ucblocks,
853 .read_signal_strength = cxd2820r_read_signal_strength,
854 },
855 {
856 /* DVB-C */
857 .info = {
858 .name = "Sony CXD2820R (DVB-C)",
859 .type = FE_QAM,
860 .caps =
861 FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
862 FE_CAN_QAM_128 | FE_CAN_QAM_256 |
863 FE_CAN_FEC_AUTO
864 },
865
866 .release = cxd2820r_release,
867 .init = cxd2820r_init,
868 .sleep = cxd2820r_sleep,
869
870 .get_tune_settings = cxd2820r_get_tune_settings,
871
872 .set_frontend = cxd2820r_set_frontend,
873 .get_frontend = cxd2820r_get_frontend,
874
875 .read_status = cxd2820r_read_status,
876 .read_snr = cxd2820r_read_snr,
877 .read_ber = cxd2820r_read_ber,
878 .read_ucblocks = cxd2820r_read_ucblocks,
879 .read_signal_strength = cxd2820r_read_signal_strength,
880 },
881};
882
883
884MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
885MODULE_DESCRIPTION("Sony CXD2820R demodulator driver");
886MODULE_LICENSE("GPL");