aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/frontends/it913x-fe.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/frontends/it913x-fe.c')
-rw-r--r--drivers/media/dvb/frontends/it913x-fe.c747
1 files changed, 747 insertions, 0 deletions
diff --git a/drivers/media/dvb/frontends/it913x-fe.c b/drivers/media/dvb/frontends/it913x-fe.c
new file mode 100644
index 00000000000..c92b3ec3f8a
--- /dev/null
+++ b/drivers/media/dvb/frontends/it913x-fe.c
@@ -0,0 +1,747 @@
1/*
2 * Driver for it913x-fe Frontend
3 *
4 * with support for on chip it9137 integral tuner
5 *
6 * Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com)
7 * IT9137 Copyright (C) ITE Tech Inc.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 *
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.=
23 */
24
25#include <linux/module.h>
26#include <linux/init.h>
27#include <linux/slab.h>
28#include <linux/types.h>
29
30#include "dvb_frontend.h"
31#include "it913x-fe.h"
32#include "it913x-fe-priv.h"
33
34static int it913x_debug;
35
36module_param_named(debug, it913x_debug, int, 0644);
37MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
38
39#define dprintk(level, args...) do { \
40 if (level & it913x_debug) \
41 printk(KERN_DEBUG "it913x-fe: " args); \
42} while (0)
43
44#define deb_info(args...) dprintk(0x01, args)
45#define debug_data_snipet(level, name, p) \
46 dprintk(level, name" (%02x%02x%02x%02x%02x%02x%02x%02x)", \
47 *p, *(p+1), *(p+2), *(p+3), *(p+4), \
48 *(p+5), *(p+6), *(p+7));
49
50struct it913x_fe_state {
51 struct dvb_frontend frontend;
52 struct i2c_adapter *i2c_adap;
53 u8 i2c_addr;
54 u32 frequency;
55 u8 adf;
56 u32 crystalFrequency;
57 u32 adcFrequency;
58 u8 tuner_type;
59 struct adctable *table;
60 fe_status_t it913x_status;
61};
62
63static int it913x_read_reg(struct it913x_fe_state *state,
64 u32 reg, u8 *data, u8 count)
65{
66 int ret;
67 u8 pro = PRO_DMOD; /* All reads from demodulator */
68 u8 b[4];
69 struct i2c_msg msg[2] = {
70 { .addr = state->i2c_addr + (pro << 1), .flags = 0,
71 .buf = b, .len = sizeof(b) },
72 { .addr = state->i2c_addr + (pro << 1), .flags = I2C_M_RD,
73 .buf = data, .len = count }
74 };
75 b[0] = (u8) reg >> 24;
76 b[1] = (u8)(reg >> 16) & 0xff;
77 b[2] = (u8)(reg >> 8) & 0xff;
78 b[3] = (u8) reg & 0xff;
79
80 ret = i2c_transfer(state->i2c_adap, msg, 2);
81
82 return ret;
83}
84
85static int it913x_read_reg_u8(struct it913x_fe_state *state, u32 reg)
86{
87 int ret;
88 u8 b[1];
89 ret = it913x_read_reg(state, reg, &b[0], sizeof(b));
90 return (ret < 0) ? -ENODEV : b[0];
91}
92
93static int it913x_write(struct it913x_fe_state *state,
94 u8 pro, u32 reg, u8 buf[], u8 count)
95{
96 u8 b[256];
97 struct i2c_msg msg[1] = {
98 { .addr = state->i2c_addr + (pro << 1), .flags = 0,
99 .buf = b, .len = count + 4 }
100 };
101 int ret;
102
103 b[0] = (u8) reg >> 24;
104 b[1] = (u8)(reg >> 16) & 0xff;
105 b[2] = (u8)(reg >> 8) & 0xff;
106 b[3] = (u8) reg & 0xff;
107 memcpy(&b[4], buf, count);
108
109 ret = i2c_transfer(state->i2c_adap, msg, 1);
110
111 if (ret < 0)
112 return -EIO;
113
114 return 0;
115}
116
117static int it913x_write_reg(struct it913x_fe_state *state,
118 u8 pro, u32 reg, u32 data)
119{
120 int ret;
121 u8 b[4];
122 u8 s;
123
124 b[0] = data >> 24;
125 b[1] = (data >> 16) & 0xff;
126 b[2] = (data >> 8) & 0xff;
127 b[3] = data & 0xff;
128 /* expand write as needed */
129 if (data < 0x100)
130 s = 3;
131 else if (data < 0x1000)
132 s = 2;
133 else if (data < 0x100000)
134 s = 1;
135 else
136 s = 0;
137
138 ret = it913x_write(state, pro, reg, &b[s], sizeof(b) - s);
139
140 return ret;
141}
142
143static int it913x_fe_script_loader(struct it913x_fe_state *state,
144 struct it913xset *loadscript)
145{
146 int ret, i;
147 if (loadscript == NULL)
148 return -EINVAL;
149
150 for (i = 0; i < 1000; ++i) {
151 if (loadscript[i].pro == 0xff)
152 break;
153 ret = it913x_write(state, loadscript[i].pro,
154 loadscript[i].address,
155 loadscript[i].reg, loadscript[i].count);
156 if (ret < 0)
157 return -ENODEV;
158 }
159 return 0;
160}
161
162static int it9137_set_tuner(struct it913x_fe_state *state,
163 enum fe_bandwidth bandwidth, u32 frequency_m)
164{
165 struct it913xset *set_tuner = set_it9137_template;
166 int ret;
167 u32 frequency = frequency_m / 1000;
168 u32 freq;
169 u16 n_div;
170 u8 n;
171 u8 l_band;
172 u8 lna_band;
173 u8 bw;
174
175 deb_info("Tuner Frequency %d Bandwidth %d", frequency, bandwidth);
176
177 if (frequency >= 51000 && frequency <= 440000) {
178 l_band = 0;
179 lna_band = 0;
180 } else if (frequency > 440000 && frequency <= 484000) {
181 l_band = 1;
182 lna_band = 1;
183 } else if (frequency > 484000 && frequency <= 533000) {
184 l_band = 1;
185 lna_band = 2;
186 } else if (frequency > 533000 && frequency <= 587000) {
187 l_band = 1;
188 lna_band = 3;
189 } else if (frequency > 587000 && frequency <= 645000) {
190 l_band = 1;
191 lna_band = 4;
192 } else if (frequency > 645000 && frequency <= 710000) {
193 l_band = 1;
194 lna_band = 5;
195 } else if (frequency > 710000 && frequency <= 782000) {
196 l_band = 1;
197 lna_band = 6;
198 } else if (frequency > 782000 && frequency <= 860000) {
199 l_band = 1;
200 lna_band = 7;
201 } else if (frequency > 1450000 && frequency <= 1492000) {
202 l_band = 1;
203 lna_band = 0;
204 } else if (frequency > 1660000 && frequency <= 1685000) {
205 l_band = 1;
206 lna_band = 1;
207 } else
208 return -EINVAL;
209 set_tuner[0].reg[0] = lna_band;
210
211 if (bandwidth == BANDWIDTH_5_MHZ)
212 bw = 0;
213 else if (bandwidth == BANDWIDTH_6_MHZ)
214 bw = 2;
215 else if (bandwidth == BANDWIDTH_7_MHZ)
216 bw = 4;
217 else if (bandwidth == BANDWIDTH_8_MHZ)
218 bw = 6;
219 else
220 bw = 6;
221 set_tuner[1].reg[0] = bw;
222 set_tuner[2].reg[0] = 0xa0 | (l_band << 3);
223
224 if (frequency > 49000 && frequency <= 74000) {
225 n_div = 48;
226 n = 0;
227 } else if (frequency > 74000 && frequency <= 111000) {
228 n_div = 32;
229 n = 1;
230 } else if (frequency > 111000 && frequency <= 148000) {
231 n_div = 24;
232 n = 2;
233 } else if (frequency > 148000 && frequency <= 222000) {
234 n_div = 16;
235 n = 3;
236 } else if (frequency > 222000 && frequency <= 296000) {
237 n_div = 12;
238 n = 4;
239 } else if (frequency > 296000 && frequency <= 445000) {
240 n_div = 8;
241 n = 5;
242 } else if (frequency > 445000 && frequency <= 560000) {
243 n_div = 6;
244 n = 6;
245 } else if (frequency > 560000 && frequency <= 860000) {
246 n_div = 4;
247 n = 7;
248 } else if (frequency > 1450000 && frequency <= 1680000) {
249 n_div = 2;
250 n = 0;
251 } else
252 return -EINVAL;
253
254
255 /* Frequency + 3000 TODO not sure this is bandwidth setting */
256 /* Xtal frequency 21327? but it works */
257 freq = (u32) (n_div * 32 * (frequency + 3000) / 21327);
258 freq += (u32) n << 13;
259 set_tuner[2].reg[1] = freq & 0xff;
260 set_tuner[2].reg[2] = (freq >> 8) & 0xff;
261
262 /* frequency */
263 freq = (u32) (n_div * 32 * frequency / 21327);
264 freq += (u32) n << 13;
265 set_tuner[2].reg[3] = freq & 0xff;
266 set_tuner[2].reg[4] = (freq >> 8) & 0xff;
267
268 deb_info("Frequency = %08x, Bandwidth = %02x, ", freq, bw);
269
270 ret = it913x_fe_script_loader(state, set_tuner);
271
272 return (ret < 0) ? -ENODEV : 0;
273
274}
275
276static int it913x_fe_select_bw(struct it913x_fe_state *state,
277 enum fe_bandwidth bandwidth, u32 adcFrequency)
278{
279 int ret, i;
280 u8 buffer[256];
281 u32 coeff[8];
282 u16 bfsfcw_fftinx_ratio;
283 u16 fftinx_bfsfcw_ratio;
284 u8 count;
285 u8 bw;
286 u8 adcmultiplier;
287
288 deb_info("Bandwidth %d Adc %d", bandwidth, adcFrequency);
289
290 if (bandwidth == BANDWIDTH_5_MHZ)
291 bw = 3;
292 else if (bandwidth == BANDWIDTH_6_MHZ)
293 bw = 0;
294 else if (bandwidth == BANDWIDTH_7_MHZ)
295 bw = 1;
296 else if (bandwidth == BANDWIDTH_8_MHZ)
297 bw = 2;
298 else
299 bw = 2;
300
301 ret = it913x_write_reg(state, PRO_DMOD, REG_BW, bw);
302
303 if (state->table == NULL)
304 return -EINVAL;
305
306 /* In write order */
307 coeff[0] = state->table[bw].coeff_1_2048;
308 coeff[1] = state->table[bw].coeff_2_2k;
309 coeff[2] = state->table[bw].coeff_1_8191;
310 coeff[3] = state->table[bw].coeff_1_8192;
311 coeff[4] = state->table[bw].coeff_1_8193;
312 coeff[5] = state->table[bw].coeff_2_8k;
313 coeff[6] = state->table[bw].coeff_1_4096;
314 coeff[7] = state->table[bw].coeff_2_4k;
315 bfsfcw_fftinx_ratio = state->table[bw].bfsfcw_fftinx_ratio;
316 fftinx_bfsfcw_ratio = state->table[bw].fftinx_bfsfcw_ratio;
317
318 /* ADC multiplier */
319 ret = it913x_read_reg_u8(state, ADC_X_2);
320 if (ret < 0)
321 return -EINVAL;
322
323 adcmultiplier = ret;
324
325 count = 0;
326
327 /* Build Buffer for COEFF Registers */
328 for (i = 0; i < 8; i++) {
329 if (adcmultiplier == 1)
330 coeff[i] /= 2;
331 buffer[count++] = (coeff[i] >> 24) & 0x3;
332 buffer[count++] = (coeff[i] >> 16) & 0xff;
333 buffer[count++] = (coeff[i] >> 8) & 0xff;
334 buffer[count++] = coeff[i] & 0xff;
335 }
336
337 /* bfsfcw_fftinx_ratio register 0x21-0x22 */
338 buffer[count++] = bfsfcw_fftinx_ratio & 0xff;
339 buffer[count++] = (bfsfcw_fftinx_ratio >> 8) & 0xff;
340 /* fftinx_bfsfcw_ratio register 0x23-0x24 */
341 buffer[count++] = fftinx_bfsfcw_ratio & 0xff;
342 buffer[count++] = (fftinx_bfsfcw_ratio >> 8) & 0xff;
343 /* start at COEFF_1_2048 and write through to fftinx_bfsfcw_ratio*/
344 ret = it913x_write(state, PRO_DMOD, COEFF_1_2048, buffer, count);
345
346 for (i = 0; i < 42; i += 8)
347 debug_data_snipet(0x1, "Buffer", &buffer[i]);
348
349 return ret;
350}
351
352
353
354static int it913x_fe_read_status(struct dvb_frontend *fe, fe_status_t *status)
355{
356 struct it913x_fe_state *state = fe->demodulator_priv;
357 int ret, i;
358 fe_status_t old_status = state->it913x_status;
359 *status = 0;
360
361 if (state->it913x_status == 0) {
362 ret = it913x_read_reg_u8(state, EMPTY_CHANNEL_STATUS);
363 if (ret == 0x1) {
364 *status |= FE_HAS_SIGNAL;
365 for (i = 0; i < 40; i++) {
366 ret = it913x_read_reg_u8(state, MP2IF_SYNC_LK);
367 if (ret == 0x1)
368 break;
369 msleep(25);
370 }
371 if (ret == 0x1)
372 *status |= FE_HAS_CARRIER
373 | FE_HAS_VITERBI
374 | FE_HAS_SYNC;
375 state->it913x_status = *status;
376 }
377 }
378
379 if (state->it913x_status & FE_HAS_SYNC) {
380 ret = it913x_read_reg_u8(state, TPSD_LOCK);
381 if (ret == 0x1)
382 *status |= FE_HAS_LOCK
383 | state->it913x_status;
384 else
385 state->it913x_status = 0;
386 if (old_status != state->it913x_status)
387 ret = it913x_write_reg(state, PRO_LINK, GPIOH3_O, ret);
388 }
389
390 return 0;
391}
392
393static int it913x_fe_read_signal_strength(struct dvb_frontend *fe,
394 u16 *strength)
395{
396 struct it913x_fe_state *state = fe->demodulator_priv;
397 int ret = it913x_read_reg_u8(state, SIGNAL_LEVEL);
398 /*SIGNAL_LEVEL always returns 100%! so using FE_HAS_SIGNAL as switch*/
399 if (state->it913x_status & FE_HAS_SIGNAL)
400 ret = (ret * 0xff) / 0x64;
401 else
402 ret = 0x0;
403 ret |= ret << 0x8;
404 *strength = ret;
405 return 0;
406}
407
408static int it913x_fe_read_snr(struct dvb_frontend *fe, u16* snr)
409{
410 struct it913x_fe_state *state = fe->demodulator_priv;
411 int ret = it913x_read_reg_u8(state, SIGNAL_QUALITY);
412 ret = (ret * 0xff) / 0x64;
413 ret |= (ret << 0x8);
414 *snr = ~ret;
415 return 0;
416}
417
418static int it913x_fe_read_ber(struct dvb_frontend *fe, u32 *ber)
419{
420 *ber = 0;
421 return 0;
422}
423
424static int it913x_fe_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
425{
426 *ucblocks = 0;
427 return 0;
428}
429
430static int it913x_fe_get_frontend(struct dvb_frontend *fe,
431 struct dvb_frontend_parameters *p)
432{
433 struct it913x_fe_state *state = fe->demodulator_priv;
434 int ret;
435 u8 reg[8];
436
437 ret = it913x_read_reg(state, REG_TPSD_TX_MODE, reg, sizeof(reg));
438
439 if (reg[3] < 3)
440 p->u.ofdm.constellation = fe_con[reg[3]];
441
442 if (reg[0] < 3)
443 p->u.ofdm.transmission_mode = fe_mode[reg[0]];
444
445 if (reg[1] < 4)
446 p->u.ofdm.guard_interval = fe_gi[reg[1]];
447
448 if (reg[2] < 4)
449 p->u.ofdm.hierarchy_information = fe_hi[reg[2]];
450
451 p->u.ofdm.code_rate_HP = (reg[6] < 6) ? fe_code[reg[6]] : FEC_NONE;
452 p->u.ofdm.code_rate_LP = (reg[7] < 6) ? fe_code[reg[7]] : FEC_NONE;
453
454 return 0;
455}
456
457static int it913x_fe_set_frontend(struct dvb_frontend *fe,
458 struct dvb_frontend_parameters *p)
459{
460 struct it913x_fe_state *state = fe->demodulator_priv;
461 int ret, i;
462 u8 empty_ch, last_ch;
463
464 state->it913x_status = 0;
465
466 /* Set bw*/
467 ret = it913x_fe_select_bw(state, p->u.ofdm.bandwidth,
468 state->adcFrequency);
469
470 /* Training Mode Off */
471 ret = it913x_write_reg(state, PRO_LINK, TRAINING_MODE, 0x0);
472
473 /* Clear Empty Channel */
474 ret = it913x_write_reg(state, PRO_DMOD, EMPTY_CHANNEL_STATUS, 0x0);
475
476 /* Clear bits */
477 ret = it913x_write_reg(state, PRO_DMOD, MP2IF_SYNC_LK, 0x0);
478 /* LED on */
479 ret = it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x1);
480 /* Select Band*/
481 if ((p->frequency >= 51000000) && (p->frequency <= 230000000))
482 i = 0;
483 else if ((p->frequency >= 350000000) && (p->frequency <= 900000000))
484 i = 1;
485 else if ((p->frequency >= 1450000000) && (p->frequency <= 1680000000))
486 i = 2;
487 else
488 return -EOPNOTSUPP;
489
490 ret = it913x_write_reg(state, PRO_DMOD, FREE_BAND, i);
491
492 deb_info("Frontend Set Tuner Type %02x", state->tuner_type);
493 switch (state->tuner_type) {
494 case IT9137: /* Tuner type 0x38 */
495 ret = it9137_set_tuner(state,
496 p->u.ofdm.bandwidth, p->frequency);
497 break;
498 default:
499 if (fe->ops.tuner_ops.set_params) {
500 fe->ops.tuner_ops.set_params(fe, p);
501 if (fe->ops.i2c_gate_ctrl)
502 fe->ops.i2c_gate_ctrl(fe, 0);
503 }
504 break;
505 }
506 /* LED off */
507 ret = it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x0);
508 /* Trigger ofsm */
509 ret = it913x_write_reg(state, PRO_DMOD, TRIGGER_OFSM, 0x0);
510 last_ch = 2;
511 for (i = 0; i < 40; ++i) {
512 empty_ch = it913x_read_reg_u8(state, EMPTY_CHANNEL_STATUS);
513 if (last_ch == 1 && empty_ch == 1)
514 break;
515 if (last_ch == 2 && empty_ch == 2)
516 return 0;
517 last_ch = empty_ch;
518 msleep(25);
519 }
520 for (i = 0; i < 40; ++i) {
521 if (it913x_read_reg_u8(state, D_TPSD_LOCK) == 1)
522 break;
523 msleep(25);
524 }
525
526 state->frequency = p->frequency;
527 return 0;
528}
529
530static int it913x_fe_suspend(struct it913x_fe_state *state)
531{
532 int ret, i;
533 u8 b;
534
535 ret = it913x_write_reg(state, PRO_DMOD, SUSPEND_FLAG, 0x1);
536
537 ret |= it913x_write_reg(state, PRO_DMOD, TRIGGER_OFSM, 0x0);
538
539 for (i = 0; i < 128; i++) {
540 ret = it913x_read_reg(state, SUSPEND_FLAG, &b, 1);
541 if (ret < 0)
542 return -EINVAL;
543 if (b == 0)
544 break;
545
546 }
547
548 ret |= it913x_write_reg(state, PRO_DMOD, AFE_MEM0, 0x8);
549 /* Turn LED off */
550 ret = it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x0);
551
552 return 0;
553}
554
555static int it913x_fe_sleep(struct dvb_frontend *fe)
556{
557 struct it913x_fe_state *state = fe->demodulator_priv;
558 return it913x_fe_suspend(state);
559}
560
561
562static u32 compute_div(u32 a, u32 b, u32 x)
563{
564 u32 res = 0;
565 u32 c = 0;
566 u32 i = 0;
567
568 if (a > b) {
569 c = a / b;
570 a = a - c * b;
571 }
572
573 for (i = 0; i < x; i++) {
574 if (a >= b) {
575 res += 1;
576 a -= b;
577 }
578 a <<= 1;
579 res <<= 1;
580 }
581
582 res = (c << x) + res;
583
584 return res;
585}
586
587static int it913x_fe_start(struct it913x_fe_state *state)
588{
589 struct it913xset *set_fe;
590 struct it913xset *set_mode;
591 int ret;
592 u8 adf = (state->adf & 0xf);
593 u32 adc, xtal;
594 u8 b[4];
595
596 if (adf < 12) {
597 state->crystalFrequency = fe_clockTable[adf].xtal ;
598 state->table = fe_clockTable[adf].table;
599 state->adcFrequency = state->table->adcFrequency;
600
601 adc = compute_div(state->adcFrequency, 1000000ul, 19ul);
602 xtal = compute_div(state->crystalFrequency, 1000000ul, 19ul);
603
604 } else
605 return -EINVAL;
606
607 deb_info("Xtal Freq :%d Adc Freq :%d Adc %08x Xtal %08x",
608 state->crystalFrequency, state->adcFrequency, adc, xtal);
609
610 /* Set LED indicator on GPIOH3 */
611 ret = it913x_write_reg(state, PRO_LINK, GPIOH3_EN, 0x1);
612 ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_ON, 0x1);
613 ret |= it913x_write_reg(state, PRO_LINK, GPIOH3_O, 0x1);
614
615 ret |= it913x_write_reg(state, PRO_DMOD, 0xed81, 0x10);
616 ret |= it913x_write_reg(state, PRO_LINK, 0xf641, state->tuner_type);
617 ret |= it913x_write_reg(state, PRO_DMOD, 0xf5ca, 0x01);
618 ret |= it913x_write_reg(state, PRO_DMOD, 0xf715, 0x01);
619
620 b[0] = xtal & 0xff;
621 b[1] = (xtal >> 8) & 0xff;
622 b[2] = (xtal >> 16) & 0xff;
623 b[3] = (xtal >> 24);
624 ret |= it913x_write(state, PRO_DMOD, XTAL_CLK, b , 4);
625
626 b[0] = adc & 0xff;
627 b[1] = (adc >> 8) & 0xff;
628 b[2] = (adc >> 16) & 0xff;
629 ret |= it913x_write(state, PRO_DMOD, ADC_FREQ, b, 3);
630
631 switch (state->tuner_type) {
632 case IT9137: /* Tuner type 0x38 */
633 set_fe = it9137_set;
634 break;
635 default:
636 return -EINVAL;
637 }
638 /* set the demod */
639 ret = it913x_fe_script_loader(state, set_fe);
640 /* Always solo frontend */
641 set_mode = set_solo_fe;
642 ret |= it913x_fe_script_loader(state, set_mode);
643
644 ret |= it913x_fe_suspend(state);
645 return 0;
646}
647
648static int it913x_fe_init(struct dvb_frontend *fe)
649{
650 struct it913x_fe_state *state = fe->demodulator_priv;
651 struct it913xset *set_tuner;
652 int ret = 0;
653
654 switch (state->tuner_type) {
655 case IT9137: /* Tuner type 0x38 */
656 set_tuner = it9137_tuner;
657 break;
658 default:
659 return -EINVAL;
660 }
661
662 /* set any tuner reg(s) */
663 ret = it913x_fe_script_loader(state, set_tuner);
664
665 it913x_write_reg(state, PRO_DMOD, AFE_MEM0, 0x0);
666
667 ret |= it913x_fe_script_loader(state, init_1);
668
669 return (ret < 0) ? -ENODEV : 0;
670}
671
672static void it913x_fe_release(struct dvb_frontend *fe)
673{
674 struct it913x_fe_state *state = fe->demodulator_priv;
675 kfree(state);
676}
677
678static struct dvb_frontend_ops it913x_fe_ofdm_ops;
679
680struct dvb_frontend *it913x_fe_attach(struct i2c_adapter *i2c_adap,
681 u8 i2c_addr, u8 adf, u8 type)
682{
683 struct it913x_fe_state *state = NULL;
684 int ret;
685 /* allocate memory for the internal state */
686 state = kzalloc(sizeof(struct it913x_fe_state), GFP_KERNEL);
687 if (state == NULL)
688 goto error;
689
690 state->i2c_adap = i2c_adap;
691 state->i2c_addr = i2c_addr;
692 state->adf = adf;
693 state->tuner_type = type;
694
695 ret = it913x_fe_start(state);
696 if (ret < 0)
697 goto error;
698
699
700 /* create dvb_frontend */
701 memcpy(&state->frontend.ops, &it913x_fe_ofdm_ops,
702 sizeof(struct dvb_frontend_ops));
703 state->frontend.demodulator_priv = state;
704
705 return &state->frontend;
706error:
707 kfree(state);
708 return NULL;
709}
710EXPORT_SYMBOL(it913x_fe_attach);
711
712static struct dvb_frontend_ops it913x_fe_ofdm_ops = {
713
714 .info = {
715 .name = "it913x-fe DVB-T",
716 .type = FE_OFDM,
717 .frequency_min = 51000000,
718 .frequency_max = 1680000000,
719 .frequency_stepsize = 62500,
720 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
721 FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
722 FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
723 FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
724 FE_CAN_TRANSMISSION_MODE_AUTO |
725 FE_CAN_GUARD_INTERVAL_AUTO |
726 FE_CAN_HIERARCHY_AUTO,
727 },
728
729 .release = it913x_fe_release,
730
731 .init = it913x_fe_init,
732 .sleep = it913x_fe_sleep,
733
734 .set_frontend = it913x_fe_set_frontend,
735 .get_frontend = it913x_fe_get_frontend,
736
737 .read_status = it913x_fe_read_status,
738 .read_signal_strength = it913x_fe_read_signal_strength,
739 .read_snr = it913x_fe_read_snr,
740 .read_ber = it913x_fe_read_ber,
741 .read_ucblocks = it913x_fe_read_ucblocks,
742};
743
744MODULE_DESCRIPTION("it913x Frontend and it9137 tuner");
745MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");
746MODULE_VERSION("1.05");
747MODULE_LICENSE("GPL");