aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/frontends/it913x-fe.c
diff options
context:
space:
mode:
authorMalcolm Priestley <tvboxspy@gmail.com>2011-07-25 14:35:12 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-08-27 09:29:20 -0400
commit3dbbf82f49865c84d472a89ada225039e5c825a0 (patch)
tree6d158542e8208c3fb362e2e8080a614205998b19 /drivers/media/dvb/frontends/it913x-fe.c
parentea3709435c7f2da8852c3d676874cd727253fc60 (diff)
[media] it913x_fe: frontend and tuner driver v1.05
Fronted and Tuner Driver for ITE IT913x Series with inital support for IT9137 integrated demodulator and tuner device. The driver is loosely based on AF9035 series. However, support is not intended for this device specificity. The IT9137 tuner has been tested on UHF bands, but VHF has only been simulated. Possible TODO the tuner sections may be separated from the main driver. All future devices should use the it913x_fe_script_loader for other tuner devices. Signed-off-by: Malcolm Priestley <tvboxspy@gmail.com> [mchehab@redhat.com: Fix an issue at the Kconfig help] Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
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");