]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/linux-3.14.22-dvbsky.patch
Update libvirt to 2.1
[ipfire-2.x.git] / src / patches / linux-3.14.22-dvbsky.patch
1 diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
2 index dd12a1e..969cd15 100644
3 --- a/drivers/media/dvb-frontends/Kconfig
4 +++ b/drivers/media/dvb-frontends/Kconfig
5 @@ -726,6 +726,20 @@ config DVB_TDA665x
6 Currently supported tuners:
7 * Panasonic ENV57H12D5 (ET-50DT)
8
9 +config DVB_DVBSKY_M88DS3103
10 + tristate "Montage M88DS3103 based(DVBSky)"
11 + depends on DVB_CORE && I2C
12 + default m if !MEDIA_SUBDRV_AUTOSELECT
13 + help
14 + A DVB-S/S2 tuner module. Say Y when you want to support this frontend.
15 +
16 +config DVB_M88DC2800
17 + tristate "Montage M88DC2800 based"
18 + depends on DVB_CORE && I2C
19 + default m if !MEDIA_SUBDRV_AUTOSELECT
20 + help
21 + A DVB-C tuner module. Say Y when you want to support this frontend.
22 +
23 config DVB_IX2505V
24 tristate "Sharp IX2505V silicon tuner"
25 depends on DVB_CORE && I2C
26 diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile
27 index 0c75a6a..37c57f9 100644
28 --- a/drivers/media/dvb-frontends/Makefile
29 +++ b/drivers/media/dvb-frontends/Makefile
30 @@ -106,3 +106,5 @@ obj-$(CONFIG_DVB_RTL2832) += rtl2832.o
31 obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o
32 obj-$(CONFIG_DVB_AF9033) += af9033.o
33
34 +obj-$(CONFIG_DVB_DVBSKY_M88DS3103) += dvbsky_m88ds3103.o
35 +obj-$(CONFIG_DVB_M88DC2800) += m88dc2800.o
36 diff --git a/drivers/media/dvb-frontends/dvbsky_m88ds3103.c b/drivers/media/dvb-frontends/dvbsky_m88ds3103.c
37 new file mode 100644
38 index 0000000..5ad1157
39 --- /dev/null
40 +++ b/drivers/media/dvb-frontends/dvbsky_m88ds3103.c
41 @@ -0,0 +1,1723 @@
42 +/*
43 + Montage Technology M88DS3103/M88TS2022 - DVBS/S2 Satellite demod/tuner driver
44 +
45 + Copyright (C) 2011 Max nibble<nibble.max@gmail.com>
46 + Copyright (C) 2010 Montage Technology<www.montage-tech.com>
47 + Copyright (C) 2009 Konstantin Dimitrov.
48 +
49 + This program is free software; you can redistribute it and/or modify
50 + it under the terms of the GNU General Public License as published by
51 + the Free Software Foundation; either version 2 of the License, or
52 + (at your option) any later version.
53 +
54 + This program is distributed in the hope that it will be useful,
55 + but WITHOUT ANY WARRANTY; without even the implied warranty of
56 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57 + GNU General Public License for more details.
58 +
59 + You should have received a copy of the GNU General Public License
60 + along with this program; if not, write to the Free Software
61 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
62 + */
63 +
64 +#include <linux/slab.h>
65 +#include <linux/kernel.h>
66 +#include <linux/module.h>
67 +#include <linux/moduleparam.h>
68 +#include <linux/init.h>
69 +#include <linux/firmware.h>
70 +
71 +#include "dvb_frontend.h"
72 +#include "dvbsky_m88ds3103.h"
73 +#include "dvbsky_m88ds3103_priv.h"
74 +
75 +static int debug;
76 +module_param(debug, int, 0644);
77 +MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
78 +
79 +#define dprintk(args...) \
80 + do { \
81 + if (debug) \
82 + printk(KERN_INFO "m88ds3103: " args); \
83 + } while (0)
84 +
85 +#define _AUTO_S2_
86 +
87 +/*demod register operations.*/
88 +static int m88ds3103_writereg(struct m88ds3103_state *state, int reg, int data)
89 +{
90 + u8 buf[] = { reg, data };
91 + struct i2c_msg msg = { .addr = state->config->demod_address,
92 + .flags = 0, .buf = buf, .len = 2 };
93 + int err;
94 +
95 + if (debug > 1)
96 + printk("m88ds3103: %s: write reg 0x%02x, value 0x%02x\n",
97 + __func__, reg, data);
98 +
99 + err = i2c_transfer(state->i2c, &msg, 1);
100 + if (err != 1) {
101 + printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x,"
102 + " value == 0x%02x)\n", __func__, err, reg, data);
103 + return -EREMOTEIO;
104 + }
105 + return 0;
106 +}
107 +
108 +static int m88ds3103_readreg(struct m88ds3103_state *state, u8 reg)
109 +{
110 + int ret;
111 + u8 b0[] = { reg };
112 + u8 b1[] = { 0 };
113 + struct i2c_msg msg[] = {
114 + { .addr = state->config->demod_address, .flags = 0,
115 + .buf = b0, .len = 1 },
116 + { .addr = state->config->demod_address, .flags = I2C_M_RD,
117 + .buf = b1, .len = 1 }
118 + };
119 + ret = i2c_transfer(state->i2c, msg, 2);
120 +
121 + if (ret != 2) {
122 + printk(KERN_ERR "%s: reg=0x%x (error=%d)\n",
123 + __func__, reg, ret);
124 + return ret;
125 + }
126 +
127 + if (debug > 1)
128 + printk(KERN_INFO "m88ds3103: read reg 0x%02x, value 0x%02x\n",
129 + reg, b1[0]);
130 +
131 + return b1[0];
132 +}
133 +
134 +/*tuner register operations.*/
135 +static int m88ds3103_tuner_writereg(struct m88ds3103_state *state, int reg, int data)
136 +{
137 + u8 buf[] = { reg, data };
138 + struct i2c_msg msg = { .addr = 0x60,
139 + .flags = 0, .buf = buf, .len = 2 };
140 + int err;
141 +
142 + m88ds3103_writereg(state, 0x03, 0x11);
143 + err = i2c_transfer(state->i2c, &msg, 1);
144 +
145 + if (err != 1) {
146 + printk("%s: writereg error(err == %i, reg == 0x%02x,"
147 + " value == 0x%02x)\n", __func__, err, reg, data);
148 + return -EREMOTEIO;
149 + }
150 +
151 + return 0;
152 +}
153 +
154 +static int m88ds3103_tuner_readreg(struct m88ds3103_state *state, u8 reg)
155 +{
156 + int ret;
157 + u8 b0[] = { reg };
158 + u8 b1[] = { 0 };
159 + struct i2c_msg msg[] = {
160 + { .addr = 0x60, .flags = 0,
161 + .buf = b0, .len = 1 },
162 + { .addr = 0x60, .flags = I2C_M_RD,
163 + .buf = b1, .len = 1 }
164 + };
165 +
166 + m88ds3103_writereg(state, 0x03, (0x11 + state->config->tuner_readstops));
167 + ret = i2c_transfer(state->i2c, msg, 2);
168 +
169 + if (ret != 2) {
170 + printk(KERN_ERR "%s: reg=0x%x(error=%d)\n", __func__, reg, ret);
171 + return ret;
172 + }
173 +
174 + return b1[0];
175 +}
176 +
177 +/* Bulk demod I2C write, for firmware download. */
178 +static int m88ds3103_writeregN(struct m88ds3103_state *state, int reg,
179 + const u8 *data, u16 len)
180 +{
181 + int ret = -EREMOTEIO;
182 + struct i2c_msg msg;
183 + u8 *buf;
184 +
185 + buf = kmalloc(len + 1, GFP_KERNEL);
186 + if (buf == NULL) {
187 + printk("Unable to kmalloc\n");
188 + ret = -ENOMEM;
189 + goto error;
190 + }
191 +
192 + *(buf) = reg;
193 + memcpy(buf + 1, data, len);
194 +
195 + msg.addr = state->config->demod_address;
196 + msg.flags = 0;
197 + msg.buf = buf;
198 + msg.len = len + 1;
199 +
200 + if (debug > 1)
201 + printk(KERN_INFO "m88ds3103: %s: write regN 0x%02x, len = %d\n",
202 + __func__, reg, len);
203 +
204 + ret = i2c_transfer(state->i2c, &msg, 1);
205 + if (ret != 1) {
206 + printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x\n",
207 + __func__, ret, reg);
208 + ret = -EREMOTEIO;
209 + }
210 +
211 +error:
212 + kfree(buf);
213 +
214 + return ret;
215 +}
216 +
217 +static int m88ds3103_load_firmware(struct dvb_frontend *fe)
218 +{
219 + struct m88ds3103_state *state = fe->demodulator_priv;
220 + const struct firmware *fw;
221 + int i, ret = 0;
222 +
223 + dprintk("%s()\n", __func__);
224 +
225 + if (state->skip_fw_load)
226 + return 0;
227 + /* Load firmware */
228 + /* request the firmware, this will block until someone uploads it */
229 + if(state->demod_id == DS3000_ID){
230 + printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", __func__,
231 + DS3000_DEFAULT_FIRMWARE);
232 + ret = request_firmware(&fw, DS3000_DEFAULT_FIRMWARE,
233 + state->i2c->dev.parent);
234 + }else if(state->demod_id == DS3103_ID){
235 + printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", __func__,
236 + DS3103_DEFAULT_FIRMWARE);
237 + ret = request_firmware(&fw, DS3103_DEFAULT_FIRMWARE,
238 + state->i2c->dev.parent);
239 + }
240 +
241 + printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n", __func__);
242 + if (ret) {
243 + printk(KERN_ERR "%s: No firmware uploaded (timeout or file not "
244 + "found?)\n", __func__);
245 + return ret;
246 + }
247 +
248 + /* Make sure we don't recurse back through here during loading */
249 + state->skip_fw_load = 1;
250 +
251 + dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n",
252 + fw->size,
253 + fw->data[0],
254 + fw->data[1],
255 + fw->data[fw->size - 2],
256 + fw->data[fw->size - 1]);
257 +
258 + /* stop internal mcu. */
259 + m88ds3103_writereg(state, 0xb2, 0x01);
260 + /* split firmware to download.*/
261 + for(i = 0; i < FW_DOWN_LOOP; i++){
262 + ret = m88ds3103_writeregN(state, 0xb0, &(fw->data[FW_DOWN_SIZE*i]), FW_DOWN_SIZE);
263 + if(ret != 1) break;
264 + }
265 + /* start internal mcu. */
266 + if(ret == 1)
267 + m88ds3103_writereg(state, 0xb2, 0x00);
268 +
269 + release_firmware(fw);
270 +
271 + dprintk("%s: Firmware upload %s\n", __func__,
272 + ret == 1 ? "complete" : "failed");
273 +
274 + if(ret == 1) ret = 0;
275 +
276 + /* Ensure firmware is always loaded if required */
277 + state->skip_fw_load = 0;
278 +
279 + return ret;
280 +}
281 +
282 +
283 +static int m88ds3103_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
284 +{
285 + struct m88ds3103_state *state = fe->demodulator_priv;
286 + u8 data;
287 +
288 + dprintk("%s(%d)\n", __func__, voltage);
289 +
290 + dprintk("m88ds3103:pin_ctrl = (%02x)\n", state->config->pin_ctrl);
291 +
292 + if(state->config->set_voltage)
293 + state->config->set_voltage(fe, voltage);
294 +
295 + data = m88ds3103_readreg(state, 0xa2);
296 +
297 + if(state->config->pin_ctrl & 0x80){ /*If control pin is assigned.*/
298 + data &= ~0x03; /* bit0 V/H, bit1 off/on */
299 + if(state->config->pin_ctrl & 0x02)
300 + data |= 0x02;
301 +
302 + switch (voltage) {
303 + case SEC_VOLTAGE_18:
304 + if((state->config->pin_ctrl & 0x01) == 0)
305 + data |= 0x01;
306 + break;
307 + case SEC_VOLTAGE_13:
308 + if(state->config->pin_ctrl & 0x01)
309 + data |= 0x01;
310 + break;
311 + case SEC_VOLTAGE_OFF:
312 + if(state->config->pin_ctrl & 0x02)
313 + data &= ~0x02;
314 + else
315 + data |= 0x02;
316 + break;
317 + }
318 + }
319 +
320 + m88ds3103_writereg(state, 0xa2, data);
321 +
322 + return 0;
323 +}
324 +
325 +static int m88ds3103_read_status(struct dvb_frontend *fe, fe_status_t* status)
326 +{
327 + struct m88ds3103_state *state = fe->demodulator_priv;
328 + int lock = 0;
329 +
330 + *status = 0;
331 +
332 + switch (state->delivery_system){
333 + case SYS_DVBS:
334 + lock = m88ds3103_readreg(state, 0xd1);
335 + dprintk("%s: SYS_DVBS status=%x.\n", __func__, lock);
336 +
337 + if ((lock & 0x07) == 0x07){
338 + /*if((m88ds3103_readreg(state, 0x0d) & 0x07) == 0x07)*/
339 + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER
340 + | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
341 +
342 + }
343 + break;
344 + case SYS_DVBS2:
345 + lock = m88ds3103_readreg(state, 0x0d);
346 + dprintk("%s: SYS_DVBS2 status=%x.\n", __func__, lock);
347 +
348 + if ((lock & 0x8f) == 0x8f)
349 + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER
350 + | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
351 +
352 + break;
353 + default:
354 + break;
355 + }
356 +
357 + return 0;
358 +}
359 +
360 +static int m88ds3103_read_ber(struct dvb_frontend *fe, u32* ber)
361 +{
362 + struct m88ds3103_state *state = fe->demodulator_priv;
363 + u8 tmp1, tmp2, tmp3;
364 + u32 ldpc_frame_cnt, pre_err_packags, code_rate_fac = 0;
365 +
366 + dprintk("%s()\n", __func__);
367 +
368 + switch (state->delivery_system) {
369 + case SYS_DVBS:
370 + m88ds3103_writereg(state, 0xf9, 0x04);
371 + tmp3 = m88ds3103_readreg(state, 0xf8);
372 + if ((tmp3&0x10) == 0){
373 + tmp1 = m88ds3103_readreg(state, 0xf7);
374 + tmp2 = m88ds3103_readreg(state, 0xf6);
375 + tmp3 |= 0x10;
376 + m88ds3103_writereg(state, 0xf8, tmp3);
377 + state->preBer = (tmp1<<8) | tmp2;
378 + }
379 + break;
380 + case SYS_DVBS2:
381 + tmp1 = m88ds3103_readreg(state, 0x7e) & 0x0f;
382 + switch(tmp1){
383 + case 0: code_rate_fac = 16008 - 80; break;
384 + case 1: code_rate_fac = 21408 - 80; break;
385 + case 2: code_rate_fac = 25728 - 80; break;
386 + case 3: code_rate_fac = 32208 - 80; break;
387 + case 4: code_rate_fac = 38688 - 80; break;
388 + case 5: code_rate_fac = 43040 - 80; break;
389 + case 6: code_rate_fac = 48408 - 80; break;
390 + case 7: code_rate_fac = 51648 - 80; break;
391 + case 8: code_rate_fac = 53840 - 80; break;
392 + case 9: code_rate_fac = 57472 - 80; break;
393 + case 10: code_rate_fac = 58192 - 80; break;
394 + }
395 +
396 + tmp1 = m88ds3103_readreg(state, 0xd7) & 0xff;
397 + tmp2 = m88ds3103_readreg(state, 0xd6) & 0xff;
398 + tmp3 = m88ds3103_readreg(state, 0xd5) & 0xff;
399 + ldpc_frame_cnt = (tmp1 << 16) | (tmp2 << 8) | tmp3;
400 +
401 + tmp1 = m88ds3103_readreg(state, 0xf8) & 0xff;
402 + tmp2 = m88ds3103_readreg(state, 0xf7) & 0xff;
403 + pre_err_packags = tmp1<<8 | tmp2;
404 +
405 + if (ldpc_frame_cnt > 1000){
406 + m88ds3103_writereg(state, 0xd1, 0x01);
407 + m88ds3103_writereg(state, 0xf9, 0x01);
408 + m88ds3103_writereg(state, 0xf9, 0x00);
409 + m88ds3103_writereg(state, 0xd1, 0x00);
410 + state->preBer = pre_err_packags;
411 + }
412 + break;
413 + default:
414 + break;
415 + }
416 + *ber = state->preBer;
417 +
418 + return 0;
419 +}
420 +
421 +static int m88ds3103_read_signal_strength(struct dvb_frontend *fe,
422 + u16 *signal_strength)
423 +{
424 + struct m88ds3103_state *state = fe->demodulator_priv;
425 + u16 gain;
426 + u8 gain1, gain2, gain3 = 0;
427 +
428 + dprintk("%s()\n", __func__);
429 +
430 + gain1 = m88ds3103_tuner_readreg(state, 0x3d) & 0x1f;
431 + dprintk("%s: gain1 = 0x%02x \n", __func__, gain1);
432 +
433 + if (gain1 > 15) gain1 = 15;
434 + gain2 = m88ds3103_tuner_readreg(state, 0x21) & 0x1f;
435 + dprintk("%s: gain2 = 0x%02x \n", __func__, gain2);
436 +
437 + if(state->tuner_id == TS2022_ID){
438 + gain3 = (m88ds3103_tuner_readreg(state, 0x66)>>3) & 0x07;
439 + dprintk("%s: gain3 = 0x%02x \n", __func__, gain3);
440 +
441 + if (gain2 > 16) gain2 = 16;
442 + if (gain2 < 2) gain2 = 2;
443 + if (gain3 > 6) gain3 = 6;
444 + }else{
445 + if (gain2 > 13) gain2 = 13;
446 + gain3 = 0;
447 + }
448 +
449 + gain = gain1*23 + gain2*35 + gain3*29;
450 + *signal_strength = 60000 - gain*55;
451 +
452 + return 0;
453 +}
454 +
455 +
456 +static int m88ds3103_read_snr(struct dvb_frontend *fe, u16 *p_snr)
457 +{
458 + struct m88ds3103_state *state = fe->demodulator_priv;
459 + u8 val, npow1, npow2, spow1, cnt;
460 + u16 tmp, snr;
461 + u32 npow, spow, snr_total;
462 + static const u16 mes_log10[] ={
463 + 0, 3010, 4771, 6021, 6990, 7781, 8451, 9031, 9542, 10000,
464 + 10414, 10792, 11139, 11461, 11761, 12041, 12304, 12553, 12788, 13010,
465 + 13222, 13424, 13617, 13802, 13979, 14150, 14314, 14472, 14624, 14771,
466 + 14914, 15052, 15185, 15315, 15441, 15563, 15682, 15798, 15911, 16021,
467 + 16128, 16232, 16335, 16435, 16532, 16628, 16721, 16812, 16902, 16990,
468 + 17076, 17160, 17243, 17324, 17404, 17482, 17559, 17634, 17709, 17782,
469 + 17853, 17924, 17993, 18062, 18129, 18195, 18261, 18325, 18388, 18451,
470 + 18513, 18573, 18633, 18692, 18751, 18808, 18865, 18921, 18976, 19031
471 + };
472 + static const u16 mes_loge[] ={
473 + 0, 6931, 10986, 13863, 16094, 17918, 19459, 20794, 21972, 23026,
474 + 23979, 24849, 25649, 26391, 27081, 27726, 28332, 28904, 29444, 29957,
475 + 30445, 30910, 31355, 31781, 32189, 32581, 32958, 33322, 33673, 34012,
476 + 34340, 34657,
477 + };
478 +
479 + dprintk("%s()\n", __func__);
480 +
481 + snr = 0;
482 +
483 + switch (state->delivery_system){
484 + case SYS_DVBS:
485 + cnt = 10; snr_total = 0;
486 + while(cnt > 0){
487 + val = m88ds3103_readreg(state, 0xff);
488 + snr_total += val;
489 + cnt--;
490 + }
491 + tmp = (u16)(snr_total/80);
492 + if(tmp > 0){
493 + if (tmp > 32) tmp = 32;
494 + snr = (mes_loge[tmp - 1] * 100) / 45;
495 + }else{
496 + snr = 0;
497 + }
498 + break;
499 + case SYS_DVBS2:
500 + cnt = 10; npow = 0; spow = 0;
501 + while(cnt >0){
502 + npow1 = m88ds3103_readreg(state, 0x8c) & 0xff;
503 + npow2 = m88ds3103_readreg(state, 0x8d) & 0xff;
504 + npow += (((npow1 & 0x3f) + (u16)(npow2 << 6)) >> 2);
505 +
506 + spow1 = m88ds3103_readreg(state, 0x8e) & 0xff;
507 + spow += ((spow1 * spow1) >> 1);
508 + cnt--;
509 + }
510 + npow /= 10; spow /= 10;
511 + if(spow == 0){
512 + snr = 0;
513 + }else if(npow == 0){
514 + snr = 19;
515 + }else{
516 + if(spow > npow){
517 + tmp = (u16)(spow / npow);
518 + if (tmp > 80) tmp = 80;
519 + snr = mes_log10[tmp - 1]*3;
520 + }else{
521 + tmp = (u16)(npow / spow);
522 + if (tmp > 80) tmp = 80;
523 + snr = -(mes_log10[tmp - 1] / 1000);
524 + }
525 + }
526 + break;
527 + default:
528 + break;
529 + }
530 + *p_snr = snr;
531 +
532 + return 0;
533 +}
534 +
535 +
536 +static int m88ds3103_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
537 +{
538 + struct m88ds3103_state *state = fe->demodulator_priv;
539 + u8 tmp1, tmp2, tmp3, data;
540 +
541 + dprintk("%s()\n", __func__);
542 +
543 + switch (state->delivery_system) {
544 + case SYS_DVBS:
545 + data = m88ds3103_readreg(state, 0xf8);
546 + data |= 0x40;
547 + m88ds3103_writereg(state, 0xf8, data);
548 + tmp1 = m88ds3103_readreg(state, 0xf5);
549 + tmp2 = m88ds3103_readreg(state, 0xf4);
550 + *ucblocks = (tmp1 <<8) | tmp2;
551 + data &= ~0x20;
552 + m88ds3103_writereg(state, 0xf8, data);
553 + data |= 0x20;
554 + m88ds3103_writereg(state, 0xf8, data);
555 + data &= ~0x40;
556 + m88ds3103_writereg(state, 0xf8, data);
557 + break;
558 + case SYS_DVBS2:
559 + tmp1 = m88ds3103_readreg(state, 0xda);
560 + tmp2 = m88ds3103_readreg(state, 0xd9);
561 + tmp3 = m88ds3103_readreg(state, 0xd8);
562 + *ucblocks = (tmp1 <<16)|(tmp2 <<8)|tmp3;
563 + data = m88ds3103_readreg(state, 0xd1);
564 + data |= 0x01;
565 + m88ds3103_writereg(state, 0xd1, data);
566 + data &= ~0x01;
567 + m88ds3103_writereg(state, 0xd1, data);
568 + break;
569 + default:
570 + break;
571 + }
572 + return 0;
573 +}
574 +
575 +static int m88ds3103_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
576 +{
577 + struct m88ds3103_state *state = fe->demodulator_priv;
578 + u8 data_a1, data_a2;
579 +
580 + dprintk("%s(%d)\n", __func__, tone);
581 + if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) {
582 + printk(KERN_ERR "%s: Invalid, tone=%d\n", __func__, tone);
583 + return -EINVAL;
584 + }
585 +
586 + data_a1 = m88ds3103_readreg(state, 0xa1);
587 + data_a2 = m88ds3103_readreg(state, 0xa2);
588 + if(state->demod_id == DS3103_ID)
589 + data_a2 &= 0xdf; /* Normal mode */
590 + switch (tone) {
591 + case SEC_TONE_ON:
592 + dprintk("%s: SEC_TONE_ON\n", __func__);
593 + data_a1 |= 0x04;
594 + data_a1 &= ~0x03;
595 + data_a1 &= ~0x40;
596 + data_a2 &= ~0xc0;
597 + break;
598 + case SEC_TONE_OFF:
599 + dprintk("%s: SEC_TONE_OFF\n", __func__);
600 + data_a2 &= ~0xc0;
601 + data_a2 |= 0x80;
602 + break;
603 + }
604 + m88ds3103_writereg(state, 0xa2, data_a2);
605 + m88ds3103_writereg(state, 0xa1, data_a1);
606 + return 0;
607 +}
608 +
609 +static int m88ds3103_send_diseqc_msg(struct dvb_frontend *fe,
610 + struct dvb_diseqc_master_cmd *d)
611 +{
612 + struct m88ds3103_state *state = fe->demodulator_priv;
613 + int i, ret = 0;
614 + u8 tmp, time_out;
615 +
616 + /* Dump DiSEqC message */
617 + if (debug) {
618 + printk(KERN_INFO "m88ds3103: %s(", __func__);
619 + for (i = 0 ; i < d->msg_len ;) {
620 + printk(KERN_INFO "0x%02x", d->msg[i]);
621 + if (++i < d->msg_len)
622 + printk(KERN_INFO ", ");
623 + }
624 + }
625 +
626 + tmp = m88ds3103_readreg(state, 0xa2);
627 + tmp &= ~0xc0;
628 + if(state->demod_id == DS3103_ID)
629 + tmp &= ~0x20;
630 + m88ds3103_writereg(state, 0xa2, tmp);
631 +
632 + for (i = 0; i < d->msg_len; i ++)
633 + m88ds3103_writereg(state, (0xa3+i), d->msg[i]);
634 +
635 + tmp = m88ds3103_readreg(state, 0xa1);
636 + tmp &= ~0x38;
637 + tmp &= ~0x40;
638 + tmp |= ((d->msg_len-1) << 3) | 0x07;
639 + tmp &= ~0x80;
640 + m88ds3103_writereg(state, 0xa1, tmp);
641 + /* 1.5 * 9 * 8 = 108ms */
642 + time_out = 150;
643 + while (time_out > 0){
644 + msleep(10);
645 + time_out -= 10;
646 + tmp = m88ds3103_readreg(state, 0xa1);
647 + if ((tmp & 0x40) == 0)
648 + break;
649 + }
650 + if (time_out == 0){
651 + tmp = m88ds3103_readreg(state, 0xa1);
652 + tmp &= ~0x80;
653 + tmp |= 0x40;
654 + m88ds3103_writereg(state, 0xa1, tmp);
655 + ret = 1;
656 + }
657 + tmp = m88ds3103_readreg(state, 0xa2);
658 + tmp &= ~0xc0;
659 + tmp |= 0x80;
660 + m88ds3103_writereg(state, 0xa2, tmp);
661 + return ret;
662 +}
663 +
664 +
665 +static int m88ds3103_diseqc_send_burst(struct dvb_frontend *fe,
666 + fe_sec_mini_cmd_t burst)
667 +{
668 + struct m88ds3103_state *state = fe->demodulator_priv;
669 + u8 val, time_out;
670 +
671 + dprintk("%s()\n", __func__);
672 +
673 + val = m88ds3103_readreg(state, 0xa2);
674 + val &= ~0xc0;
675 + if(state->demod_id == DS3103_ID)
676 + val &= 0xdf; /* Normal mode */
677 + m88ds3103_writereg(state, 0xa2, val);
678 + /* DiSEqC burst */
679 + if (burst == SEC_MINI_B)
680 + m88ds3103_writereg(state, 0xa1, 0x01);
681 + else
682 + m88ds3103_writereg(state, 0xa1, 0x02);
683 +
684 + msleep(13);
685 +
686 + time_out = 5;
687 + do{
688 + val = m88ds3103_readreg(state, 0xa1);
689 + if ((val & 0x40) == 0)
690 + break;
691 + msleep(1);
692 + time_out --;
693 + } while (time_out > 0);
694 +
695 + val = m88ds3103_readreg(state, 0xa2);
696 + val &= ~0xc0;
697 + val |= 0x80;
698 + m88ds3103_writereg(state, 0xa2, val);
699 +
700 + return 0;
701 +}
702 +
703 +static void m88ds3103_release(struct dvb_frontend *fe)
704 +{
705 + struct m88ds3103_state *state = fe->demodulator_priv;
706 +
707 + dprintk("%s\n", __func__);
708 + kfree(state);
709 +}
710 +
711 +static int m88ds3103_check_id(struct m88ds3103_state *state)
712 +{
713 + int val_00, val_01;
714 +
715 + /*check demod id*/
716 + val_01 = m88ds3103_readreg(state, 0x01);
717 + printk(KERN_INFO "DS3000 chip version: %x attached.\n", val_01);
718 +
719 + if(val_01 == 0xD0)
720 + state->demod_id = DS3103_ID;
721 + else if(val_01 == 0xC0)
722 + state->demod_id = DS3000_ID;
723 + else
724 + state->demod_id = UNKNOW_ID;
725 +
726 + /*check tuner id*/
727 + val_00 = m88ds3103_tuner_readreg(state, 0x00);
728 + printk(KERN_INFO "TS202x chip version[1]: %x attached.\n", val_00);
729 + val_00 &= 0x03;
730 + if(val_00 == 0)
731 + {
732 + m88ds3103_tuner_writereg(state, 0x00, 0x01);
733 + msleep(3);
734 + }
735 + m88ds3103_tuner_writereg(state, 0x00, 0x03);
736 + msleep(5);
737 +
738 + val_00 = m88ds3103_tuner_readreg(state, 0x00);
739 + printk(KERN_INFO "TS202x chip version[2]: %x attached.\n", val_00);
740 + val_00 &= 0xff;
741 + if((val_00 == 0x01) || (val_00 == 0x41) || (val_00 == 0x81))
742 + state->tuner_id = TS2020_ID;
743 + else if(((val_00 & 0xc0)== 0xc0) || (val_00 == 0x83))
744 + state->tuner_id = TS2022_ID;
745 + else
746 + state->tuner_id = UNKNOW_ID;
747 +
748 + return state->demod_id;
749 +}
750 +
751 +static struct dvb_frontend_ops m88ds3103_ops;
752 +static int m88ds3103_initilaze(struct dvb_frontend *fe);
753 +
754 +struct dvb_frontend *dvbsky_m88ds3103_attach(const struct dvbsky_m88ds3103_config *config,
755 + struct i2c_adapter *i2c)
756 +{
757 + struct m88ds3103_state *state = NULL;
758 +
759 + dprintk("%s\n", __func__);
760 +
761 + /* allocate memory for the internal state */
762 + state = kzalloc(sizeof(struct m88ds3103_state), GFP_KERNEL);
763 + if (state == NULL) {
764 + printk(KERN_ERR "Unable to kmalloc\n");
765 + goto error2;
766 + }
767 +
768 + state->config = config;
769 + state->i2c = i2c;
770 + state->preBer = 0xffff;
771 + state->delivery_system = SYS_DVBS; /*Default to DVB-S.*/
772 +
773 + /* check demod id */
774 + if(m88ds3103_check_id(state) == UNKNOW_ID){
775 + printk(KERN_ERR "Unable to find Montage chip\n");
776 + goto error3;
777 + }
778 +
779 + memcpy(&state->frontend.ops, &m88ds3103_ops,
780 + sizeof(struct dvb_frontend_ops));
781 + state->frontend.demodulator_priv = state;
782 +
783 + m88ds3103_initilaze(&state->frontend);
784 +
785 + return &state->frontend;
786 +
787 +error3:
788 + kfree(state);
789 +error2:
790 + return NULL;
791 +}
792 +EXPORT_SYMBOL(dvbsky_m88ds3103_attach);
793 +
794 +static int m88ds3103_set_carrier_offset(struct dvb_frontend *fe,
795 + s32 carrier_offset_khz)
796 +{
797 + struct m88ds3103_state *state = fe->demodulator_priv;
798 + s32 tmp;
799 +
800 + tmp = carrier_offset_khz;
801 + tmp *= 65536;
802 +
803 + tmp = (2*tmp + MT_FE_MCLK_KHZ) / (2*MT_FE_MCLK_KHZ);
804 +
805 + if (tmp < 0)
806 + tmp += 65536;
807 +
808 + m88ds3103_writereg(state, 0x5f, tmp >> 8);
809 + m88ds3103_writereg(state, 0x5e, tmp & 0xff);
810 +
811 + return 0;
812 +}
813 +
814 +static int m88ds3103_set_symrate(struct dvb_frontend *fe)
815 +{
816 + struct m88ds3103_state *state = fe->demodulator_priv;
817 + struct dtv_frontend_properties *c = &fe->dtv_property_cache;
818 + u16 value;
819 +
820 + value = (((c->symbol_rate / 1000) << 15) + (MT_FE_MCLK_KHZ / 4)) / (MT_FE_MCLK_KHZ / 2);
821 + m88ds3103_writereg(state, 0x61, value & 0x00ff);
822 + m88ds3103_writereg(state, 0x62, (value & 0xff00) >> 8);
823 +
824 + return 0;
825 +}
826 +
827 +static int m88ds3103_set_CCI(struct dvb_frontend *fe)
828 +{
829 + struct m88ds3103_state *state = fe->demodulator_priv;
830 + u8 tmp;
831 +
832 + tmp = m88ds3103_readreg(state, 0x56);
833 + tmp &= ~0x01;
834 + m88ds3103_writereg(state, 0x56, tmp);
835 +
836 + tmp = m88ds3103_readreg(state, 0x76);
837 + tmp &= ~0x80;
838 + m88ds3103_writereg(state, 0x76, tmp);
839 +
840 + return 0;
841 +}
842 +
843 +static int m88ds3103_init_reg(struct m88ds3103_state *state, const u8 *p_reg_tab, u32 size)
844 +{
845 + u32 i;
846 +
847 + for(i = 0; i < size; i+=2)
848 + m88ds3103_writereg(state, p_reg_tab[i], p_reg_tab[i+1]);
849 +
850 + return 0;
851 +}
852 +
853 +static int m88ds3103_get_locked_sym_rate(struct m88ds3103_state *state, u32 *sym_rate_KSs)
854 +{
855 + u16 tmp;
856 + u32 sym_rate_tmp;
857 + u8 val_0x6d, val_0x6e;
858 +
859 + val_0x6d = m88ds3103_readreg(state, 0x6d);
860 + val_0x6e = m88ds3103_readreg(state, 0x6e);
861 +
862 + tmp = (u16)((val_0x6e<<8) | val_0x6d);
863 +
864 + sym_rate_tmp = (u32)(tmp * MT_FE_MCLK_KHZ);
865 + sym_rate_tmp = (u32)(sym_rate_tmp / (1<<16));
866 + *sym_rate_KSs = sym_rate_tmp;
867 +
868 + return 0;
869 +}
870 +
871 +static int m88ds3103_get_channel_info(struct m88ds3103_state *state, u8 *p_mode, u8 *p_coderate)
872 +{
873 + u8 tmp, val_0x7E;
874 +
875 + if(state->delivery_system == SYS_DVBS2){
876 + val_0x7E = m88ds3103_readreg(state, 0x7e);
877 + tmp = (u8)((val_0x7E&0xC0) >> 6);
878 + *p_mode = tmp;
879 + tmp = (u8)(val_0x7E & 0x0f);
880 + *p_coderate = tmp;
881 + } else {
882 + *p_mode = 0;
883 + tmp = m88ds3103_readreg(state, 0xe6);
884 + tmp = (u8)(tmp >> 5);
885 + *p_coderate = tmp;
886 + }
887 +
888 + return 0;
889 +}
890 +
891 +static int m88ds3103_set_clock_ratio(struct m88ds3103_state *state)
892 +{
893 + u8 val, mod_fac, tmp1, tmp2;
894 + u32 input_datarate, locked_sym_rate_KSs;
895 + u32 MClk_KHz = 96000;
896 + u8 mod_mode, code_rate, divid_ratio = 0;
897 +
898 + locked_sym_rate_KSs = 0;
899 + m88ds3103_get_locked_sym_rate(state, &locked_sym_rate_KSs);
900 + if(locked_sym_rate_KSs == 0)
901 + return 0;
902 +
903 + m88ds3103_get_channel_info(state, &mod_mode, &code_rate);
904 +
905 + if (state->delivery_system == SYS_DVBS2)
906 + {
907 + switch(mod_mode) {
908 + case 1: mod_fac = 3; break;
909 + case 2: mod_fac = 4; break;
910 + case 3: mod_fac = 5; break;
911 + default: mod_fac = 2; break;
912 + }
913 +
914 + switch(code_rate) {
915 + case 0: input_datarate = locked_sym_rate_KSs*mod_fac/8/4; break;
916 + case 1: input_datarate = locked_sym_rate_KSs*mod_fac/8/3; break;
917 + case 2: input_datarate = locked_sym_rate_KSs*mod_fac*2/8/5; break;
918 + case 3: input_datarate = locked_sym_rate_KSs*mod_fac/8/2; break;
919 + case 4: input_datarate = locked_sym_rate_KSs*mod_fac*3/8/5; break;
920 + case 5: input_datarate = locked_sym_rate_KSs*mod_fac*2/8/3; break;
921 + case 6: input_datarate = locked_sym_rate_KSs*mod_fac*3/8/4; break;
922 + case 7: input_datarate = locked_sym_rate_KSs*mod_fac*4/8/5; break;
923 + case 8: input_datarate = locked_sym_rate_KSs*mod_fac*5/8/6; break;
924 + case 9: input_datarate = locked_sym_rate_KSs*mod_fac*8/8/9; break;
925 + case 10: input_datarate = locked_sym_rate_KSs*mod_fac*9/8/10; break;
926 + default: input_datarate = locked_sym_rate_KSs*mod_fac*2/8/3; break;
927 + }
928 +
929 + if(state->demod_id == DS3000_ID)
930 + input_datarate = input_datarate * 115 / 100;
931 +
932 + if(input_datarate < 4800) {tmp1 = 15;tmp2 = 15;} //4.8MHz TS clock
933 + else if(input_datarate < 4966) {tmp1 = 14;tmp2 = 15;} //4.966MHz TS clock
934 + else if(input_datarate < 5143) {tmp1 = 14;tmp2 = 14;} //5.143MHz TS clock
935 + else if(input_datarate < 5333) {tmp1 = 13;tmp2 = 14;} //5.333MHz TS clock
936 + else if(input_datarate < 5538) {tmp1 = 13;tmp2 = 13;} //5.538MHz TS clock
937 + else if(input_datarate < 5760) {tmp1 = 12;tmp2 = 13;} //5.76MHz TS clock allan 0809
938 + else if(input_datarate < 6000) {tmp1 = 12;tmp2 = 12;} //6MHz TS clock
939 + else if(input_datarate < 6260) {tmp1 = 11;tmp2 = 12;} //6.26MHz TS clock
940 + else if(input_datarate < 6545) {tmp1 = 11;tmp2 = 11;} //6.545MHz TS clock
941 + else if(input_datarate < 6857) {tmp1 = 10;tmp2 = 11;} //6.857MHz TS clock
942 + else if(input_datarate < 7200) {tmp1 = 10;tmp2 = 10;} //7.2MHz TS clock
943 + else if(input_datarate < 7578) {tmp1 = 9;tmp2 = 10;} //7.578MHz TS clock
944 + else if(input_datarate < 8000) {tmp1 = 9;tmp2 = 9;} //8MHz TS clock
945 + else if(input_datarate < 8470) {tmp1 = 8;tmp2 = 9;} //8.47MHz TS clock
946 + else if(input_datarate < 9000) {tmp1 = 8;tmp2 = 8;} //9MHz TS clock
947 + else if(input_datarate < 9600) {tmp1 = 7;tmp2 = 8;} //9.6MHz TS clock
948 + else if(input_datarate < 10285) {tmp1 = 7;tmp2 = 7;} //10.285MHz TS clock
949 + else if(input_datarate < 12000) {tmp1 = 6;tmp2 = 6;} //12MHz TS clock
950 + else if(input_datarate < 14400) {tmp1 = 5;tmp2 = 5;} //14.4MHz TS clock
951 + else if(input_datarate < 18000) {tmp1 = 4;tmp2 = 4;} //18MHz TS clock
952 + else {tmp1 = 3;tmp2 = 3;} //24MHz TS clock
953 +
954 + if(state->demod_id == DS3000_ID) {
955 + val = (u8)((tmp1<<4) + tmp2);
956 + m88ds3103_writereg(state, 0xfe, val);
957 + } else {
958 + tmp1 = m88ds3103_readreg(state, 0x22);
959 + tmp2 = m88ds3103_readreg(state, 0x24);
960 +
961 + tmp1 >>= 6;
962 + tmp1 &= 0x03;
963 + tmp2 >>= 6;
964 + tmp2 &= 0x03;
965 +
966 + if((tmp1 == 0x00) && (tmp2 == 0x01))
967 + MClk_KHz = 144000;
968 + else if((tmp1 == 0x00) && (tmp2 == 0x03))
969 + MClk_KHz = 72000;
970 + else if((tmp1 == 0x01) && (tmp2 == 0x01))
971 + MClk_KHz = 115200;
972 + else if((tmp1 == 0x02) && (tmp2 == 0x01))
973 + MClk_KHz = 96000;
974 + else if((tmp1 == 0x03) && (tmp2 == 0x00))
975 + MClk_KHz = 192000;
976 + else
977 + return 0;
978 +
979 + if(input_datarate < 5200) /*Max. 2011-12-23 11:55*/
980 + input_datarate = 5200;
981 +
982 + if(input_datarate != 0)
983 + divid_ratio = (u8)(MClk_KHz / input_datarate);
984 + else
985 + divid_ratio = 0xFF;
986 +
987 + if(divid_ratio > 128)
988 + divid_ratio = 128;
989 +
990 + if(divid_ratio < 2)
991 + divid_ratio = 2;
992 +
993 + tmp1 = (u8)(divid_ratio / 2);
994 + tmp2 = (u8)(divid_ratio / 2);
995 +
996 + if((divid_ratio % 2) != 0)
997 + tmp2 += 1;
998 +
999 + tmp1 -= 1;
1000 + tmp2 -= 1;
1001 +
1002 + tmp1 &= 0x3f;
1003 + tmp2 &= 0x3f;
1004 +
1005 + val = m88ds3103_readreg(state, 0xfe);
1006 + val &= 0xF0;
1007 + val |= (tmp2 >> 2) & 0x0f;
1008 + m88ds3103_writereg(state, 0xfe, val);
1009 +
1010 + val = (u8)((tmp2 & 0x03) << 6);
1011 + val |= tmp1;
1012 + m88ds3103_writereg(state, 0xea, val);
1013 + }
1014 + } else {
1015 + mod_fac = 2;
1016 +
1017 + switch(code_rate) {
1018 + case 4: input_datarate = locked_sym_rate_KSs*mod_fac/2/8; break;
1019 + case 3: input_datarate = locked_sym_rate_KSs*mod_fac*2/3/8; break;
1020 + case 2: input_datarate = locked_sym_rate_KSs*mod_fac*3/4/8; break;
1021 + case 1: input_datarate = locked_sym_rate_KSs*mod_fac*5/6/8; break;
1022 + case 0: input_datarate = locked_sym_rate_KSs*mod_fac*7/8/8; break;
1023 + default: input_datarate = locked_sym_rate_KSs*mod_fac*3/4/8; break;
1024 + }
1025 +
1026 + if(state->demod_id == DS3000_ID)
1027 + input_datarate = input_datarate * 115 / 100;
1028 +
1029 + if(input_datarate < 6857) {tmp1 = 7;tmp2 = 7;} //6.857MHz TS clock
1030 + else if(input_datarate < 7384) {tmp1 = 6;tmp2 = 7;} //7.384MHz TS clock
1031 + else if(input_datarate < 8000) {tmp1 = 6;tmp2 = 6;} //8MHz TS clock
1032 + else if(input_datarate < 8727) {tmp1 = 5;tmp2 = 6;} //8.727MHz TS clock
1033 + else if(input_datarate < 9600) {tmp1 = 5;tmp2 = 5;} //9.6MHz TS clock
1034 + else if(input_datarate < 10666) {tmp1 = 4;tmp2 = 5;} //10.666MHz TS clock
1035 + else if(input_datarate < 12000) {tmp1 = 4;tmp2 = 4;} //12MHz TS clock
1036 + else if(input_datarate < 13714) {tmp1 = 3;tmp2 = 4;} //13.714MHz TS clock
1037 + else if(input_datarate < 16000) {tmp1 = 3;tmp2 = 3;} //16MHz TS clock
1038 + else if(input_datarate < 19200) {tmp1 = 2;tmp2 = 3;} //19.2MHz TS clock
1039 + else {tmp1 = 2;tmp2 = 2;} //24MHz TS clock
1040 +
1041 + if(state->demod_id == DS3000_ID) {
1042 + val = m88ds3103_readreg(state, 0xfe);
1043 + val &= 0xc0;
1044 + val |= ((u8)((tmp1<<3) + tmp2));
1045 + m88ds3103_writereg(state, 0xfe, val);
1046 + } else {
1047 + if(input_datarate < 5200) /*Max. 2011-12-23 11:55*/
1048 + input_datarate = 5200;
1049 +
1050 + if(input_datarate != 0)
1051 + divid_ratio = (u8)(MClk_KHz / input_datarate);
1052 + else
1053 + divid_ratio = 0xFF;
1054 +
1055 + if(divid_ratio > 128)
1056 + divid_ratio = 128;
1057 +
1058 + if(divid_ratio < 2)
1059 + divid_ratio = 2;
1060 +
1061 + tmp1 = (u8)(divid_ratio / 2);
1062 + tmp2 = (u8)(divid_ratio / 2);
1063 +
1064 + if((divid_ratio % 2) != 0)
1065 + tmp2 += 1;
1066 +
1067 + tmp1 -= 1;
1068 + tmp2 -= 1;
1069 +
1070 + tmp1 &= 0x3f;
1071 + tmp2 &= 0x3f;
1072 +
1073 + val = m88ds3103_readreg(state, 0xfe);
1074 + val &= 0xF0;
1075 + val |= (tmp2 >> 2) & 0x0f;
1076 + m88ds3103_writereg(state, 0xfe, val);
1077 +
1078 + val = (u8)((tmp2 & 0x03) << 6);
1079 + val |= tmp1;
1080 + m88ds3103_writereg(state, 0xea, val);
1081 + }
1082 + }
1083 + return 0;
1084 +}
1085 +
1086 +static int m88ds3103_demod_connect(struct dvb_frontend *fe, s32 carrier_offset_khz)
1087 +{
1088 + struct m88ds3103_state *state = fe->demodulator_priv;
1089 + struct dtv_frontend_properties *c = &fe->dtv_property_cache;
1090 + u16 value;
1091 + u8 val1,val2,data;
1092 +
1093 + dprintk("connect delivery system = %d\n", state->delivery_system);
1094 +
1095 + /* ds3000 global reset */
1096 + m88ds3103_writereg(state, 0x07, 0x80);
1097 + m88ds3103_writereg(state, 0x07, 0x00);
1098 + /* ds3000 build-in uC reset */
1099 + m88ds3103_writereg(state, 0xb2, 0x01);
1100 + /* ds3000 software reset */
1101 + m88ds3103_writereg(state, 0x00, 0x01);
1102 +
1103 + switch (state->delivery_system) {
1104 + case SYS_DVBS:
1105 + /* initialise the demod in DVB-S mode */
1106 + if(state->demod_id == DS3000_ID){
1107 + m88ds3103_init_reg(state, ds3000_dvbs_init_tab, sizeof(ds3000_dvbs_init_tab));
1108 +
1109 + value = m88ds3103_readreg(state, 0xfe);
1110 + value &= 0xc0;
1111 + value |= 0x1b;
1112 + m88ds3103_writereg(state, 0xfe, value);
1113 +
1114 + if(state->config->ci_mode)
1115 + val1 = 0x80;
1116 + else if(state->config->ts_mode)
1117 + val1 = 0x60;
1118 + else
1119 + val1 = 0x20;
1120 + m88ds3103_writereg(state, 0xfd, val1);
1121 +
1122 + }else if(state->demod_id == DS3103_ID){
1123 + m88ds3103_init_reg(state, ds3103_dvbs_init_tab, sizeof(ds3103_dvbs_init_tab));
1124 +
1125 + /* set ts clock */
1126 + if(state->config->ci_mode == 2){
1127 + val1 = 6; val2 = 6;
1128 + }else if(state->config->ts_mode == 0) {
1129 + val1 = 3; val2 = 3;
1130 + }else{
1131 + val1 = 0; val2 = 0;
1132 + }
1133 + val1 -= 1; val2 -= 1;
1134 + val1 &= 0x3f; val2 &= 0x3f;
1135 + data = m88ds3103_readreg(state, 0xfe);
1136 + data &= 0xf0;
1137 + data |= (val2 >> 2) & 0x0f;
1138 + m88ds3103_writereg(state, 0xfe, data);
1139 + data = (val2 & 0x03) << 6;
1140 + data |= val1;
1141 + m88ds3103_writereg(state, 0xea, data);
1142 +
1143 + m88ds3103_writereg(state, 0x4d, 0xfd & m88ds3103_readreg(state, 0x4d));
1144 + m88ds3103_writereg(state, 0x30, 0xef & m88ds3103_readreg(state, 0x30));
1145 +
1146 + /* set master clock */
1147 + val1 = m88ds3103_readreg(state, 0x22);
1148 + val2 = m88ds3103_readreg(state, 0x24);
1149 +
1150 + val1 &= 0x3f;
1151 + val2 &= 0x3f;
1152 + val1 |= 0x80;
1153 + val2 |= 0x40;
1154 +
1155 + m88ds3103_writereg(state, 0x22, val1);
1156 + m88ds3103_writereg(state, 0x24, val2);
1157 +
1158 + if(state->config->ci_mode){
1159 + if(state->config->ci_mode == 2)
1160 + val1 = 0x43;
1161 + else
1162 + val1 = 0x03;
1163 + }
1164 + else if(state->config->ts_mode)
1165 + val1 = 0x06;
1166 + else
1167 + val1 = 0x42;
1168 + m88ds3103_writereg(state, 0xfd, val1);
1169 + }
1170 + break;
1171 + case SYS_DVBS2:
1172 + /* initialise the demod in DVB-S2 mode */
1173 + if(state->demod_id == DS3000_ID){
1174 + m88ds3103_init_reg(state, ds3000_dvbs2_init_tab, sizeof(ds3000_dvbs2_init_tab));
1175 +
1176 + if (c->symbol_rate >= 30000000)
1177 + m88ds3103_writereg(state, 0xfe, 0x54);
1178 + else
1179 + m88ds3103_writereg(state, 0xfe, 0x98);
1180 +
1181 + }else if(state->demod_id == DS3103_ID){
1182 + m88ds3103_init_reg(state, ds3103_dvbs2_init_tab, sizeof(ds3103_dvbs2_init_tab));
1183 +
1184 + /* set ts clock */
1185 + if(state->config->ci_mode == 2){
1186 + val1 = 6; val2 = 6;
1187 + }else if(state->config->ts_mode == 0){
1188 + val1 = 5; val2 = 4;
1189 + }else{
1190 + val1 = 0; val2 = 0;
1191 + }
1192 + val1 -= 1; val2 -= 1;
1193 + val1 &= 0x3f; val2 &= 0x3f;
1194 + data = m88ds3103_readreg(state, 0xfe);
1195 + data &= 0xf0;
1196 + data |= (val2 >> 2) & 0x0f;
1197 + m88ds3103_writereg(state, 0xfe, data);
1198 + data = (val2 & 0x03) << 6;
1199 + data |= val1;
1200 + m88ds3103_writereg(state, 0xea, data);
1201 +
1202 + m88ds3103_writereg(state, 0x4d, 0xfd & m88ds3103_readreg(state, 0x4d));
1203 + m88ds3103_writereg(state, 0x30, 0xef & m88ds3103_readreg(state, 0x30));
1204 +
1205 + /* set master clock */
1206 + val1 = m88ds3103_readreg(state, 0x22);
1207 + val2 = m88ds3103_readreg(state, 0x24);
1208 +
1209 + val1 &= 0x3f;
1210 + val2 &= 0x3f;
1211 + if((state->config->ci_mode == 2) || (state->config->ts_mode == 1)){
1212 + val1 |= 0x80;
1213 + val2 |= 0x40;
1214 + }else{
1215 + if (c->symbol_rate >= 28000000){
1216 + val1 |= 0xc0;
1217 + }else if (c->symbol_rate >= 18000000){
1218 + val2 |= 0x40;
1219 + }else{
1220 + val1 |= 0x80;
1221 + val2 |= 0x40;
1222 + }
1223 + }
1224 + m88ds3103_writereg(state, 0x22, val1);
1225 + m88ds3103_writereg(state, 0x24, val2);
1226 + }
1227 +
1228 + if(state->config->ci_mode){
1229 + if(state->config->ci_mode == 2)
1230 + val1 = 0x43;
1231 + else
1232 + val1 = 0x03;
1233 + }
1234 + else if(state->config->ts_mode)
1235 + val1 = 0x06;
1236 + else
1237 + val1 = 0x42;
1238 + m88ds3103_writereg(state, 0xfd, val1);
1239 +
1240 + break;
1241 + default:
1242 + return 1;
1243 + }
1244 + /* disable 27MHz clock output */
1245 + m88ds3103_writereg(state, 0x29, 0x80);
1246 + /* enable ac coupling */
1247 + m88ds3103_writereg(state, 0x25, 0x8a);
1248 +
1249 + if ((c->symbol_rate / 1000) <= 3000){
1250 + m88ds3103_writereg(state, 0xc3, 0x08); /* 8 * 32 * 100 / 64 = 400*/
1251 + m88ds3103_writereg(state, 0xc8, 0x20);
1252 + m88ds3103_writereg(state, 0xc4, 0x08); /* 8 * 0 * 100 / 128 = 0*/
1253 + m88ds3103_writereg(state, 0xc7, 0x00);
1254 + }else if((c->symbol_rate / 1000) <= 10000){
1255 + m88ds3103_writereg(state, 0xc3, 0x08); /* 8 * 16 * 100 / 64 = 200*/
1256 + m88ds3103_writereg(state, 0xc8, 0x10);
1257 + m88ds3103_writereg(state, 0xc4, 0x08); /* 8 * 0 * 100 / 128 = 0*/
1258 + m88ds3103_writereg(state, 0xc7, 0x00);
1259 + }else{
1260 + m88ds3103_writereg(state, 0xc3, 0x08); /* 8 * 6 * 100 / 64 = 75*/
1261 + m88ds3103_writereg(state, 0xc8, 0x06);
1262 + m88ds3103_writereg(state, 0xc4, 0x08); /* 8 * 0 * 100 / 128 = 0*/
1263 + m88ds3103_writereg(state, 0xc7, 0x00);
1264 + }
1265 +
1266 + m88ds3103_set_symrate(fe);
1267 +
1268 + m88ds3103_set_CCI(fe);
1269 +
1270 + m88ds3103_set_carrier_offset(fe, carrier_offset_khz);
1271 +
1272 + /* ds3000 out of software reset */
1273 + m88ds3103_writereg(state, 0x00, 0x00);
1274 + /* start ds3000 build-in uC */
1275 + m88ds3103_writereg(state, 0xb2, 0x00);
1276 +
1277 + return 0;
1278 +}
1279 +
1280 +static int m88ds3103_set_frontend(struct dvb_frontend *fe)
1281 +{
1282 + struct m88ds3103_state *state = fe->demodulator_priv;
1283 + struct dtv_frontend_properties *c = &fe->dtv_property_cache;
1284 +
1285 + int i;
1286 + fe_status_t status;
1287 + u8 lpf_mxdiv, mlpf_max, mlpf_min, nlpf, div4, capCode, changePLL;
1288 + s32 offset_khz, lpf_offset_KHz;
1289 + u16 value, ndiv, N, lpf_coeff;
1290 + u32 f3db, gdiv28, realFreq;
1291 + u8 RFgain;
1292 +
1293 + dprintk("%s() ", __func__);
1294 + dprintk("c frequency = %d\n", c->frequency);
1295 + dprintk("symbol rate = %d\n", c->symbol_rate);
1296 + dprintk("delivery system = %d\n", c->delivery_system);
1297 +
1298 + realFreq = c->frequency;
1299 + lpf_offset_KHz = 0;
1300 + if(c->symbol_rate < 5000000){
1301 + lpf_offset_KHz = FREQ_OFFSET_AT_SMALL_SYM_RATE_KHz;
1302 + realFreq += FREQ_OFFSET_AT_SMALL_SYM_RATE_KHz;
1303 + }
1304 +
1305 + if (state->config->set_ts_params)
1306 + state->config->set_ts_params(fe, 0);
1307 +
1308 + div4 = 0;
1309 + RFgain = 0;
1310 + if(state->tuner_id == TS2022_ID){
1311 + m88ds3103_tuner_writereg(state, 0x10, 0x0a);
1312 + m88ds3103_tuner_writereg(state, 0x11, 0x40);
1313 + if (realFreq < 1103000) {
1314 + m88ds3103_tuner_writereg(state, 0x10, 0x1b);
1315 + div4 = 1;
1316 + ndiv = (realFreq * (6 + 8) * 4)/MT_FE_CRYSTAL_KHZ;
1317 + }else {
1318 + ndiv = (realFreq * (6 + 8) * 2)/MT_FE_CRYSTAL_KHZ;
1319 + }
1320 + ndiv = ndiv + ndiv%2;
1321 + if(ndiv < 4095)
1322 + N = ndiv - 1024;
1323 + else if (ndiv < 6143)
1324 + N = ndiv + 1024;
1325 + else
1326 + N = ndiv + 3072;
1327 +
1328 + m88ds3103_tuner_writereg(state, 0x01, (N & 0x3f00) >> 8);
1329 + }else{
1330 + m88ds3103_tuner_writereg(state, 0x10, 0x00);
1331 + if (realFreq < 1146000){
1332 + m88ds3103_tuner_writereg(state, 0x10, 0x11);
1333 + div4 = 1;
1334 + ndiv = (realFreq * (6 + 8) * 4) / MT_FE_CRYSTAL_KHZ;
1335 + }else{
1336 + m88ds3103_tuner_writereg(state, 0x10, 0x01);
1337 + ndiv = (realFreq * (6 + 8) * 2) / MT_FE_CRYSTAL_KHZ;
1338 + }
1339 + ndiv = ndiv + ndiv%2;
1340 + N = ndiv - 1024;
1341 + m88ds3103_tuner_writereg(state, 0x01, (N>>8)&0x0f);
1342 + }
1343 + /* set pll */
1344 + m88ds3103_tuner_writereg(state, 0x02, N & 0x00ff);
1345 + m88ds3103_tuner_writereg(state, 0x03, 0x06);
1346 + m88ds3103_tuner_writereg(state, 0x51, 0x0f);
1347 + m88ds3103_tuner_writereg(state, 0x51, 0x1f);
1348 + m88ds3103_tuner_writereg(state, 0x50, 0x10);
1349 + m88ds3103_tuner_writereg(state, 0x50, 0x00);
1350 +
1351 + if(state->tuner_id == TS2022_ID){
1352 + if(( realFreq >= 1650000 ) && (realFreq <= 1850000)){
1353 + msleep(5);
1354 + value = m88ds3103_tuner_readreg(state, 0x14);
1355 + value &= 0x7f;
1356 + if(value < 64){
1357 + m88ds3103_tuner_writereg(state, 0x10, 0x82);
1358 + m88ds3103_tuner_writereg(state, 0x11, 0x6f);
1359 +
1360 + m88ds3103_tuner_writereg(state, 0x51, 0x0f);
1361 + m88ds3103_tuner_writereg(state, 0x51, 0x1f);
1362 + m88ds3103_tuner_writereg(state, 0x50, 0x10);
1363 + m88ds3103_tuner_writereg(state, 0x50, 0x00);
1364 + }
1365 + }
1366 + msleep(5);
1367 + value = m88ds3103_tuner_readreg(state, 0x14);
1368 + value &= 0x1f;
1369 +
1370 + if(value > 19){
1371 + value = m88ds3103_tuner_readreg(state, 0x10);
1372 + value &= 0x1d;
1373 + m88ds3103_tuner_writereg(state, 0x10, value);
1374 + }
1375 + }else{
1376 + msleep(5);
1377 + value = m88ds3103_tuner_readreg(state, 0x66);
1378 + changePLL = (((value & 0x80) >> 7) != div4);
1379 +
1380 + if(changePLL){
1381 + m88ds3103_tuner_writereg(state, 0x10, 0x11);
1382 + div4 = 1;
1383 + ndiv = (realFreq * (6 + 8) * 4)/MT_FE_CRYSTAL_KHZ;
1384 + ndiv = ndiv + ndiv%2;
1385 + N = ndiv - 1024;
1386 +
1387 + m88ds3103_tuner_writereg(state, 0x01, (N>>8) & 0x0f);
1388 + m88ds3103_tuner_writereg(state, 0x02, N & 0xff);
1389 +
1390 + m88ds3103_tuner_writereg(state, 0x51, 0x0f);
1391 + m88ds3103_tuner_writereg(state, 0x51, 0x1f);
1392 + m88ds3103_tuner_writereg(state, 0x50, 0x10);
1393 + m88ds3103_tuner_writereg(state, 0x50, 0x00);
1394 + }
1395 + }
1396 + /*set the RF gain*/
1397 + if(state->tuner_id == TS2020_ID)
1398 + m88ds3103_tuner_writereg(state, 0x60, 0x79);
1399 +
1400 + m88ds3103_tuner_writereg(state, 0x51, 0x17);
1401 + m88ds3103_tuner_writereg(state, 0x51, 0x1f);
1402 + m88ds3103_tuner_writereg(state, 0x50, 0x08);
1403 + m88ds3103_tuner_writereg(state, 0x50, 0x00);
1404 + msleep(5);
1405 +
1406 + if(state->tuner_id == TS2020_ID){
1407 + RFgain = m88ds3103_tuner_readreg(state, 0x3d);
1408 + RFgain &= 0x0f;
1409 + if(RFgain < 15){
1410 + if(RFgain < 4)
1411 + RFgain = 0;
1412 + else
1413 + RFgain = RFgain -3;
1414 + value = ((RFgain << 3) | 0x01) & 0x79;
1415 + m88ds3103_tuner_writereg(state, 0x60, value);
1416 + m88ds3103_tuner_writereg(state, 0x51, 0x17);
1417 + m88ds3103_tuner_writereg(state, 0x51, 0x1f);
1418 + m88ds3103_tuner_writereg(state, 0x50, 0x08);
1419 + m88ds3103_tuner_writereg(state, 0x50, 0x00);
1420 + }
1421 + }
1422 +
1423 + /* set the LPF */
1424 + if(state->tuner_id == TS2022_ID){
1425 + m88ds3103_tuner_writereg(state, 0x25, 0x00);
1426 + m88ds3103_tuner_writereg(state, 0x27, 0x70);
1427 + m88ds3103_tuner_writereg(state, 0x41, 0x09);
1428 + m88ds3103_tuner_writereg(state, 0x08, 0x0b);
1429 + }
1430 +
1431 + f3db = ((c->symbol_rate / 1000) *135) / 200 + 2000;
1432 + f3db += lpf_offset_KHz;
1433 + if (f3db < 7000)
1434 + f3db = 7000;
1435 + if (f3db > 40000)
1436 + f3db = 40000;
1437 +
1438 + gdiv28 = (MT_FE_CRYSTAL_KHZ / 1000 * 1694 + 500) / 1000;
1439 + m88ds3103_tuner_writereg(state, 0x04, gdiv28 & 0xff);
1440 + m88ds3103_tuner_writereg(state, 0x51, 0x1b);
1441 + m88ds3103_tuner_writereg(state, 0x51, 0x1f);
1442 + m88ds3103_tuner_writereg(state, 0x50, 0x04);
1443 + m88ds3103_tuner_writereg(state, 0x50, 0x00);
1444 + msleep(5);
1445 +
1446 + value = m88ds3103_tuner_readreg(state, 0x26);
1447 + capCode = value & 0x3f;
1448 + if(state->tuner_id == TS2022_ID){
1449 + m88ds3103_tuner_writereg(state, 0x41, 0x0d);
1450 +
1451 + m88ds3103_tuner_writereg(state, 0x51, 0x1b);
1452 + m88ds3103_tuner_writereg(state, 0x51, 0x1f);
1453 + m88ds3103_tuner_writereg(state, 0x50, 0x04);
1454 + m88ds3103_tuner_writereg(state, 0x50, 0x00);
1455 +
1456 + msleep(2);
1457 +
1458 + value = m88ds3103_tuner_readreg(state, 0x26);
1459 + value &= 0x3f;
1460 + value = (capCode + value) / 2;
1461 + }
1462 + else
1463 + value = capCode;
1464 +
1465 + gdiv28 = gdiv28 * 207 / (value * 2 + 151);
1466 + mlpf_max = gdiv28 * 135 / 100;
1467 + mlpf_min = gdiv28 * 78 / 100;
1468 + if (mlpf_max > 63)
1469 + mlpf_max = 63;
1470 +
1471 + if(state->tuner_id == TS2022_ID)
1472 + lpf_coeff = 3200;
1473 + else
1474 + lpf_coeff = 2766;
1475 +
1476 + nlpf = (f3db * gdiv28 * 2 / lpf_coeff / (MT_FE_CRYSTAL_KHZ / 1000) + 1) / 2 ;
1477 + if (nlpf > 23) nlpf = 23;
1478 + if (nlpf < 1) nlpf = 1;
1479 +
1480 + lpf_mxdiv = (nlpf * (MT_FE_CRYSTAL_KHZ / 1000) * lpf_coeff * 2 / f3db + 1) / 2;
1481 +
1482 + if (lpf_mxdiv < mlpf_min){
1483 + nlpf++;
1484 + lpf_mxdiv = (nlpf * (MT_FE_CRYSTAL_KHZ / 1000) * lpf_coeff * 2 / f3db + 1) / 2;
1485 + }
1486 +
1487 + if (lpf_mxdiv > mlpf_max)
1488 + lpf_mxdiv = mlpf_max;
1489 +
1490 + m88ds3103_tuner_writereg(state, 0x04, lpf_mxdiv);
1491 + m88ds3103_tuner_writereg(state, 0x06, nlpf);
1492 + m88ds3103_tuner_writereg(state, 0x51, 0x1b);
1493 + m88ds3103_tuner_writereg(state, 0x51, 0x1f);
1494 + m88ds3103_tuner_writereg(state, 0x50, 0x04);
1495 + m88ds3103_tuner_writereg(state, 0x50, 0x00);
1496 + msleep(5);
1497 +
1498 + if(state->tuner_id == TS2022_ID){
1499 + msleep(2);
1500 + value = m88ds3103_tuner_readreg(state, 0x26);
1501 + capCode = value & 0x3f;
1502 +
1503 + m88ds3103_tuner_writereg(state, 0x41, 0x09);
1504 +
1505 + m88ds3103_tuner_writereg(state, 0x51, 0x1b);
1506 + m88ds3103_tuner_writereg(state, 0x51, 0x1f);
1507 + m88ds3103_tuner_writereg(state, 0x50, 0x04);
1508 + m88ds3103_tuner_writereg(state, 0x50, 0x00);
1509 +
1510 + msleep(2);
1511 + value = m88ds3103_tuner_readreg(state, 0x26);
1512 + value &= 0x3f;
1513 + value = (capCode + value) / 2;
1514 +
1515 + value = value | 0x80;
1516 + m88ds3103_tuner_writereg(state, 0x25, value);
1517 + m88ds3103_tuner_writereg(state, 0x27, 0x30);
1518 +
1519 + m88ds3103_tuner_writereg(state, 0x08, 0x09);
1520 + }
1521 +
1522 + /* Set the BB gain */
1523 + m88ds3103_tuner_writereg(state, 0x51, 0x1e);
1524 + m88ds3103_tuner_writereg(state, 0x51, 0x1f);
1525 + m88ds3103_tuner_writereg(state, 0x50, 0x01);
1526 + m88ds3103_tuner_writereg(state, 0x50, 0x00);
1527 + if(state->tuner_id == TS2020_ID){
1528 + if(RFgain == 15){
1529 + msleep(40);
1530 + value = m88ds3103_tuner_readreg(state, 0x21);
1531 + value &= 0x0f;
1532 + if(value < 3){
1533 + m88ds3103_tuner_writereg(state, 0x60, 0x61);
1534 + m88ds3103_tuner_writereg(state, 0x51, 0x17);
1535 + m88ds3103_tuner_writereg(state, 0x51, 0x1f);
1536 + m88ds3103_tuner_writereg(state, 0x50, 0x08);
1537 + m88ds3103_tuner_writereg(state, 0x50, 0x00);
1538 + }
1539 + }
1540 + }
1541 + msleep(60);
1542 +
1543 + offset_khz = (ndiv) * MT_FE_CRYSTAL_KHZ
1544 + / (6 + 8) / (div4 + 1) / 2 - realFreq;
1545 +
1546 + m88ds3103_demod_connect(fe, offset_khz+lpf_offset_KHz);
1547 +
1548 + for (i = 0; i < 30 ; i++) {
1549 + m88ds3103_read_status(fe, &status);
1550 + if (status & FE_HAS_LOCK){
1551 + break;
1552 + }
1553 + msleep(20);
1554 + }
1555 +
1556 +#ifdef _AUTO_S2_
1557 + if((status & FE_HAS_LOCK) == 0){
1558 + state->delivery_system = (state->delivery_system == SYS_DVBS) ? SYS_DVBS2 : SYS_DVBS;
1559 + m88ds3103_demod_connect(fe, offset_khz);
1560 +
1561 + for (i = 0; i < 30 ; i++) {
1562 + m88ds3103_read_status(fe, &status);
1563 + if (status & FE_HAS_LOCK){
1564 + break;
1565 + }
1566 + msleep(20);
1567 + }
1568 + }
1569 +#else
1570 + state->delivery_system = c->delivery_system;
1571 +#endif
1572 + if (status & FE_HAS_LOCK){
1573 + if(state->config->ci_mode == 2)
1574 + m88ds3103_set_clock_ratio(state);
1575 + if(state->config->start_ctrl){
1576 + if(state->first_lock == 0){
1577 + state->config->start_ctrl(fe);
1578 + state->first_lock = 1;
1579 + }
1580 + }
1581 + }
1582 +
1583 + return 0;
1584 +}
1585 +
1586 +static int m88ds3103_tune(struct dvb_frontend *fe,
1587 + bool re_tune,
1588 + unsigned int mode_flags,
1589 + unsigned int *delay,
1590 + fe_status_t *status)
1591 +{
1592 + *delay = HZ / 5;
1593 +
1594 + dprintk("%s() ", __func__);
1595 + dprintk("re_tune = %d\n", re_tune);
1596 +
1597 + if (re_tune) {
1598 + int ret = m88ds3103_set_frontend(fe);
1599 + if (ret)
1600 + return ret;
1601 + }
1602 +
1603 + return m88ds3103_read_status(fe, status);
1604 +}
1605 +
1606 +static enum dvbfe_algo m88ds3103_get_algo(struct dvb_frontend *fe)
1607 +{
1608 + return DVBFE_ALGO_HW;
1609 +}
1610 +
1611 + /*
1612 + * Power config will reset and load initial firmware if required
1613 + */
1614 +static int m88ds3103_initilaze(struct dvb_frontend *fe)
1615 +{
1616 + struct m88ds3103_state *state = fe->demodulator_priv;
1617 + int ret;
1618 +
1619 + dprintk("%s()\n", __func__);
1620 + /* hard reset */
1621 + m88ds3103_writereg(state, 0x07, 0x80);
1622 + m88ds3103_writereg(state, 0x07, 0x00);
1623 + msleep(1);
1624 +
1625 + m88ds3103_writereg(state, 0x08, 0x01 | m88ds3103_readreg(state, 0x08));
1626 + msleep(1);
1627 +
1628 + if(state->tuner_id == TS2020_ID){
1629 + /* TS2020 init */
1630 + m88ds3103_tuner_writereg(state, 0x42, 0x73);
1631 + msleep(2);
1632 + m88ds3103_tuner_writereg(state, 0x05, 0x01);
1633 + m88ds3103_tuner_writereg(state, 0x62, 0xb5);
1634 + m88ds3103_tuner_writereg(state, 0x07, 0x02);
1635 + m88ds3103_tuner_writereg(state, 0x08, 0x01);
1636 + }
1637 + else if(state->tuner_id == TS2022_ID){
1638 + /* TS2022 init */
1639 + m88ds3103_tuner_writereg(state, 0x62, 0x6c);
1640 + msleep(2);
1641 + m88ds3103_tuner_writereg(state, 0x42, 0x6c);
1642 + msleep(2);
1643 + m88ds3103_tuner_writereg(state, 0x7d, 0x9d);
1644 + m88ds3103_tuner_writereg(state, 0x7c, 0x9a);
1645 + m88ds3103_tuner_writereg(state, 0x7a, 0x76);
1646 +
1647 + m88ds3103_tuner_writereg(state, 0x3b, 0x01);
1648 + m88ds3103_tuner_writereg(state, 0x63, 0x88);
1649 +
1650 + m88ds3103_tuner_writereg(state, 0x61, 0x85);
1651 + m88ds3103_tuner_writereg(state, 0x22, 0x30);
1652 + m88ds3103_tuner_writereg(state, 0x30, 0x40);
1653 + m88ds3103_tuner_writereg(state, 0x20, 0x23);
1654 + m88ds3103_tuner_writereg(state, 0x24, 0x02);
1655 + m88ds3103_tuner_writereg(state, 0x12, 0xa0);
1656 + }
1657 +
1658 + if(state->demod_id == DS3103_ID){
1659 + m88ds3103_writereg(state, 0x07, 0xe0);
1660 + m88ds3103_writereg(state, 0x07, 0x00);
1661 + msleep(1);
1662 + }
1663 + m88ds3103_writereg(state, 0xb2, 0x01);
1664 +
1665 + /* Load the firmware if required */
1666 + ret = m88ds3103_load_firmware(fe);
1667 + if (ret != 0){
1668 + printk(KERN_ERR "%s: Unable initialize firmware\n", __func__);
1669 + return ret;
1670 + }
1671 + if(state->demod_id == DS3103_ID){
1672 + m88ds3103_writereg(state, 0x4d, 0xfd & m88ds3103_readreg(state, 0x4d));
1673 + m88ds3103_writereg(state, 0x30, 0xef & m88ds3103_readreg(state, 0x30));
1674 + }
1675 +
1676 + return 0;
1677 +}
1678 +
1679 +/*
1680 + * Initialise or wake up device
1681 + */
1682 +static int m88ds3103_initfe(struct dvb_frontend *fe)
1683 +{
1684 + struct m88ds3103_state *state = fe->demodulator_priv;
1685 + u8 val;
1686 +
1687 + dprintk("%s()\n", __func__);
1688 +
1689 + /* 1st step to wake up demod */
1690 + m88ds3103_writereg(state, 0x08, 0x01 | m88ds3103_readreg(state, 0x08));
1691 + m88ds3103_writereg(state, 0x04, 0xfe & m88ds3103_readreg(state, 0x04));
1692 + m88ds3103_writereg(state, 0x23, 0xef & m88ds3103_readreg(state, 0x23));
1693 +
1694 + /* 2nd step to wake up tuner */
1695 + val = m88ds3103_tuner_readreg(state, 0x00) & 0xff;
1696 + if((val & 0x01) == 0){
1697 + m88ds3103_tuner_writereg(state, 0x00, 0x01);
1698 + msleep(50);
1699 + }
1700 + m88ds3103_tuner_writereg(state, 0x00, 0x03);
1701 + msleep(50);
1702 +
1703 + return 0;
1704 +}
1705 +
1706 +/* Put device to sleep */
1707 +static int m88ds3103_sleep(struct dvb_frontend *fe)
1708 +{
1709 + struct m88ds3103_state *state = fe->demodulator_priv;
1710 +
1711 + dprintk("%s()\n", __func__);
1712 +
1713 + /* 1st step to sleep tuner */
1714 + m88ds3103_tuner_writereg(state, 0x00, 0x00);
1715 +
1716 + /* 2nd step to sleep demod */
1717 + m88ds3103_writereg(state, 0x08, 0xfe & m88ds3103_readreg(state, 0x08));
1718 + m88ds3103_writereg(state, 0x04, 0x01 | m88ds3103_readreg(state, 0x04));
1719 + m88ds3103_writereg(state, 0x23, 0x10 | m88ds3103_readreg(state, 0x23));
1720 +
1721 +
1722 + return 0;
1723 +}
1724 +
1725 +static struct dvb_frontend_ops m88ds3103_ops = {
1726 + .delsys = { SYS_DVBS, SYS_DVBS2},
1727 + .info = {
1728 + .name = "Montage DS3103/TS2022",
1729 + .type = FE_QPSK,
1730 + .frequency_min = 950000,
1731 + .frequency_max = 2150000,
1732 + .frequency_stepsize = 1011, /* kHz for QPSK frontends */
1733 + .frequency_tolerance = 5000,
1734 + .symbol_rate_min = 1000000,
1735 + .symbol_rate_max = 45000000,
1736 + .caps = FE_CAN_INVERSION_AUTO |
1737 + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
1738 + FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
1739 + FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
1740 + FE_CAN_2G_MODULATION |
1741 + FE_CAN_QPSK | FE_CAN_RECOVER
1742 + },
1743 +
1744 + .release = m88ds3103_release,
1745 +
1746 + .init = m88ds3103_initfe,
1747 + .sleep = m88ds3103_sleep,
1748 + .read_status = m88ds3103_read_status,
1749 + .read_ber = m88ds3103_read_ber,
1750 + .read_signal_strength = m88ds3103_read_signal_strength,
1751 + .read_snr = m88ds3103_read_snr,
1752 + .read_ucblocks = m88ds3103_read_ucblocks,
1753 + .set_tone = m88ds3103_set_tone,
1754 + .set_voltage = m88ds3103_set_voltage,
1755 + .diseqc_send_master_cmd = m88ds3103_send_diseqc_msg,
1756 + .diseqc_send_burst = m88ds3103_diseqc_send_burst,
1757 + .get_frontend_algo = m88ds3103_get_algo,
1758 + .tune = m88ds3103_tune,
1759 + .set_frontend = m88ds3103_set_frontend,
1760 +};
1761 +
1762 +MODULE_DESCRIPTION("DVB Frontend module for Montage DS3103/TS2022 hardware");
1763 +MODULE_AUTHOR("Max nibble");
1764 +MODULE_LICENSE("GPL");
1765 diff --git a/drivers/media/dvb-frontends/dvbsky_m88ds3103.h b/drivers/media/dvb-frontends/dvbsky_m88ds3103.h
1766 new file mode 100644
1767 index 0000000..e2358d6
1768 --- /dev/null
1769 +++ b/drivers/media/dvb-frontends/dvbsky_m88ds3103.h
1770 @@ -0,0 +1,54 @@
1771 +/*
1772 + Montage Technology M88DS3103/M88TS2022 - DVBS/S2 Satellite demod/tuner driver
1773 +
1774 + This program is free software; you can redistribute it and/or modify
1775 + it under the terms of the GNU General Public License as published by
1776 + the Free Software Foundation; either version 2 of the License, or
1777 + (at your option) any later version.
1778 +
1779 + This program is distributed in the hope that it will be useful,
1780 + but WITHOUT ANY WARRANTY; without even the implied warranty of
1781 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1782 + GNU General Public License for more details.
1783 +
1784 + You should have received a copy of the GNU General Public License
1785 + along with this program; if not, write to the Free Software
1786 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1787 + */
1788 +
1789 +#ifndef DVBSKY_M88DS3103_H
1790 +#define DVBSKY_M88DS3103_H
1791 +
1792 +#include <linux/kconfig.h>
1793 +#include <linux/dvb/frontend.h>
1794 +
1795 +struct dvbsky_m88ds3103_config {
1796 + /* the demodulator's i2c address */
1797 + u8 demod_address;
1798 + u8 ci_mode;
1799 + u8 pin_ctrl;
1800 + u8 ts_mode; /* 0: Parallel, 1: Serial */
1801 + u8 tuner_readstops;
1802 +
1803 + /* Set device param to start dma */
1804 + int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
1805 + /* Start to transfer data */
1806 + int (*start_ctrl)(struct dvb_frontend *fe);
1807 + /* Set LNB voltage */
1808 + int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
1809 +};
1810 +
1811 +#if IS_ENABLED(CONFIG_DVB_DVBSKY_M88DS3103)
1812 +extern struct dvb_frontend *dvbsky_m88ds3103_attach(
1813 + const struct dvbsky_m88ds3103_config *config,
1814 + struct i2c_adapter *i2c);
1815 +#else
1816 +static inline struct dvb_frontend *dvbsky_m88ds3103_attach(
1817 + const struct dvbsky_m88ds3103_config *config,
1818 + struct i2c_adapter *i2c)
1819 +{
1820 + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
1821 + return NULL;
1822 +}
1823 +#endif /* CONFIG_DVB_DVBSKY_M88DS3103 */
1824 +#endif /* DVBSKY_M88DS3103_H */
1825 diff --git a/drivers/media/dvb-frontends/dvbsky_m88ds3103_priv.h b/drivers/media/dvb-frontends/dvbsky_m88ds3103_priv.h
1826 new file mode 100644
1827 index 0000000..9966931
1828 --- /dev/null
1829 +++ b/drivers/media/dvb-frontends/dvbsky_m88ds3103_priv.h
1830 @@ -0,0 +1,403 @@
1831 +/*
1832 + Montage Technology M88DS3103/M88TS2022 - DVBS/S2 Satellite demod/tuner driver
1833 +
1834 + This program is free software; you can redistribute it and/or modify
1835 + it under the terms of the GNU General Public License as published by
1836 + the Free Software Foundation; either version 2 of the License, or
1837 + (at your option) any later version.
1838 +
1839 + This program is distributed in the hope that it will be useful,
1840 + but WITHOUT ANY WARRANTY; without even the implied warranty of
1841 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1842 + GNU General Public License for more details.
1843 +
1844 + You should have received a copy of the GNU General Public License
1845 + along with this program; if not, write to the Free Software
1846 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1847 + */
1848 +
1849 +#ifndef DVBSKY_M88DS3103_PRIV_H
1850 +#define DVBSKY_M88DS3103_PRIV_H
1851 +
1852 +#define FW_DOWN_SIZE 32
1853 +#define FW_DOWN_LOOP (8192/FW_DOWN_SIZE)
1854 +#define DS3103_DEFAULT_FIRMWARE "dvb-fe-ds3103.fw"
1855 +#define DS3000_DEFAULT_FIRMWARE "dvb-fe-ds300x.fw"
1856 +#define MT_FE_MCLK_KHZ 96000 /* in kHz */
1857 +#define MT_FE_CRYSTAL_KHZ 27000 /* in kHz */
1858 +#define FREQ_OFFSET_AT_SMALL_SYM_RATE_KHz 3000
1859 +#define DS3000_ID 0x3000
1860 +#define DS3103_ID 0x3103
1861 +#define TS2020_ID 0x2020
1862 +#define TS2022_ID 0x2022
1863 +#define UNKNOW_ID 0x0000
1864 +
1865 +struct m88ds3103_state {
1866 + struct i2c_adapter *i2c;
1867 + const struct dvbsky_m88ds3103_config *config;
1868 +
1869 + struct dvb_frontend frontend;
1870 +
1871 + u32 preBer;
1872 + u8 skip_fw_load;
1873 + u8 first_lock; /* The first time of signal lock */
1874 + u16 demod_id; /* demod chip type */
1875 + u16 tuner_id; /* tuner chip type */
1876 + fe_delivery_system_t delivery_system;
1877 +};
1878 +
1879 +/* For M88DS3103 demod dvbs mode.*/
1880 +static u8 ds3103_dvbs_init_tab[] = {
1881 + 0x23, 0x07,
1882 + 0x08, 0x03,
1883 + 0x0c, 0x02,
1884 + 0x21, 0x54,
1885 + 0x25, 0x82,
1886 + 0x27, 0x31,
1887 + 0x30, 0x08,
1888 + 0x31, 0x40,
1889 + 0x32, 0x32,
1890 + 0x33, 0x35,
1891 + 0x35, 0xff,
1892 + 0x3a, 0x00,
1893 + 0x37, 0x10,
1894 + 0x38, 0x10,
1895 + 0x39, 0x02,
1896 + 0x42, 0x60,
1897 + 0x4a, 0x80,
1898 + 0x4b, 0x04,
1899 + 0x4d, 0x91,
1900 + 0x5d, 0xc8,
1901 + 0x50, 0x36,
1902 + 0x51, 0x36,
1903 + 0x52, 0x36,
1904 + 0x53, 0x36,
1905 + 0x63, 0x0f,
1906 + 0x64, 0x30,
1907 + 0x65, 0x40,
1908 + 0x68, 0x26,
1909 + 0x69, 0x4c,
1910 + 0x70, 0x20,
1911 + 0x71, 0x70,
1912 + 0x72, 0x04,
1913 + 0x73, 0x00,
1914 + 0x70, 0x40,
1915 + 0x71, 0x70,
1916 + 0x72, 0x04,
1917 + 0x73, 0x00,
1918 + 0x70, 0x60,
1919 + 0x71, 0x70,
1920 + 0x72, 0x04,
1921 + 0x73, 0x00,
1922 + 0x70, 0x80,
1923 + 0x71, 0x70,
1924 + 0x72, 0x04,
1925 + 0x73, 0x00,
1926 + 0x70, 0xa0,
1927 + 0x71, 0x70,
1928 + 0x72, 0x04,
1929 + 0x73, 0x00,
1930 + 0x70, 0x1f,
1931 + 0x76, 0x38,
1932 + 0x77, 0xa6,
1933 + 0x78, 0x0c,
1934 + 0x79, 0x80,
1935 + 0x7f, 0x14,
1936 + 0x7c, 0x00,
1937 + 0xae, 0x82,
1938 + 0x80, 0x64,
1939 + 0x81, 0x66,
1940 + 0x82, 0x44,
1941 + 0x85, 0x04,
1942 + 0xcd, 0xf4,
1943 + 0x90, 0x33,
1944 + 0xa0, 0x44,
1945 + 0xc0, 0x08,
1946 + 0xc3, 0x10,
1947 + 0xc4, 0x08,
1948 + 0xc5, 0xf0,
1949 + 0xc6, 0xff,
1950 + 0xc7, 0x00,
1951 + 0xc8, 0x1a,
1952 + 0xc9, 0x80,
1953 + 0xe0, 0xf8,
1954 + 0xe6, 0x8b,
1955 + 0xd0, 0x40,
1956 + 0xf8, 0x20,
1957 + 0xfa, 0x0f,
1958 + 0x00, 0x00,
1959 + 0xbd, 0x01,
1960 + 0xb8, 0x00,
1961 +};
1962 +/* For M88DS3103 demod dvbs2 mode.*/
1963 +static u8 ds3103_dvbs2_init_tab[] = {
1964 + 0x23, 0x07,
1965 + 0x08, 0x07,
1966 + 0x0c, 0x02,
1967 + 0x21, 0x54,
1968 + 0x25, 0x82,
1969 + 0x27, 0x31,
1970 + 0x30, 0x08,
1971 + 0x32, 0x32,
1972 + 0x33, 0x35,
1973 + 0x35, 0xff,
1974 + 0x3a, 0x00,
1975 + 0x37, 0x10,
1976 + 0x38, 0x10,
1977 + 0x39, 0x02,
1978 + 0x42, 0x60,
1979 + 0x4a, 0x80,
1980 + 0x4b, 0x04,
1981 + 0x4d, 0x91,
1982 + 0x5d, 0xc8,
1983 + 0x50, 0x36,
1984 + 0x51, 0x36,
1985 + 0x52, 0x36,
1986 + 0x53, 0x36,
1987 + 0x63, 0x0f,
1988 + 0x64, 0x10,
1989 + 0x65, 0x20,
1990 + 0x68, 0x46,
1991 + 0x69, 0xcd,
1992 + 0x70, 0x20,
1993 + 0x71, 0x70,
1994 + 0x72, 0x04,
1995 + 0x73, 0x00,
1996 + 0x70, 0x40,
1997 + 0x71, 0x70,
1998 + 0x72, 0x04,
1999 + 0x73, 0x00,
2000 + 0x70, 0x60,
2001 + 0x71, 0x70,
2002 + 0x72, 0x04,
2003 + 0x73, 0x00,
2004 + 0x70, 0x80,
2005 + 0x71, 0x70,
2006 + 0x72, 0x04,
2007 + 0x73, 0x00,
2008 + 0x70, 0xa0,
2009 + 0x71, 0x70,
2010 + 0x72, 0x04,
2011 + 0x73, 0x00,
2012 + 0x70, 0x1f,
2013 + 0x76, 0x38,
2014 + 0x77, 0xa6,
2015 + 0x78, 0x0c,
2016 + 0x79, 0x80,
2017 + 0x7f, 0x14,
2018 + 0x85, 0x08,
2019 + 0xcd, 0xf4,
2020 + 0x90, 0x33,
2021 + 0x86, 0x00,
2022 + 0x87, 0x0f,
2023 + 0x89, 0x00,
2024 + 0x8b, 0x44,
2025 + 0x8c, 0x66,
2026 + 0x9d, 0xc1,
2027 + 0x8a, 0x10,
2028 + 0xad, 0x40,
2029 + 0xa0, 0x44,
2030 + 0xc0, 0x08,
2031 + 0xc1, 0x10,
2032 + 0xc2, 0x08,
2033 + 0xc3, 0x10,
2034 + 0xc4, 0x08,
2035 + 0xc5, 0xf0,
2036 + 0xc6, 0xff,
2037 + 0xc7, 0x00,
2038 + 0xc8, 0x1a,
2039 + 0xc9, 0x80,
2040 + 0xca, 0x23,
2041 + 0xcb, 0x24,
2042 + 0xcc, 0xf4,
2043 + 0xce, 0x74,
2044 + 0x00, 0x00,
2045 + 0xbd, 0x01,
2046 + 0xb8, 0x00,
2047 +};
2048 +
2049 +/* For M88DS3000 demod dvbs mode.*/
2050 +static u8 ds3000_dvbs_init_tab[] = {
2051 + 0x23, 0x05,
2052 + 0x08, 0x03,
2053 + 0x0c, 0x02,
2054 + 0x21, 0x54,
2055 + 0x25, 0x82,
2056 + 0x27, 0x31,
2057 + 0x30, 0x08,
2058 + 0x31, 0x40,
2059 + 0x32, 0x32,
2060 + 0x33, 0x35,
2061 + 0x35, 0xff,
2062 + 0x3a, 0x00,
2063 + 0x37, 0x10,
2064 + 0x38, 0x10,
2065 + 0x39, 0x02,
2066 + 0x42, 0x60,
2067 + 0x4a, 0x40,
2068 + 0x4b, 0x04,
2069 + 0x4d, 0x91,
2070 + 0x5d, 0xc8,
2071 + 0x50, 0x77,
2072 + 0x51, 0x77,
2073 + 0x52, 0x36,
2074 + 0x53, 0x36,
2075 + 0x56, 0x01,
2076 + 0x63, 0x47,
2077 + 0x64, 0x30,
2078 + 0x65, 0x40,
2079 + 0x68, 0x26,
2080 + 0x69, 0x4c,
2081 + 0x70, 0x20,
2082 + 0x71, 0x70,
2083 + 0x72, 0x04,
2084 + 0x73, 0x00,
2085 + 0x70, 0x40,
2086 + 0x71, 0x70,
2087 + 0x72, 0x04,
2088 + 0x73, 0x00,
2089 + 0x70, 0x60,
2090 + 0x71, 0x70,
2091 + 0x72, 0x04,
2092 + 0x73, 0x00,
2093 + 0x70, 0x80,
2094 + 0x71, 0x70,
2095 + 0x72, 0x04,
2096 + 0x73, 0x00,
2097 + 0x70, 0xa0,
2098 + 0x71, 0x70,
2099 + 0x72, 0x04,
2100 + 0x73, 0x00,
2101 + 0x70, 0x1f,
2102 + 0x76, 0x00,
2103 + 0x77, 0xd1,
2104 + 0x78, 0x0c,
2105 + 0x79, 0x80,
2106 + 0x7f, 0x04,
2107 + 0x7c, 0x00,
2108 + 0x80, 0x86,
2109 + 0x81, 0xa6,
2110 + 0x85, 0x04,
2111 + 0xcd, 0xf4,
2112 + 0x90, 0x33,
2113 + 0xa0, 0x44,
2114 + 0xc0, 0x18,
2115 + 0xc3, 0x10,
2116 + 0xc4, 0x08,
2117 + 0xc5, 0x80,
2118 + 0xc6, 0x80,
2119 + 0xc7, 0x0a,
2120 + 0xc8, 0x1a,
2121 + 0xc9, 0x80,
2122 + 0xfe, 0xb6,
2123 + 0xe0, 0xf8,
2124 + 0xe6, 0x8b,
2125 + 0xd0, 0x40,
2126 + 0xf8, 0x20,
2127 + 0xfa, 0x0f,
2128 + 0xad, 0x20,
2129 + 0xae, 0x07,
2130 + 0xb8, 0x00,
2131 +};
2132 +
2133 +/* For M88DS3000 demod dvbs2 mode.*/
2134 +static u8 ds3000_dvbs2_init_tab[] = {
2135 + 0x23, 0x0f,
2136 + 0x08, 0x07,
2137 + 0x0c, 0x02,
2138 + 0x21, 0x54,
2139 + 0x25, 0x82,
2140 + 0x27, 0x31,
2141 + 0x30, 0x08,
2142 + 0x31, 0x32,
2143 + 0x32, 0x32,
2144 + 0x33, 0x35,
2145 + 0x35, 0xff,
2146 + 0x3a, 0x00,
2147 + 0x37, 0x10,
2148 + 0x38, 0x10,
2149 + 0x39, 0x02,
2150 + 0x42, 0x60,
2151 + 0x4a, 0x80,
2152 + 0x4b, 0x04,
2153 + 0x4d, 0x91,
2154 + 0x5d, 0x88,
2155 + 0x50, 0x36,
2156 + 0x51, 0x36,
2157 + 0x52, 0x36,
2158 + 0x53, 0x36,
2159 + 0x63, 0x60,
2160 + 0x64, 0x10,
2161 + 0x65, 0x10,
2162 + 0x68, 0x04,
2163 + 0x69, 0x29,
2164 + 0x70, 0x20,
2165 + 0x71, 0x70,
2166 + 0x72, 0x04,
2167 + 0x73, 0x00,
2168 + 0x70, 0x40,
2169 + 0x71, 0x70,
2170 + 0x72, 0x04,
2171 + 0x73, 0x00,
2172 + 0x70, 0x60,
2173 + 0x71, 0x70,
2174 + 0x72, 0x04,
2175 + 0x73, 0x00,
2176 + 0x70, 0x80,
2177 + 0x71, 0x70,
2178 + 0x72, 0x04,
2179 + 0x73, 0x00,
2180 + 0x70, 0xa0,
2181 + 0x71, 0x70,
2182 + 0x72, 0x04,
2183 + 0x73, 0x00,
2184 + 0x70, 0x1f,
2185 + 0xa0, 0x44,
2186 + 0xc0, 0x08,
2187 + 0xc1, 0x10,
2188 + 0xc2, 0x08,
2189 + 0xc3, 0x10,
2190 + 0xc4, 0x08,
2191 + 0xc5, 0xf0,
2192 + 0xc6, 0xf0,
2193 + 0xc7, 0x0a,
2194 + 0xc8, 0x1a,
2195 + 0xc9, 0x80,
2196 + 0xca, 0x23,
2197 + 0xcb, 0x24,
2198 + 0xce, 0x74,
2199 + 0x56, 0x01,
2200 + 0x90, 0x03,
2201 + 0x76, 0x80,
2202 + 0x77, 0x42,
2203 + 0x78, 0x0a,
2204 + 0x79, 0x80,
2205 + 0xad, 0x40,
2206 + 0xae, 0x07,
2207 + 0x7f, 0xd4,
2208 + 0x7c, 0x00,
2209 + 0x80, 0xa8,
2210 + 0x81, 0xda,
2211 + 0x7c, 0x01,
2212 + 0x80, 0xda,
2213 + 0x81, 0xec,
2214 + 0x7c, 0x02,
2215 + 0x80, 0xca,
2216 + 0x81, 0xeb,
2217 + 0x7c, 0x03,
2218 + 0x80, 0xba,
2219 + 0x81, 0xdb,
2220 + 0x85, 0x08,
2221 + 0x86, 0x00,
2222 + 0x87, 0x02,
2223 + 0x89, 0x80,
2224 + 0x8b, 0x44,
2225 + 0x8c, 0xaa,
2226 + 0x8a, 0x10,
2227 + 0xba, 0x00,
2228 + 0xf5, 0x04,
2229 + 0xd2, 0x32,
2230 + 0xb8, 0x00,
2231 +};
2232 +
2233 +#endif /* DVBSKY_M88DS3103_PRIV_H */
2234 diff --git a/drivers/media/dvb-frontends/m88dc2800.c b/drivers/media/dvb-frontends/m88dc2800.c
2235 new file mode 100644
2236 index 0000000..f876a11
2237 --- /dev/null
2238 +++ b/drivers/media/dvb-frontends/m88dc2800.c
2239 @@ -0,0 +1,2124 @@
2240 +/*
2241 + M88DC2800/M88TC2800 - DVB-C demodulator and tuner from Montage
2242 +
2243 + Copyright (C) 2012 Max nibble<nibble.max@gmail.com>
2244 + Copyright (C) 2011 Montage Technology / www.montage-tech.com
2245 +
2246 + This program is free software; you can redistribute it and/or modify
2247 + it under the terms of the GNU General Public License as published by
2248 + the Free Software Foundation; either version 2 of the License, or
2249 + (at your option) any later version.
2250 +
2251 + This program is distributed in the hope that it will be useful,
2252 + but WITHOUT ANY WARRANTY; without even the implied warranty of
2253 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2254 + GNU General Public License for more details.
2255 +
2256 + You should have received a copy of the GNU General Public License
2257 + along with this program; if not, write to the Free Software
2258 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2259 +*/
2260 +
2261 +#include <linux/delay.h>
2262 +#include <linux/errno.h>
2263 +#include <linux/init.h>
2264 +#include <linux/kernel.h>
2265 +#include <linux/module.h>
2266 +#include <linux/string.h>
2267 +#include <linux/slab.h>
2268 +#include <asm/div64.h>
2269 +#include "dvb_frontend.h"
2270 +#include "m88dc2800.h"
2271 +
2272 +struct m88dc2800_state {
2273 + struct i2c_adapter *i2c;
2274 + const struct m88dc2800_config *config;
2275 + struct dvb_frontend frontend;
2276 + u32 freq;
2277 + u32 ber;
2278 + u32 sym;
2279 + u16 qam;
2280 + u8 inverted;
2281 + u32 xtal;
2282 + /* tuner state */
2283 + u8 tuner_init_OK; /* Tuner initialize status */
2284 + u8 tuner_dev_addr; /* Tuner device address */
2285 + u32 tuner_freq; /* RF frequency to be set, unit: KHz */
2286 + u16 tuner_qam; /* Reserved */
2287 + u16 tuner_mode;
2288 + u8 tuner_bandwidth; /* Bandwidth of the channel, unit: MHz, 6/7/8 */
2289 + u8 tuner_loopthrough; /* Tuner loop through switch, 0/1 */
2290 + u32 tuner_crystal; /* Tuner crystal frequency, unit: KHz */
2291 + u32 tuner_dac; /* Tuner DAC frequency, unit: KHz */
2292 + u16 tuner_mtt; /* Tuner chip version, D1: 0x0d, E0: 0x0e, E1: 0x8e */
2293 + u16 tuner_custom_cfg;
2294 + u32 tuner_version; /* Tuner driver version number */
2295 + u32 tuner_time;
2296 +};
2297 +
2298 +static int debug;
2299 +module_param(debug, int, 0644);
2300 +MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
2301 +
2302 +#define dprintk(args...) \
2303 + do { \
2304 + if (debug) \
2305 + printk(KERN_INFO "m88dc2800: " args); \
2306 + } while (0)
2307 +
2308 +
2309 +static int m88dc2800_i2c_write(struct m88dc2800_state *state, u8 addr,
2310 + u8 * p_data, u8 len)
2311 +{
2312 + struct i2c_msg msg = { .flags = 0 };
2313 +
2314 + msg.addr = addr;
2315 + msg.buf = p_data;
2316 + msg.len = len;
2317 +
2318 + return i2c_transfer(state->i2c, &msg, 1);
2319 +}
2320 +
2321 +static int m88dc2800_i2c_read(struct m88dc2800_state *state, u8 addr,
2322 + u8 * p_data, u8 len)
2323 +{
2324 + struct i2c_msg msg = { .flags = I2C_M_RD };
2325 +
2326 + msg.addr = addr;
2327 + msg.buf = p_data;
2328 + msg.len = len;
2329 +
2330 + return i2c_transfer(state->i2c, &msg, 1);
2331 +}
2332 +
2333 +/*demod register operations.*/
2334 +static int WriteReg(struct m88dc2800_state *state, u8 reg, u8 data)
2335 +{
2336 + u8 buf[] = { reg, data };
2337 + u8 addr = state->config->demod_address;
2338 + int err;
2339 +
2340 + dprintk("%s: write reg 0x%02x, value 0x%02x\n", __func__, reg, data);
2341 +
2342 + err = m88dc2800_i2c_write(state, addr, buf, 2);
2343 +
2344 + if (err != 1) {
2345 + printk(KERN_ERR
2346 + "%s: writereg error(err == %i, reg == 0x%02x,"
2347 + " value == 0x%02x)\n", __func__, err, reg, data);
2348 + return -EIO;
2349 + }
2350 + return 0;
2351 +}
2352 +
2353 +static int ReadReg(struct m88dc2800_state *state, u8 reg)
2354 +{
2355 + int ret;
2356 + u8 b0[] = { reg };
2357 + u8 b1[] = { 0 };
2358 + u8 addr = state->config->demod_address;
2359 +
2360 + ret = m88dc2800_i2c_write(state, addr, b0, 1);
2361 +
2362 + if (ret != 1) {
2363 + printk(KERN_ERR "%s: reg=0x%x (error=%d)\n",
2364 + __func__, reg, ret);
2365 + return -EIO;
2366 + }
2367 +
2368 + ret = m88dc2800_i2c_read(state, addr, b1, 1);
2369 +
2370 + dprintk("%s: read reg 0x%02x, value 0x%02x\n", __func__, reg, b1[0]);
2371 + return b1[0];
2372 +}
2373 +
2374 +static int _mt_fe_tn_set_reg(struct m88dc2800_state *state, u8 reg,
2375 + u8 data)
2376 +{
2377 + int ret;
2378 + u8 buf[2];
2379 + u8 addr = state->tuner_dev_addr;
2380 +
2381 + buf[1] = ReadReg(state, 0x86);
2382 + buf[1] |= 0x80;
2383 + ret = WriteReg(state, 0x86, buf[1]);
2384 +
2385 + buf[0] = reg;
2386 + buf[1] = data;
2387 +
2388 + ret = m88dc2800_i2c_write(state, addr, buf, 2);
2389 + if (ret != 1)
2390 + return -EIO;
2391 + return 0;
2392 +}
2393 +
2394 +static int _mt_fe_tn_get_reg(struct m88dc2800_state *state, u8 reg,
2395 + u8 * p_data)
2396 +{
2397 + int ret;
2398 + u8 buf[2];
2399 + u8 addr = state->tuner_dev_addr;
2400 +
2401 + buf[1] = ReadReg(state, 0x86);
2402 + buf[1] |= 0x80;
2403 + ret = WriteReg(state, 0x86, buf[1]);
2404 +
2405 + buf[0] = reg;
2406 + ret = m88dc2800_i2c_write(state, addr, buf, 1);
2407 +
2408 + msleep(1);
2409 +
2410 + buf[1] = ReadReg(state, 0x86);
2411 + buf[1] |= 0x80;
2412 + ret = WriteReg(state, 0x86, buf[1]);
2413 +
2414 + return m88dc2800_i2c_read(state, addr, p_data, 1);
2415 +}
2416 +
2417 +/* Tuner operation functions.*/
2418 +static int _mt_fe_tn_set_RF_front_tc2800(struct m88dc2800_state *state)
2419 +{
2420 + u32 freq_KHz = state->tuner_freq;
2421 + u8 a, b, c;
2422 + if (state->tuner_mtt == 0xD1) { /* D1 */
2423 + if (freq_KHz <= 123000) {
2424 + if (freq_KHz <= 56000) {
2425 + a = 0x00; b = 0x00; c = 0x00;
2426 + } else if (freq_KHz <= 64000) {
2427 + a = 0x10; b = 0x01; c = 0x08;
2428 + } else if (freq_KHz <= 72000) {
2429 + a = 0x20; b = 0x02; c = 0x10;
2430 + } else if (freq_KHz <= 80000) {
2431 + a = 0x30; b = 0x03; c = 0x18;
2432 + } else if (freq_KHz <= 88000) {
2433 + a = 0x40; b = 0x04; c = 0x20;
2434 + } else if (freq_KHz <= 96000) {
2435 + a = 0x50; b = 0x05; c = 0x28;
2436 + } else if (freq_KHz <= 104000) {
2437 + a = 0x60; b = 0x06; c = 0x30;
2438 + } else {
2439 + a = 0x70; b = 0x07; c = 0x38;
2440 + }
2441 + _mt_fe_tn_set_reg(state, 0x58, 0x9b);
2442 + _mt_fe_tn_set_reg(state, 0x59, a);
2443 + _mt_fe_tn_set_reg(state, 0x5d, b);
2444 + _mt_fe_tn_set_reg(state, 0x5e, c);
2445 + _mt_fe_tn_set_reg(state, 0x5a, 0x75);
2446 + _mt_fe_tn_set_reg(state, 0x73, 0x0c);
2447 + } else { /* if (freq_KHz > 112000) */
2448 + _mt_fe_tn_set_reg(state, 0x58, 0x7b);
2449 + if (freq_KHz <= 304000) {
2450 + if (freq_KHz <= 136000) {
2451 + _mt_fe_tn_set_reg(state, 0x5e, 0x40);
2452 + } else if (freq_KHz <= 160000) {
2453 + _mt_fe_tn_set_reg(state, 0x5e, 0x48);
2454 + } else if (freq_KHz <= 184000) {
2455 + _mt_fe_tn_set_reg(state, 0x5e, 0x50);
2456 + } else if (freq_KHz <= 208000) {
2457 + _mt_fe_tn_set_reg(state, 0x5e, 0x58);
2458 + } else if (freq_KHz <= 232000) {
2459 + _mt_fe_tn_set_reg(state, 0x5e, 0x60);
2460 + } else if (freq_KHz <= 256000) {
2461 + _mt_fe_tn_set_reg(state, 0x5e, 0x68);
2462 + } else if (freq_KHz <= 280000) {
2463 + _mt_fe_tn_set_reg(state, 0x5e, 0x70);
2464 + } else { /* if (freq_KHz <= 304000) */
2465 + _mt_fe_tn_set_reg(state, 0x5e, 0x78);
2466 + }
2467 + if (freq_KHz <= 171000) {
2468 + _mt_fe_tn_set_reg(state, 0x73, 0x08);
2469 + } else if (freq_KHz <= 211000) {
2470 + _mt_fe_tn_set_reg(state, 0x73, 0x0a);
2471 + } else {
2472 + _mt_fe_tn_set_reg(state, 0x73, 0x0e);
2473 + }
2474 + } else { /* if (freq_KHz > 304000) */
2475 + _mt_fe_tn_set_reg(state, 0x5e, 0x88);
2476 + if (freq_KHz <= 400000) {
2477 + _mt_fe_tn_set_reg(state, 0x73, 0x0c);
2478 + } else if (freq_KHz <= 450000) {
2479 + _mt_fe_tn_set_reg(state, 0x73, 0x09);
2480 + } else if (freq_KHz <= 550000) {
2481 + _mt_fe_tn_set_reg(state, 0x73, 0x0e);
2482 + } else if (freq_KHz <= 650000) {
2483 + _mt_fe_tn_set_reg(state, 0x73, 0x0d);
2484 + } else { /*if (freq_KHz > 650000) */
2485 + _mt_fe_tn_set_reg(state, 0x73, 0x0e);
2486 + }
2487 + }
2488 + }
2489 + if (freq_KHz > 800000)
2490 + _mt_fe_tn_set_reg(state, 0x87, 0x24);
2491 + else if (freq_KHz > 700000)
2492 + _mt_fe_tn_set_reg(state, 0x87, 0x34);
2493 + else if (freq_KHz > 500000)
2494 + _mt_fe_tn_set_reg(state, 0x87, 0x44);
2495 + else if (freq_KHz > 300000)
2496 + _mt_fe_tn_set_reg(state, 0x87, 0x43);
2497 + else if (freq_KHz > 220000)
2498 + _mt_fe_tn_set_reg(state, 0x87, 0x54);
2499 + else if (freq_KHz > 110000)
2500 + _mt_fe_tn_set_reg(state, 0x87, 0x14);
2501 + else
2502 + _mt_fe_tn_set_reg(state, 0x87, 0x54);
2503 + if (freq_KHz > 600000)
2504 + _mt_fe_tn_set_reg(state, 0x6a, 0x53);
2505 + else if (freq_KHz > 500000)
2506 + _mt_fe_tn_set_reg(state, 0x6a, 0x57);
2507 + else
2508 + _mt_fe_tn_set_reg(state, 0x6a, 0x59);
2509 + if (freq_KHz < 200000) {
2510 + _mt_fe_tn_set_reg(state, 0x20, 0x5d);
2511 + } else if (freq_KHz < 500000) {
2512 + _mt_fe_tn_set_reg(state, 0x20, 0x7d);
2513 + } else {
2514 + _mt_fe_tn_set_reg(state, 0x20, 0xfd);
2515 + } /* end of 0xD1 */
2516 + } else if (state->tuner_mtt == 0xE1) { /* E1 */
2517 + if (freq_KHz <= 112000) { /* 123MHz */
2518 + if (freq_KHz <= 56000) {
2519 + _mt_fe_tn_set_reg(state, 0x5c, 0x01);
2520 + } else if (freq_KHz <= 64000) {
2521 + _mt_fe_tn_set_reg(state, 0x5c, 0x09);
2522 + } else if (freq_KHz <= 72000) {
2523 + _mt_fe_tn_set_reg(state, 0x5c, 0x11);
2524 + } else if (freq_KHz <= 80000) {
2525 + _mt_fe_tn_set_reg(state, 0x5c, 0x19);
2526 + } else if (freq_KHz <= 88000) {
2527 + _mt_fe_tn_set_reg(state, 0x5c, 0x21);
2528 + } else if (freq_KHz <= 96000) {
2529 + _mt_fe_tn_set_reg(state, 0x5c, 0x29);
2530 + } else if (freq_KHz <= 104000) {
2531 + _mt_fe_tn_set_reg(state, 0x5c, 0x31);
2532 + } else { /* if (freq_KHz <= 112000) */
2533 + _mt_fe_tn_set_reg(state, 0x5c, 0x39);
2534 + }
2535 + _mt_fe_tn_set_reg(state, 0x5b, 0x30);
2536 + } else { /* if (freq_KHz > 112000) */
2537 + if (freq_KHz <= 304000) {
2538 + if (freq_KHz <= 136000) {
2539 + _mt_fe_tn_set_reg(state, 0x5c, 0x41);
2540 + } else if (freq_KHz <= 160000) {
2541 + _mt_fe_tn_set_reg(state, 0x5c, 0x49);
2542 + } else if (freq_KHz <= 184000) {
2543 + _mt_fe_tn_set_reg(state, 0x5c, 0x51);
2544 + } else if (freq_KHz <= 208000) {
2545 + _mt_fe_tn_set_reg(state, 0x5c, 0x59);
2546 + } else if (freq_KHz <= 232000) {
2547 + _mt_fe_tn_set_reg(state, 0x5c, 0x61);
2548 + } else if (freq_KHz <= 256000) {
2549 + _mt_fe_tn_set_reg(state, 0x5c, 0x69);
2550 + } else if (freq_KHz <= 280000) {
2551 + _mt_fe_tn_set_reg(state, 0x5c, 0x71);
2552 + } else { /* if (freq_KHz <= 304000) */
2553 + _mt_fe_tn_set_reg(state, 0x5c, 0x79);
2554 + }
2555 + if (freq_KHz <= 150000) {
2556 + _mt_fe_tn_set_reg(state, 0x5b, 0x28);
2557 + } else if (freq_KHz <= 256000) {
2558 + _mt_fe_tn_set_reg(state, 0x5b, 0x29);
2559 + } else {
2560 + _mt_fe_tn_set_reg(state, 0x5b, 0x2a);
2561 + }
2562 + } else { /* if (freq_KHz > 304000) */
2563 + if (freq_KHz <= 400000) {
2564 + _mt_fe_tn_set_reg(state, 0x5c, 0x89);
2565 + } else if (freq_KHz <= 450000) {
2566 + _mt_fe_tn_set_reg(state, 0x5c, 0x91);
2567 + } else if (freq_KHz <= 650000) {
2568 + _mt_fe_tn_set_reg(state, 0x5c, 0x98);
2569 + } else if (freq_KHz <= 850000) {
2570 + _mt_fe_tn_set_reg(state, 0x5c, 0xa0);
2571 + } else {
2572 + _mt_fe_tn_set_reg(state, 0x5c, 0xa8);
2573 + }
2574 + _mt_fe_tn_set_reg(state, 0x5b, 0x08);
2575 + }
2576 + }
2577 + } /* end of 0xE1 */
2578 + return 0;
2579 +}
2580 +
2581 +static int _mt_fe_tn_cali_PLL_tc2800(struct m88dc2800_state *state,
2582 + u32 freq_KHz,
2583 + u32 cali_freq_thres_div2,
2584 + u32 cali_freq_thres_div3r,
2585 + u32 cali_freq_thres_div3)
2586 +{
2587 + s32 N, F, MUL;
2588 + u8 buf, tmp, tmp2;
2589 + s32 M;
2590 + const s32 crystal_KHz = state->tuner_crystal;
2591 + if (state->tuner_mtt == 0xD1) {
2592 + M = state->tuner_crystal / 4000;
2593 + if (freq_KHz > cali_freq_thres_div2) {
2594 + MUL = 4;
2595 + tmp = 2;
2596 + } else if (freq_KHz > 300000) {
2597 + MUL = 8;
2598 + tmp = 3;
2599 + } else if (freq_KHz > (cali_freq_thres_div2 / 2)) {
2600 + MUL = 8;
2601 + tmp = 4;
2602 + } else if (freq_KHz > (cali_freq_thres_div2 / 4)) {
2603 + MUL = 16;
2604 + tmp = 5;
2605 + } else if (freq_KHz > (cali_freq_thres_div2 / 8)) {
2606 + MUL = 32;
2607 + tmp = 6;
2608 + } else if (freq_KHz > (cali_freq_thres_div2 / 16)) {
2609 + MUL = 64;
2610 + tmp = 7;
2611 + } else { /* invalid */
2612 + MUL = 0;
2613 + tmp = 0;
2614 + return 1;
2615 + }
2616 + } else if (state->tuner_mtt == 0xE1) {
2617 + M = state->tuner_crystal / 1000;
2618 + _mt_fe_tn_set_reg(state, 0x30, 0xff);
2619 + _mt_fe_tn_set_reg(state, 0x32, 0xe0);
2620 + _mt_fe_tn_set_reg(state, 0x33, 0x86);
2621 + _mt_fe_tn_set_reg(state, 0x37, 0x70);
2622 + _mt_fe_tn_set_reg(state, 0x38, 0x20);
2623 + _mt_fe_tn_set_reg(state, 0x39, 0x18);
2624 + _mt_fe_tn_set_reg(state, 0x89, 0x83);
2625 + if (freq_KHz > cali_freq_thres_div2) {
2626 + M = M / 4;
2627 + MUL = 4;
2628 + tmp = 2;
2629 + tmp2 = M + 16; /* 48 */
2630 + } else if (freq_KHz > cali_freq_thres_div3r) {
2631 + M = M / 3;
2632 + MUL = 6;
2633 + tmp = 2;
2634 + tmp2 = M + 32; /* 32 */
2635 + } else if (freq_KHz > cali_freq_thres_div3) {
2636 + M = M / 3;
2637 + MUL = 6;
2638 + tmp = 2;
2639 + tmp2 = M; /* 16 */
2640 + } else if (freq_KHz > 304000) {
2641 + M = M / 4;
2642 + MUL = 8;
2643 + tmp = 3;
2644 + tmp2 = M + 16; /* 48 */
2645 + } else if (freq_KHz > (cali_freq_thres_div2 / 2)) {
2646 + M = M / 4;
2647 + MUL = 8;
2648 + tmp = 4;
2649 + tmp2 = M + 16; /* 48 */
2650 + } else if (freq_KHz > (cali_freq_thres_div3r / 2)) {
2651 + M = M / 3;
2652 + MUL = 12;
2653 + tmp = 4;
2654 + tmp2 = M + 32; /* 32 */
2655 + } else if (freq_KHz > (cali_freq_thres_div3 / 2)) {
2656 + M = M / 3;
2657 + MUL = 12;
2658 + tmp = 4;
2659 + tmp2 = M; /* 16 */
2660 + } else if (freq_KHz > (cali_freq_thres_div2 / 4)) {
2661 + M = M / 4;
2662 + MUL = 16;
2663 + tmp = 5;
2664 + tmp2 = M + 16; /* 48 */
2665 + } else if (freq_KHz > (cali_freq_thres_div3r / 4)) {
2666 + M = M / 3;
2667 + MUL = 24;
2668 + tmp = 5;
2669 + tmp2 = M + 32; /* 32 */
2670 + } else if (freq_KHz > (cali_freq_thres_div3 / 4)) {
2671 + M = M / 3;
2672 + MUL = 24;
2673 + tmp = 5;
2674 + tmp2 = M; /* 16 */
2675 + } else if (freq_KHz > (cali_freq_thres_div2 / 8)) {
2676 + M = M / 4;
2677 + MUL = 32;
2678 + tmp = 6;
2679 + tmp2 = M + 16; /* 48 */
2680 + } else if (freq_KHz > (cali_freq_thres_div3r / 8)) {
2681 + M = M / 3;
2682 + MUL = 48;
2683 + tmp = 6;
2684 + tmp2 = M + 32; /* 32 */
2685 + } else if (freq_KHz > (cali_freq_thres_div3 / 8)) {
2686 + M = M / 3;
2687 + MUL = 48;
2688 + tmp = 6;
2689 + tmp2 = M; /* 16 */
2690 + } else if (freq_KHz > (cali_freq_thres_div2 / 16)) {
2691 + M = M / 4;
2692 + MUL = 64;
2693 + tmp = 7;
2694 + tmp2 = M + 16; /* 48 */
2695 + } else if (freq_KHz > (cali_freq_thres_div3r / 16)) {
2696 + M = M / 3;
2697 + MUL = 96;
2698 + tmp = 7;
2699 + tmp2 = M + 32; /* 32 */
2700 + } else if (freq_KHz > (cali_freq_thres_div3 / 16)) {
2701 + M = M / 3;
2702 + MUL = 96;
2703 + tmp = 7;
2704 + tmp2 = M; /* 16 */
2705 + } else { /* invalid */
2706 + M = M / 4;
2707 + MUL = 0;
2708 + tmp = 0;
2709 + tmp2 = 48;
2710 + return 1;
2711 + }
2712 + if (freq_KHz == 291000) {
2713 + M = state->tuner_crystal / 1000 / 3;
2714 + MUL = 12;
2715 + tmp = 4;
2716 + tmp2 = M + 32; /* 32 */
2717 + }
2718 + /*
2719 + if (freq_KHz == 578000) {
2720 + M = state->tuner_crystal / 1000 / 4;
2721 + MUL = 4;
2722 + tmp = 2;
2723 + tmp2 = M + 16; // 48
2724 + }
2725 + */
2726 + if (freq_KHz == 690000) {
2727 + M = state->tuner_crystal / 1000 / 3;
2728 + MUL = 4;
2729 + tmp = 2;
2730 + tmp2 = M + 16; /* 48 */
2731 + }
2732 + _mt_fe_tn_get_reg(state, 0x33, &buf);
2733 + buf &= 0xc0;
2734 + buf += tmp2;
2735 + _mt_fe_tn_set_reg(state, 0x33, buf);
2736 + } else {
2737 + return 1;
2738 + }
2739 + _mt_fe_tn_get_reg(state, 0x39, &buf);
2740 + buf &= 0xf8;
2741 + buf += tmp;
2742 + _mt_fe_tn_set_reg(state, 0x39, buf);
2743 + N = (freq_KHz * MUL * M / crystal_KHz) / 2 * 2 - 256;
2744 + buf = (N >> 8) & 0xcf;
2745 + if (state->tuner_mtt == 0xE1) {
2746 + buf |= 0x30;
2747 + }
2748 + _mt_fe_tn_set_reg(state, 0x34, buf);
2749 + buf = N & 0xff;
2750 + _mt_fe_tn_set_reg(state, 0x35, buf);
2751 + F = ((freq_KHz * MUL * M / (crystal_KHz / 1000) / 2) -
2752 + (freq_KHz * MUL * M / crystal_KHz / 2 * 1000)) * 64 / 1000;
2753 + buf = F & 0xff;
2754 + _mt_fe_tn_set_reg(state, 0x36, buf);
2755 + if (F == 0) {
2756 + if (state->tuner_mtt == 0xD1) {
2757 + _mt_fe_tn_set_reg(state, 0x3d, 0xca);
2758 + } else if (state->tuner_mtt == 0xE1) {
2759 + _mt_fe_tn_set_reg(state, 0x3d, 0xfe);
2760 + } else {
2761 + return 1;
2762 + }
2763 + _mt_fe_tn_set_reg(state, 0x3e, 0x9c);
2764 + _mt_fe_tn_set_reg(state, 0x3f, 0x34);
2765 + }
2766 + if (F > 0) {
2767 + if (state->tuner_mtt == 0xD1) {
2768 + if ((F == 32) || (F == 16) || (F == 48)) {
2769 + _mt_fe_tn_set_reg(state, 0x3e, 0xa4);
2770 + _mt_fe_tn_set_reg(state, 0x3d, 0x4a);
2771 + _mt_fe_tn_set_reg(state, 0x3f, 0x36);
2772 + } else {
2773 + _mt_fe_tn_set_reg(state, 0x3e, 0xa4);
2774 + _mt_fe_tn_set_reg(state, 0x3d, 0x4a);
2775 + _mt_fe_tn_set_reg(state, 0x3f, 0x36);
2776 + }
2777 + } else if (state->tuner_mtt == 0xE1) {
2778 + _mt_fe_tn_set_reg(state, 0x3e, 0xa4);
2779 + _mt_fe_tn_set_reg(state, 0x3d, 0x7e);
2780 + _mt_fe_tn_set_reg(state, 0x3f, 0x36);
2781 + _mt_fe_tn_set_reg(state, 0x89, 0x84);
2782 + _mt_fe_tn_get_reg(state, 0x39, &buf);
2783 + buf = buf & 0x1f;
2784 + _mt_fe_tn_set_reg(state, 0x39, buf);
2785 + _mt_fe_tn_get_reg(state, 0x32, &buf);
2786 + buf = buf | 0x02;
2787 + _mt_fe_tn_set_reg(state, 0x32, buf);
2788 + } else {
2789 + return 1;
2790 + }
2791 + }
2792 + _mt_fe_tn_set_reg(state, 0x41, 0x00);
2793 + if (state->tuner_mtt == 0xD1) {
2794 + msleep(5);
2795 + } else if (state->tuner_mtt == 0xE1) {
2796 + msleep(2);
2797 + } else {
2798 + return 1;
2799 + }
2800 + _mt_fe_tn_set_reg(state, 0x41, 0x02);
2801 + _mt_fe_tn_set_reg(state, 0x30, 0x7f);
2802 + _mt_fe_tn_set_reg(state, 0x30, 0xff);
2803 + _mt_fe_tn_set_reg(state, 0x31, 0x80);
2804 + _mt_fe_tn_set_reg(state, 0x31, 0x00);
2805 +
2806 + return 0;
2807 +}
2808 +
2809 +static int _mt_fe_tn_set_PLL_freq_tc2800(struct m88dc2800_state *state)
2810 +{
2811 + u8 buf, buf1;
2812 + u32 freq_thres_div2_KHz, freq_thres_div3r_KHz,
2813 + freq_thres_div3_KHz;
2814 + const u32 freq_KHz = state->tuner_freq;
2815 + if (state->tuner_mtt == 0xD1) {
2816 + _mt_fe_tn_set_reg(state, 0x32, 0xe1);
2817 + _mt_fe_tn_set_reg(state, 0x33, 0xa6);
2818 + _mt_fe_tn_set_reg(state, 0x37, 0x7f);
2819 + _mt_fe_tn_set_reg(state, 0x38, 0x20);
2820 + _mt_fe_tn_set_reg(state, 0x39, 0x18);
2821 + _mt_fe_tn_set_reg(state, 0x40, 0x40);
2822 + freq_thres_div2_KHz = 520000;
2823 + _mt_fe_tn_cali_PLL_tc2800(state, freq_KHz,
2824 + freq_thres_div2_KHz, 0, 0);
2825 + msleep(5);
2826 + _mt_fe_tn_get_reg(state, 0x3a, &buf);
2827 + buf1 = buf;
2828 + buf = buf & 0x03;
2829 + buf1 = buf1 & 0x01;
2830 + if ((buf1 == 0) || (buf == 3)) {
2831 + freq_thres_div2_KHz = 420000;
2832 + _mt_fe_tn_cali_PLL_tc2800(state, freq_KHz,
2833 + freq_thres_div2_KHz, 0,
2834 + 0);
2835 + msleep(5);
2836 + _mt_fe_tn_get_reg(state, 0x3a, &buf);
2837 + buf = buf & 0x07;
2838 + if (buf == 5) {
2839 + freq_thres_div2_KHz = 520000;
2840 + _mt_fe_tn_cali_PLL_tc2800(state, freq_KHz,
2841 + freq_thres_div2_KHz,
2842 + 0, 0);
2843 + msleep(5);
2844 + }
2845 + }
2846 + _mt_fe_tn_get_reg(state, 0x38, &buf);
2847 + _mt_fe_tn_set_reg(state, 0x38, buf);
2848 + _mt_fe_tn_get_reg(state, 0x32, &buf);
2849 + buf = buf | 0x10;
2850 + _mt_fe_tn_set_reg(state, 0x32, buf);
2851 + _mt_fe_tn_set_reg(state, 0x30, 0x7f);
2852 + _mt_fe_tn_set_reg(state, 0x30, 0xff);
2853 + _mt_fe_tn_get_reg(state, 0x32, &buf);
2854 + buf = buf & 0xdf;
2855 + _mt_fe_tn_set_reg(state, 0x32, buf);
2856 + _mt_fe_tn_set_reg(state, 0x40, 0x0);
2857 + _mt_fe_tn_set_reg(state, 0x30, 0x7f);
2858 + _mt_fe_tn_set_reg(state, 0x30, 0xff);
2859 + _mt_fe_tn_set_reg(state, 0x31, 0x80);
2860 + _mt_fe_tn_set_reg(state, 0x31, 0x00);
2861 + msleep(5);
2862 + _mt_fe_tn_get_reg(state, 0x39, &buf);
2863 + buf = buf >> 5;
2864 + if (buf < 5) {
2865 + _mt_fe_tn_get_reg(state, 0x39, &buf);
2866 + buf = buf | 0xa0;
2867 + buf = buf & 0xbf;
2868 + _mt_fe_tn_set_reg(state, 0x39, buf);
2869 + _mt_fe_tn_get_reg(state, 0x32, &buf);
2870 + buf = buf | 0x02;
2871 + _mt_fe_tn_set_reg(state, 0x32, buf);
2872 + }
2873 + _mt_fe_tn_get_reg(state, 0x37, &buf);
2874 + if (buf > 0x70) {
2875 + buf = 0x7f;
2876 + _mt_fe_tn_set_reg(state, 0x40, 0x40);
2877 + }
2878 + _mt_fe_tn_set_reg(state, 0x37, buf);
2879 + _mt_fe_tn_get_reg(state, 0x38, &buf);
2880 + if (buf < 0x0f) {
2881 + buf = (buf & 0x0f) << 2;
2882 + buf = buf + 0x0f;
2883 + _mt_fe_tn_set_reg(state, 0x37, buf);
2884 + } else if (buf < 0x1f) {
2885 + buf = buf + 0x0f;
2886 + _mt_fe_tn_set_reg(state, 0x37, buf);
2887 + }
2888 + _mt_fe_tn_get_reg(state, 0x32, &buf);
2889 + buf = (buf | 0x20) & 0xef;
2890 + _mt_fe_tn_set_reg(state, 0x32, buf);
2891 + _mt_fe_tn_set_reg(state, 0x41, 0x00);
2892 + msleep(5);
2893 + _mt_fe_tn_set_reg(state, 0x41, 0x02);
2894 + } else if (state->tuner_mtt == 0xE1) {
2895 + freq_thres_div2_KHz = 580000;
2896 + freq_thres_div3r_KHz = 500000;
2897 + freq_thres_div3_KHz = 440000;
2898 + _mt_fe_tn_cali_PLL_tc2800(state, freq_KHz,
2899 + freq_thres_div2_KHz,
2900 + freq_thres_div3r_KHz,
2901 + freq_thres_div3_KHz);
2902 + msleep(3);
2903 + _mt_fe_tn_get_reg(state, 0x38, &buf);
2904 + _mt_fe_tn_set_reg(state, 0x38, buf);
2905 + _mt_fe_tn_set_reg(state, 0x30, 0x7f);
2906 + _mt_fe_tn_set_reg(state, 0x30, 0xff);
2907 + _mt_fe_tn_set_reg(state, 0x31, 0x80);
2908 + _mt_fe_tn_set_reg(state, 0x31, 0x00);
2909 + msleep(3);
2910 + _mt_fe_tn_get_reg(state, 0x38, &buf);
2911 + _mt_fe_tn_set_reg(state, 0x38, buf);
2912 + _mt_fe_tn_get_reg(state, 0x32, &buf);
2913 + buf = buf | 0x10;
2914 + _mt_fe_tn_set_reg(state, 0x32, buf);
2915 + _mt_fe_tn_set_reg(state, 0x30, 0x7f);
2916 + _mt_fe_tn_set_reg(state, 0x30, 0xff);
2917 + _mt_fe_tn_get_reg(state, 0x32, &buf);
2918 + buf = buf & 0xdf;
2919 + _mt_fe_tn_set_reg(state, 0x32, buf);
2920 + _mt_fe_tn_set_reg(state, 0x31, 0x80);
2921 + _mt_fe_tn_set_reg(state, 0x31, 0x00);
2922 + msleep(3);
2923 + _mt_fe_tn_get_reg(state, 0x37, &buf);
2924 + _mt_fe_tn_set_reg(state, 0x37, buf);
2925 + /*
2926 + if ((freq_KHz == 802000) || (freq_KHz == 826000)) {
2927 + _mt_fe_tn_set_reg(state, 0x37, 0x5e);
2928 + }
2929 + */
2930 + _mt_fe_tn_get_reg(state, 0x32, &buf);
2931 + buf = (buf & 0xef) | 0x30;
2932 + _mt_fe_tn_set_reg(state, 0x32, buf);
2933 + _mt_fe_tn_set_reg(state, 0x41, 0x00);
2934 + msleep(2);
2935 + _mt_fe_tn_set_reg(state, 0x41, 0x02);
2936 + } else {
2937 + return 1;
2938 + }
2939 + return 0;
2940 +}
2941 +
2942 +static int _mt_fe_tn_set_BB_tc2800(struct m88dc2800_state *state)
2943 +{
2944 + return 0;
2945 +}
2946 +
2947 + static int _mt_fe_tn_set_appendix_tc2800(struct m88dc2800_state *state)
2948 +
2949 +{
2950 + u8 buf;
2951 + const u32 freq_KHz = state->tuner_freq;
2952 + if (state->tuner_mtt == 0xD1) {
2953 + if ((freq_KHz == 123000) || (freq_KHz == 147000) ||
2954 + (freq_KHz == 171000) || (freq_KHz == 195000)) {
2955 + _mt_fe_tn_set_reg(state, 0x20, 0x1b);
2956 + }
2957 + if ((freq_KHz == 371000) || (freq_KHz == 419000) ||
2958 + (freq_KHz == 610000) || (freq_KHz == 730000) ||
2959 + (freq_KHz == 754000) || (freq_KHz == 826000)) {
2960 + _mt_fe_tn_get_reg(state, 0x0d, &buf);
2961 + _mt_fe_tn_set_reg(state, 0x0d, (u8) (buf + 1));
2962 + }
2963 + if ((freq_KHz == 522000) || (freq_KHz == 578000) ||
2964 + (freq_KHz == 634000) || (freq_KHz == 690000) ||
2965 + (freq_KHz == 834000)) {
2966 + _mt_fe_tn_get_reg(state, 0x0d, &buf);
2967 + _mt_fe_tn_set_reg(state, 0x0d, (u8) (buf - 1));
2968 + }
2969 + } else if (state->tuner_mtt == 0xE1) {
2970 + _mt_fe_tn_set_reg(state, 0x20, 0xfc);
2971 + if (freq_KHz == 123000 || freq_KHz == 147000 ||
2972 + freq_KHz == 171000 || freq_KHz == 195000 ||
2973 + freq_KHz == 219000 || freq_KHz == 267000 ||
2974 + freq_KHz == 291000 || freq_KHz == 339000 ||
2975 + freq_KHz == 387000 || freq_KHz == 435000 ||
2976 + freq_KHz == 482000 || freq_KHz == 530000 ||
2977 + freq_KHz == 722000 ||
2978 + (state->tuner_custom_cfg == 1 && freq_KHz == 315000)) {
2979 + _mt_fe_tn_set_reg(state, 0x20, 0x5c);
2980 + }
2981 + }
2982 + return 0;
2983 +}
2984 +
2985 + static int _mt_fe_tn_set_DAC_tc2800(struct m88dc2800_state *state)
2986 +{
2987 + u8 buf, tempnumber;
2988 + s32 N;
2989 + s32 f1f2number, f1, f2, delta1, Totalnum1;
2990 + s32 cntT, cntin, NCOI, z0, z1, z2, tmp;
2991 + u32 fc, fadc, fsd, f2d;
2992 + u32 FreqTrue108_Hz;
2993 + s32 M = state->tuner_crystal / 4000;
2994 + /* const u8 bandwidth = state->tuner_bandwidth; */
2995 + const u16 DAC_fre = 108;
2996 + const u32 crystal_KHz = state->tuner_crystal;
2997 + const u32 DACFreq_KHz = state->tuner_dac;
2998 + const u32 freq_KHz = state->tuner_freq;
2999 +
3000 + if (state->tuner_mtt == 0xE1) {
3001 + _mt_fe_tn_get_reg(state, 0x33, &buf);
3002 + M = buf & 0x0f;
3003 + if (M == 0)
3004 + M = 6;
3005 + }
3006 + _mt_fe_tn_get_reg(state, 0x34, &buf);
3007 + N = buf & 0x07;
3008 + _mt_fe_tn_get_reg(state, 0x35, &buf);
3009 + N = (N << 8) + buf;
3010 + buf = ((N + 256) * crystal_KHz / M / DAC_fre + 500) / 1000;
3011 + if (state->tuner_mtt == 0xE1) {
3012 + _mt_fe_tn_set_appendix_tc2800(state);
3013 + if (freq_KHz == 187000 || freq_KHz == 195000 ||
3014 + freq_KHz == 131000 || freq_KHz == 211000 ||
3015 + freq_KHz == 219000 || freq_KHz == 227000 ||
3016 + freq_KHz == 267000 || freq_KHz == 299000 ||
3017 + freq_KHz == 347000 || freq_KHz == 363000 ||
3018 + freq_KHz == 395000 || freq_KHz == 403000 ||
3019 + freq_KHz == 435000 || freq_KHz == 482000 ||
3020 + freq_KHz == 474000 || freq_KHz == 490000 ||
3021 + freq_KHz == 610000 || freq_KHz == 642000 ||
3022 + freq_KHz == 666000 || freq_KHz == 722000 ||
3023 + freq_KHz == 754000 ||
3024 + ((freq_KHz == 379000 || freq_KHz == 467000 ||
3025 + freq_KHz == 762000) && state->tuner_custom_cfg != 1)) {
3026 + buf = buf + 1;
3027 + }
3028 + if (freq_KHz == 123000 || freq_KHz == 139000 ||
3029 + freq_KHz == 147000 || freq_KHz == 171000 ||
3030 + freq_KHz == 179000 || freq_KHz == 203000 ||
3031 + freq_KHz == 235000 || freq_KHz == 251000 ||
3032 + freq_KHz == 259000 || freq_KHz == 283000 ||
3033 + freq_KHz == 331000 || freq_KHz == 363000 ||
3034 + freq_KHz == 371000 || freq_KHz == 387000 ||
3035 + freq_KHz == 411000 || freq_KHz == 427000 ||
3036 + freq_KHz == 443000 || freq_KHz == 451000 ||
3037 + freq_KHz == 459000 || freq_KHz == 506000 ||
3038 + freq_KHz == 514000 || freq_KHz == 538000 ||
3039 + freq_KHz == 546000 || freq_KHz == 554000 ||
3040 + freq_KHz == 562000 || freq_KHz == 570000 ||
3041 + freq_KHz == 578000 || freq_KHz == 602000 ||
3042 + freq_KHz == 626000 || freq_KHz == 658000 ||
3043 + freq_KHz == 690000 || freq_KHz == 714000 ||
3044 + freq_KHz == 746000 || freq_KHz == 522000 ||
3045 + freq_KHz == 826000 || freq_KHz == 155000 ||
3046 + freq_KHz == 530000 ||
3047 + ((freq_KHz == 275000 || freq_KHz == 355000) &&
3048 + state->tuner_custom_cfg != 1) ||
3049 + ((freq_KHz == 467000 || freq_KHz == 762000 ||
3050 + freq_KHz == 778000 || freq_KHz == 818000) &&
3051 + state->tuner_custom_cfg == 1)) {
3052 + buf = buf - 1;
3053 + }
3054 + }
3055 + _mt_fe_tn_set_reg(state, 0x0e, buf);
3056 + _mt_fe_tn_set_reg(state, 0x0d, buf);
3057 + f1f2number =
3058 + (((DACFreq_KHz * M * buf) / crystal_KHz) << 16) / (N + 256) +
3059 + (((DACFreq_KHz * M * buf) % crystal_KHz) << 16) / ((N + 256) *
3060 + crystal_KHz);
3061 + _mt_fe_tn_set_reg(state, 0xf1, (f1f2number & 0xff00) >> 8);
3062 + _mt_fe_tn_set_reg(state, 0xf2, f1f2number & 0x00ff);
3063 + FreqTrue108_Hz =
3064 + (N + 256) * crystal_KHz / (M * buf) * 1000 +
3065 + (((N + 256) * crystal_KHz) % (M * buf)) * 1000 / (M * buf);
3066 + f1 = 4096;
3067 + fc = FreqTrue108_Hz;
3068 + fadc = fc / 4;
3069 + fsd = 27000000;
3070 + f2d = state->tuner_bandwidth * 1000 / 2 - 150;
3071 + f2 = (fsd / 250) * f2d / ((fc + 500) / 1000);
3072 + delta1 = ((f1 - f2) << 15) / f2;
3073 + Totalnum1 = ((f1 - f2) << 15) - delta1 * f2;
3074 + cntT = f2;
3075 + cntin = Totalnum1;
3076 + NCOI = delta1;
3077 + z0 = cntin;
3078 + z1 = cntT;
3079 + z2 = NCOI;
3080 + tempnumber = (z0 & 0xff00) >> 8;
3081 + _mt_fe_tn_set_reg(state, 0xc9, (u8) (tempnumber & 0x0f));
3082 + tempnumber = (z0 & 0xff);
3083 + _mt_fe_tn_set_reg(state, 0xca, tempnumber);
3084 + tempnumber = (z1 & 0xff00) >> 8;
3085 + _mt_fe_tn_set_reg(state, 0xcb, tempnumber);
3086 + tempnumber = (z1 & 0xff);
3087 + _mt_fe_tn_set_reg(state, 0xcc, tempnumber);
3088 + tempnumber = (z2 & 0xff00) >> 8;
3089 + _mt_fe_tn_set_reg(state, 0xcd, tempnumber);
3090 + tempnumber = (z2 & 0xff);
3091 + _mt_fe_tn_set_reg(state, 0xce, tempnumber);
3092 + tmp = f1;
3093 + f1 = f2;
3094 + f2 = tmp / 2;
3095 + delta1 = ((f1 - f2) << 15) / f2;
3096 + Totalnum1 = ((f1 - f2) << 15) - delta1 * f2;
3097 + NCOI = (f1 << 15) / f2 - (1 << 15);
3098 + cntT = f2;
3099 + cntin = Totalnum1;
3100 + z0 = cntin;
3101 + z1 = cntT;
3102 + z2 = NCOI;
3103 + tempnumber = (z0 & 0xff00) >> 8;
3104 + _mt_fe_tn_set_reg(state, 0xd9, (u8) (tempnumber & 0x0f));
3105 + tempnumber = (z0 & 0xff);
3106 + _mt_fe_tn_set_reg(state, 0xda, tempnumber);
3107 + tempnumber = (z1 & 0xff00) >> 8;
3108 + _mt_fe_tn_set_reg(state, 0xdb, tempnumber);
3109 + tempnumber = (z1 & 0xff);
3110 + _mt_fe_tn_set_reg(state, 0xdc, tempnumber);
3111 + tempnumber = (z2 & 0xff00) >> 8;
3112 + _mt_fe_tn_set_reg(state, 0xdd, tempnumber);
3113 + tempnumber = (z2 & 0xff);
3114 + _mt_fe_tn_set_reg(state, 0xde, tempnumber);
3115 +
3116 + return 0;
3117 +}
3118 +
3119 +static int _mt_fe_tn_preset_tc2800(struct m88dc2800_state *state)
3120 +{
3121 + if (state->tuner_mtt == 0xD1) {
3122 + _mt_fe_tn_set_reg(state, 0x19, 0x4a);
3123 + _mt_fe_tn_set_reg(state, 0x1b, 0x4b);
3124 + _mt_fe_tn_set_reg(state, 0x04, 0x04);
3125 + _mt_fe_tn_set_reg(state, 0x17, 0x0d);
3126 + _mt_fe_tn_set_reg(state, 0x62, 0x6c);
3127 + _mt_fe_tn_set_reg(state, 0x63, 0xf4);
3128 + _mt_fe_tn_set_reg(state, 0x1f, 0x0e);
3129 + _mt_fe_tn_set_reg(state, 0x6b, 0xf4);
3130 + _mt_fe_tn_set_reg(state, 0x14, 0x01);
3131 + _mt_fe_tn_set_reg(state, 0x5a, 0x75);
3132 + _mt_fe_tn_set_reg(state, 0x66, 0x74);
3133 + _mt_fe_tn_set_reg(state, 0x72, 0xe0);
3134 + _mt_fe_tn_set_reg(state, 0x70, 0x07);
3135 + _mt_fe_tn_set_reg(state, 0x15, 0x7b);
3136 + _mt_fe_tn_set_reg(state, 0x55, 0x71);
3137 + _mt_fe_tn_set_reg(state, 0x75, 0x55);
3138 + _mt_fe_tn_set_reg(state, 0x76, 0xac);
3139 + _mt_fe_tn_set_reg(state, 0x77, 0x6c);
3140 + _mt_fe_tn_set_reg(state, 0x78, 0x8b);
3141 + _mt_fe_tn_set_reg(state, 0x79, 0x42);
3142 + _mt_fe_tn_set_reg(state, 0x7a, 0xd2);
3143 + _mt_fe_tn_set_reg(state, 0x81, 0x01);
3144 + _mt_fe_tn_set_reg(state, 0x82, 0x00);
3145 + _mt_fe_tn_set_reg(state, 0x82, 0x02);
3146 + _mt_fe_tn_set_reg(state, 0x82, 0x04);
3147 + _mt_fe_tn_set_reg(state, 0x82, 0x06);
3148 + _mt_fe_tn_set_reg(state, 0x82, 0x08);
3149 + _mt_fe_tn_set_reg(state, 0x82, 0x09);
3150 + _mt_fe_tn_set_reg(state, 0x82, 0x29);
3151 + _mt_fe_tn_set_reg(state, 0x82, 0x49);
3152 + _mt_fe_tn_set_reg(state, 0x82, 0x58);
3153 + _mt_fe_tn_set_reg(state, 0x82, 0x59);
3154 + _mt_fe_tn_set_reg(state, 0x82, 0x98);
3155 + _mt_fe_tn_set_reg(state, 0x82, 0x99);
3156 + _mt_fe_tn_set_reg(state, 0x10, 0x05);
3157 + _mt_fe_tn_set_reg(state, 0x10, 0x0d);
3158 + _mt_fe_tn_set_reg(state, 0x11, 0x95);
3159 + _mt_fe_tn_set_reg(state, 0x11, 0x9d);
3160 + if (state->tuner_loopthrough != 0) {
3161 + _mt_fe_tn_set_reg(state, 0x67, 0x25);
3162 + } else {
3163 + _mt_fe_tn_set_reg(state, 0x67, 0x05);
3164 + }
3165 + } else if (state->tuner_mtt == 0xE1) {
3166 + _mt_fe_tn_set_reg(state, 0x1b, 0x47);
3167 + if (state->tuner_mode == 0) { /* DVB-C */
3168 + _mt_fe_tn_set_reg(state, 0x66, 0x74);
3169 + _mt_fe_tn_set_reg(state, 0x62, 0x2c);
3170 + _mt_fe_tn_set_reg(state, 0x63, 0x54);
3171 + _mt_fe_tn_set_reg(state, 0x68, 0x0b);
3172 + _mt_fe_tn_set_reg(state, 0x14, 0x00);
3173 + } else { /* CTTB */
3174 + _mt_fe_tn_set_reg(state, 0x66, 0x74);
3175 + _mt_fe_tn_set_reg(state, 0x62, 0x0c);
3176 + _mt_fe_tn_set_reg(state, 0x63, 0x54);
3177 + _mt_fe_tn_set_reg(state, 0x68, 0x0b);
3178 + _mt_fe_tn_set_reg(state, 0x14, 0x05);
3179 + }
3180 + _mt_fe_tn_set_reg(state, 0x6f, 0x00);
3181 + _mt_fe_tn_set_reg(state, 0x84, 0x04);
3182 + _mt_fe_tn_set_reg(state, 0x5e, 0xbe);
3183 + _mt_fe_tn_set_reg(state, 0x87, 0x07);
3184 + _mt_fe_tn_set_reg(state, 0x8a, 0x1f);
3185 + _mt_fe_tn_set_reg(state, 0x8b, 0x1f);
3186 + _mt_fe_tn_set_reg(state, 0x88, 0x30);
3187 + _mt_fe_tn_set_reg(state, 0x58, 0x34);
3188 + _mt_fe_tn_set_reg(state, 0x61, 0x8c);
3189 + _mt_fe_tn_set_reg(state, 0x6a, 0x42);
3190 + }
3191 + return 0;
3192 +}
3193 +
3194 +static int mt_fe_tn_wakeup_tc2800(struct m88dc2800_state *state)
3195 +{
3196 + _mt_fe_tn_set_reg(state, 0x16, 0xb1);
3197 + _mt_fe_tn_set_reg(state, 0x09, 0x7d);
3198 + return 0;
3199 +}
3200 +
3201 + static int mt_fe_tn_sleep_tc2800(struct m88dc2800_state *state)
3202 +{
3203 + _mt_fe_tn_set_reg(state, 0x16, 0xb0);
3204 + _mt_fe_tn_set_reg(state, 0x09, 0x6d);
3205 + return 0;
3206 +}
3207 +
3208 + static int mt_fe_tn_init_tc2800(struct m88dc2800_state *state)
3209 +{
3210 + if (state->tuner_init_OK != 1) {
3211 + state->tuner_dev_addr = 0x61; /* TUNER_I2C_ADDR_TC2800 */
3212 + state->tuner_freq = 650000;
3213 + state->tuner_qam = 0;
3214 + state->tuner_mode = 0; // 0: DVB-C, 1: CTTB
3215 + state->tuner_bandwidth = 8;
3216 + state->tuner_loopthrough = 0;
3217 + state->tuner_crystal = 24000;
3218 + state->tuner_dac = 7200;
3219 + state->tuner_mtt = 0x00;
3220 + state->tuner_custom_cfg = 0;
3221 + state->tuner_version = 30022; /* Driver version number */
3222 + state->tuner_time = 12092611;
3223 + state->tuner_init_OK = 1;
3224 + }
3225 + _mt_fe_tn_set_reg(state, 0x2b, 0x46);
3226 + _mt_fe_tn_set_reg(state, 0x2c, 0x75);
3227 + if (state->tuner_mtt == 0x00) {
3228 + u8 tmp = 0;
3229 + _mt_fe_tn_get_reg(state, 0x01, &tmp);
3230 + printk(KERN_INFO "m88dc2800: tuner id = 0x%02x ", tmp);
3231 + switch (tmp) {
3232 + case 0x0d:
3233 + state->tuner_mtt = 0xD1;
3234 + break;
3235 + case 0x8e:
3236 + default:
3237 + state->tuner_mtt = 0xE1;
3238 + break;
3239 + }
3240 + }
3241 + return 0;
3242 +}
3243 +
3244 + static int mt_fe_tn_set_freq_tc2800(struct m88dc2800_state *state,
3245 + u32 freq_KHz)
3246 +{
3247 + u8 buf;
3248 + u8 buf1;
3249 +
3250 + mt_fe_tn_init_tc2800(state);
3251 + state->tuner_freq = freq_KHz;
3252 + _mt_fe_tn_set_reg(state, 0x21, freq_KHz > 500000 ? 0xb9 : 0x99);
3253 + mt_fe_tn_wakeup_tc2800(state);
3254 + _mt_fe_tn_set_reg(state, 0x05, 0x7f);
3255 + _mt_fe_tn_set_reg(state, 0x06, 0xf8);
3256 + _mt_fe_tn_set_RF_front_tc2800(state);
3257 + _mt_fe_tn_set_PLL_freq_tc2800(state);
3258 + _mt_fe_tn_set_DAC_tc2800(state);
3259 + _mt_fe_tn_set_BB_tc2800(state);
3260 + _mt_fe_tn_preset_tc2800(state);
3261 + _mt_fe_tn_set_reg(state, 0x05, 0x00);
3262 + _mt_fe_tn_set_reg(state, 0x06, 0x00);
3263 + if (state->tuner_mtt == 0xD1) {
3264 + _mt_fe_tn_set_reg(state, 0x00, 0x01);
3265 + _mt_fe_tn_set_reg(state, 0x00, 0x00);
3266 + msleep(5);
3267 + _mt_fe_tn_set_reg(state, 0x41, 0x00);
3268 + msleep(5);
3269 + _mt_fe_tn_set_reg(state, 0x41, 0x02);
3270 +
3271 + _mt_fe_tn_get_reg(state, 0x69, &buf1);
3272 + buf1 = buf1 & 0x0f;
3273 + _mt_fe_tn_get_reg(state, 0x61, &buf);
3274 + buf = buf & 0x0f;
3275 + if (buf == 0x0c)
3276 + _mt_fe_tn_set_reg(state, 0x6a, 0x59);
3277 + if (buf1 > 0x02) {
3278 + if (freq_KHz > 600000)
3279 + _mt_fe_tn_set_reg(state, 0x66, 0x44);
3280 + else if (freq_KHz > 500000)
3281 + _mt_fe_tn_set_reg(state, 0x66, 0x64);
3282 + else
3283 + _mt_fe_tn_set_reg(state, 0x66, 0x74);
3284 + }
3285 + if (buf1 < 0x03) {
3286 + if (freq_KHz > 800000)
3287 + _mt_fe_tn_set_reg(state, 0x87, 0x64);
3288 + else if (freq_KHz > 600000)
3289 + _mt_fe_tn_set_reg(state, 0x87, 0x54);
3290 + else if (freq_KHz > 500000)
3291 + _mt_fe_tn_set_reg(state, 0x87, 0x54);
3292 + else if (freq_KHz > 300000)
3293 + _mt_fe_tn_set_reg(state, 0x87, 0x43);
3294 + else if (freq_KHz > 220000)
3295 + _mt_fe_tn_set_reg(state, 0x87, 0x54);
3296 + else if (freq_KHz > 110000)
3297 + _mt_fe_tn_set_reg(state, 0x87, 0x14);
3298 + else
3299 + _mt_fe_tn_set_reg(state, 0x87, 0x54);
3300 + msleep(5);
3301 + } else if (buf < 0x0c) {
3302 + if (freq_KHz > 800000)
3303 + _mt_fe_tn_set_reg(state, 0x87, 0x14);
3304 + else if (freq_KHz > 600000)
3305 + _mt_fe_tn_set_reg(state, 0x87, 0x14);
3306 + else if (freq_KHz > 500000)
3307 + _mt_fe_tn_set_reg(state, 0x87, 0x34);
3308 + else if (freq_KHz > 300000)
3309 + _mt_fe_tn_set_reg(state, 0x87, 0x43);
3310 + else if (freq_KHz > 220000)
3311 + _mt_fe_tn_set_reg(state, 0x87, 0x54);
3312 + else if (freq_KHz > 110000)
3313 + _mt_fe_tn_set_reg(state, 0x87, 0x14);
3314 + else
3315 + _mt_fe_tn_set_reg(state, 0x87, 0x54);
3316 + msleep(5);
3317 + }
3318 + } else if ((state->tuner_mtt == 0xE1)) {
3319 + _mt_fe_tn_set_reg(state, 0x00, 0x01);
3320 + _mt_fe_tn_set_reg(state, 0x00, 0x00);
3321 + msleep(20);
3322 + _mt_fe_tn_get_reg(state, 0x32, &buf);
3323 + buf = (buf & 0xef) | 0x28;
3324 + _mt_fe_tn_set_reg(state, 0x32, buf);
3325 + msleep(50);
3326 + _mt_fe_tn_get_reg(state, 0x38, &buf);
3327 + _mt_fe_tn_set_reg(state, 0x38, buf);
3328 + _mt_fe_tn_get_reg(state, 0x32, &buf);
3329 + buf = (buf & 0xf7) | 0x10;
3330 + _mt_fe_tn_set_reg(state, 0x32, buf);
3331 + msleep(10);
3332 + _mt_fe_tn_get_reg(state, 0x69, &buf);
3333 + buf = buf & 0x03;
3334 + _mt_fe_tn_set_reg(state, 0x2a, buf);
3335 + if (buf > 0) {
3336 + msleep(20);
3337 + _mt_fe_tn_get_reg(state, 0x84, &buf);
3338 + buf = buf & 0x1f;
3339 + _mt_fe_tn_set_reg(state, 0x68, 0x0a);
3340 + _mt_fe_tn_get_reg(state, 0x88, &buf1);
3341 + buf1 = buf1 & 0x1f;
3342 + if (buf <= buf1)
3343 + _mt_fe_tn_set_reg(state, 0x66, 0x44);
3344 + else
3345 + _mt_fe_tn_set_reg(state, 0x66, 0x74);
3346 + } else {
3347 + if (freq_KHz <= 600000)
3348 + _mt_fe_tn_set_reg(state, 0x68, 0x0c);
3349 + else
3350 + _mt_fe_tn_set_reg(state, 0x68, 0x0e);
3351 + _mt_fe_tn_set_reg(state, 0x30, 0xfb);
3352 + _mt_fe_tn_set_reg(state, 0x30, 0xff);
3353 + _mt_fe_tn_set_reg(state, 0x31, 0x04);
3354 + _mt_fe_tn_set_reg(state, 0x31, 0x00);
3355 + }
3356 + if (state->tuner_loopthrough != 0) {
3357 + _mt_fe_tn_get_reg(state, 0x28, &buf);
3358 + if (buf == 0) {
3359 + _mt_fe_tn_set_reg(state, 0x28, 0xff);
3360 + _mt_fe_tn_get_reg(state, 0x61, &buf);
3361 + buf = buf & 0x0f;
3362 + if (buf > 9)
3363 + _mt_fe_tn_set_reg(state, 0x67, 0x74);
3364 + else if (buf > 6)
3365 + _mt_fe_tn_set_reg(state, 0x67, 0x64);
3366 + else if (buf > 3)
3367 + _mt_fe_tn_set_reg(state, 0x67, 0x54);
3368 + else
3369 + _mt_fe_tn_set_reg(state, 0x67, 0x44);
3370 + }
3371 + } else {
3372 + _mt_fe_tn_set_reg(state, 0x67, 0x34);
3373 + }
3374 + } else {
3375 + return 1;
3376 + }
3377 + return 0;
3378 +}
3379 +
3380 +
3381 +/*
3382 +static int mt_fe_tn_set_BB_filter_band_tc2800(struct m88dc2800_state *state,
3383 + u8 bandwidth)
3384 +{
3385 + u8 buf, tmp;
3386 +
3387 + _mt_fe_tn_get_reg(state, 0x53, &tmp);
3388 +
3389 + if (bandwidth == 6)
3390 + buf = 0x01 << 1;
3391 + else if (bandwidth == 7)
3392 + buf = 0x02 << 1;
3393 + else if (bandwidth == 8)
3394 + buf = 0x04 << 1;
3395 + else
3396 + buf = 0x04 << 1;
3397 +
3398 + tmp &= 0xf1;
3399 + tmp |= buf;
3400 + _mt_fe_tn_set_reg(state, 0x53, tmp);
3401 + state->tuner_bandwidth = bandwidth;
3402 + return 0;
3403 +}
3404 +*/
3405 +
3406 +static s32 mt_fe_tn_get_signal_strength_tc2800(struct m88dc2800_state
3407 + *state)
3408 +{
3409 + s32 level = -107;
3410 + s32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
3411 + s32 val1, val2, val;
3412 + s32 result2, result3, result4, result5, result6;
3413 + s32 append;
3414 + u8 tmp;
3415 + s32 freq_KHz = (s32) state->tuner_freq;
3416 + if (state->tuner_mtt == 0xD1) {
3417 + _mt_fe_tn_get_reg(state, 0x61, &tmp);
3418 + tmp1 = tmp & 0x0f;
3419 + _mt_fe_tn_get_reg(state, 0x69, &tmp);
3420 + tmp2 = tmp & 0x0f;
3421 + _mt_fe_tn_get_reg(state, 0x73, &tmp);
3422 + tmp3 = tmp & 0x07;
3423 + _mt_fe_tn_get_reg(state, 0x7c, &tmp);
3424 + tmp4 = (tmp >> 4) & 0x0f;
3425 + _mt_fe_tn_get_reg(state, 0x7b, &tmp);
3426 + tmp5 = tmp & 0x0f;
3427 + _mt_fe_tn_get_reg(state, 0x7f, &tmp);
3428 + tmp6 = (tmp >> 5) & 0x01;
3429 + if (tmp1 > 6) {
3430 + val1 = 0;
3431 + if (freq_KHz <= 200000) {
3432 + val2 = (tmp1 - 6) * 267;
3433 + } else if (freq_KHz <= 600000) {
3434 + val2 = (tmp1 - 6) * 280;
3435 + } else {
3436 + val2 = (tmp1 - 6) * 290;
3437 + }
3438 + val = val1 + val2;
3439 + } else {
3440 + if (tmp1 == 0) {
3441 + val1 = -550;
3442 + } else {
3443 + val1 = 0;
3444 + }
3445 + if ((tmp1 < 4) && (freq_KHz >= 506000)) {
3446 + val1 = -850;
3447 + }
3448 + val2 = 0;
3449 + val = val1 + val2;
3450 + }
3451 + if (freq_KHz <= 95000) {
3452 + result2 = tmp2 * 289;
3453 + } else if (freq_KHz <= 155000) {
3454 + result2 = tmp2 * 278;
3455 + } else if (freq_KHz <= 245000) {
3456 + result2 = tmp2 * 267;
3457 + } else if (freq_KHz <= 305000) {
3458 + result2 = tmp2 * 256;
3459 + } else if (freq_KHz <= 335000) {
3460 + result2 = tmp2 * 244;
3461 + } else if (freq_KHz <= 425000) {
3462 + result2 = tmp2 * 233;
3463 + } else if (freq_KHz <= 575000) {
3464 + result2 = tmp2 * 222;
3465 + } else if (freq_KHz <= 665000) {
3466 + result2 = tmp2 * 211;
3467 + } else {
3468 + result2 = tmp2 * 200;
3469 + }
3470 + result3 = (6 - tmp3) * 100;
3471 + result4 = 300 * tmp4;
3472 + result5 = 50 * tmp5;
3473 + result6 = 300 * tmp6;
3474 + if (freq_KHz < 105000) {
3475 + append = -450;
3476 + } else if (freq_KHz <= 227000) {
3477 + append = -4 * (freq_KHz / 1000 - 100) + 150;
3478 + } else if (freq_KHz <= 305000) {
3479 + append = -4 * (freq_KHz / 1000 - 100);
3480 + } else if (freq_KHz <= 419000) {
3481 + append = 500 - 40 * (freq_KHz / 1000 - 300) / 17 + 130;
3482 + } else if (freq_KHz <= 640000) {
3483 + append = 500 - 40 * (freq_KHz / 1000 - 300) / 17;
3484 + } else {
3485 + append = -500;
3486 + }
3487 + level = append - (val + result2 + result3 + result4 +
3488 + result5 + result6);
3489 + level /= 100;
3490 + } else if (state->tuner_mtt == 0xE1) {
3491 + _mt_fe_tn_get_reg(state, 0x61, &tmp);
3492 + tmp1 = tmp & 0x0f;
3493 + _mt_fe_tn_get_reg(state, 0x84, &tmp);
3494 + tmp2 = tmp & 0x1f;
3495 + _mt_fe_tn_get_reg(state, 0x69, &tmp);
3496 + tmp3 = tmp & 0x03;
3497 + _mt_fe_tn_get_reg(state, 0x73, &tmp);
3498 + tmp4 = tmp & 0x0f;
3499 + _mt_fe_tn_get_reg(state, 0x7c, &tmp);
3500 + tmp5 = (tmp >> 4) & 0x0f;
3501 + _mt_fe_tn_get_reg(state, 0x7b, &tmp);
3502 + tmp6 = tmp & 0x0f;
3503 + if (freq_KHz < 151000) {
3504 + result2 = (1150 - freq_KHz / 100) * 163 / 33 + 4230;
3505 + result3 = (1150 - freq_KHz / 100) * 115 / 33 + 1850;
3506 + result4 = -3676 * (freq_KHz / 1000) / 100 + 6115;
3507 + } else if (freq_KHz < 257000) {
3508 + result2 = (1540 - freq_KHz / 100) * 11 / 4 + 3870;
3509 + result3 = (1540 - freq_KHz / 100) * 205 / 96 + 2100;
3510 + result4 = -21 * freq_KHz / 1000 + 5084;
3511 + } else if (freq_KHz < 305000) {
3512 + result2 = (2620 - freq_KHz / 100) * 5 / 3 + 2770;
3513 + result3 = (2620 - freq_KHz / 100) * 10 / 7 + 1700;
3514 + result4 = 650;
3515 + } else if (freq_KHz < 449000) {
3516 + result2 = (307 - freq_KHz / 1000) * 82 / 27 + 11270;
3517 + result3 = (3100 - freq_KHz / 100) * 5 / 3 + 10000;
3518 + result4 = 134 * freq_KHz / 10000 + 11875;
3519 + } else {
3520 + result2 = (307 - freq_KHz / 1000) * 82 / 27 + 11270;
3521 + result3 = 8400;
3522 + result4 = 5300;
3523 + }
3524 + if (tmp1 > 6) {
3525 + val1 = result2;
3526 + val2 = 2900;
3527 + val = 500;
3528 + } else if (tmp1 > 0) {
3529 + val1 = result3;
3530 + val2 = 2700;
3531 + val = 500;
3532 + } else {
3533 + val1 = result4;
3534 + val2 = 2700;
3535 + val = 400;
3536 + }
3537 + level = val1 - (val2 * tmp1 + 500 * tmp2 + 3000 * tmp3 -
3538 + 500 * tmp4 + 3000 * tmp5 + val * tmp6) - 1000;
3539 + level /= 1000;
3540 + }
3541 + return level;
3542 +}
3543 +
3544 +
3545 +/* m88dc2800 operation functions */
3546 +u8 M88DC2000GetLock(struct m88dc2800_state * state)
3547 +{
3548 + u8 u8ret = 0;
3549 + if (ReadReg(state, 0x80) < 0x06) {
3550 + if ((ReadReg(state, 0xdf) & 0x80) == 0x80
3551 + &&(ReadReg(state, 0x91) & 0x23) == 0x03
3552 + &&(ReadReg(state, 0x43) & 0x08) == 0x08)
3553 + u8ret = 1;
3554 + else
3555 + u8ret = 0;
3556 + } else {
3557 + if ((ReadReg(state, 0x85) & 0x08) == 0x08)
3558 + u8ret = 1;
3559 + else
3560 + u8ret = 0;
3561 + }
3562 + dprintk("%s, lock=%d\n", __func__, u8ret);
3563 + return u8ret;
3564 +}
3565 +
3566 +static int M88DC2000SetTsType(struct m88dc2800_state *state, u8 type)
3567 +{
3568 + u8 regC2H;
3569 +
3570 + if (type == 3) {
3571 + WriteReg(state, 0x84, 0x6A);
3572 + WriteReg(state, 0xC0, 0x43);
3573 + WriteReg(state, 0xE2, 0x06);
3574 + regC2H = ReadReg(state, 0xC2);
3575 + regC2H &= 0xC0;
3576 + regC2H |= 0x1B;
3577 + WriteReg(state, 0xC2, regC2H);
3578 + WriteReg(state, 0xC1, 0x60); /* common interface */
3579 + } else if (type == 1) {
3580 + WriteReg(state, 0x84, 0x6A);
3581 + WriteReg(state, 0xC0, 0x47); /* serial format */
3582 + WriteReg(state, 0xE2, 0x02);
3583 + regC2H = ReadReg(state, 0xC2);
3584 + regC2H &= 0xC7;
3585 + WriteReg(state, 0xC2, regC2H);
3586 + WriteReg(state, 0xC1, 0x00);
3587 + } else {
3588 + WriteReg(state, 0x84, 0x6C);
3589 + WriteReg(state, 0xC0, 0x43); /* parallel format */
3590 + WriteReg(state, 0xE2, 0x06);
3591 + regC2H = ReadReg(state, 0xC2);
3592 + regC2H &= 0xC7;
3593 + WriteReg(state, 0xC2, regC2H);
3594 + WriteReg(state, 0xC1, 0x00);
3595 + }
3596 + return 0;
3597 +}
3598 +
3599 +static int M88DC2000RegInitial_TC2800(struct m88dc2800_state *state)
3600 +{
3601 + u8 RegE3H, RegE4H;
3602 +
3603 + WriteReg(state, 0x00, 0x48);
3604 + WriteReg(state, 0x01, 0x09);
3605 + WriteReg(state, 0xFB, 0x0A);
3606 + WriteReg(state, 0xFC, 0x0B);
3607 + WriteReg(state, 0x02, 0x0B);
3608 + WriteReg(state, 0x03, 0x18);
3609 + WriteReg(state, 0x05, 0x0D);
3610 + WriteReg(state, 0x36, 0x80);
3611 + WriteReg(state, 0x43, 0x40);
3612 + WriteReg(state, 0x55, 0x7A);
3613 + WriteReg(state, 0x56, 0xD9);
3614 + WriteReg(state, 0x57, 0xDF);
3615 + WriteReg(state, 0x58, 0x39);
3616 + WriteReg(state, 0x5A, 0x00);
3617 + WriteReg(state, 0x5C, 0x71);
3618 + WriteReg(state, 0x5D, 0x23);
3619 + WriteReg(state, 0x86, 0x40);
3620 + WriteReg(state, 0xF9, 0x08);
3621 + WriteReg(state, 0x61, 0x40);
3622 + WriteReg(state, 0x62, 0x0A);
3623 + WriteReg(state, 0x90, 0x06);
3624 + WriteReg(state, 0xDE, 0x00);
3625 + WriteReg(state, 0xA0, 0x03);
3626 + WriteReg(state, 0xDF, 0x81);
3627 + WriteReg(state, 0xFA, 0x40);
3628 + WriteReg(state, 0x37, 0x10);
3629 + WriteReg(state, 0xF0, 0x40);
3630 + WriteReg(state, 0xF2, 0x9C);
3631 + WriteReg(state, 0xF3, 0x40);
3632 + RegE3H = ReadReg(state, 0xE3);
3633 + RegE4H = ReadReg(state, 0xE4);
3634 + if (((RegE3H & 0xC0) == 0x00) && ((RegE4H & 0xC0) == 0x00)) {
3635 + WriteReg(state, 0x30, 0xFF);
3636 + WriteReg(state, 0x31, 0x00);
3637 + WriteReg(state, 0x32, 0x00);
3638 + WriteReg(state, 0x33, 0x00);
3639 + WriteReg(state, 0x35, 0x32);
3640 + WriteReg(state, 0x40, 0x00);
3641 + WriteReg(state, 0x41, 0x10);
3642 + WriteReg(state, 0xF1, 0x02);
3643 + WriteReg(state, 0xF4, 0x04);
3644 + WriteReg(state, 0xF5, 0x00);
3645 + WriteReg(state, 0x42, 0x14);
3646 + WriteReg(state, 0xE1, 0x25);
3647 + } else if (((RegE3H & 0xC0) == 0x80) && ((RegE4H & 0xC0) == 0x40)) {
3648 + WriteReg(state, 0x30, 0xFF);
3649 + WriteReg(state, 0x31, 0x00);
3650 + WriteReg(state, 0x32, 0x00);
3651 + WriteReg(state, 0x33, 0x00);
3652 + WriteReg(state, 0x35, 0x32);
3653 + WriteReg(state, 0x39, 0x00);
3654 + WriteReg(state, 0x3A, 0x00);
3655 + WriteReg(state, 0x40, 0x00);
3656 + WriteReg(state, 0x41, 0x10);
3657 + WriteReg(state, 0xF1, 0x00);
3658 + WriteReg(state, 0xF4, 0x00);
3659 + WriteReg(state, 0xF5, 0x40);
3660 + WriteReg(state, 0x42, 0x14);
3661 + WriteReg(state, 0xE1, 0x25);
3662 + } else if ((RegE3H == 0x80 || RegE3H == 0x81)
3663 + && (RegE4H == 0x80 || RegE4H == 0x81)) {
3664 + WriteReg(state, 0x30, 0xFF);
3665 + WriteReg(state, 0x31, 0x00);
3666 + WriteReg(state, 0x32, 0x00);
3667 + WriteReg(state, 0x33, 0x00);
3668 + WriteReg(state, 0x35, 0x32);
3669 + WriteReg(state, 0x39, 0x00);
3670 + WriteReg(state, 0x3A, 0x00);
3671 + WriteReg(state, 0xF1, 0x00);
3672 + WriteReg(state, 0xF4, 0x00);
3673 + WriteReg(state, 0xF5, 0x40);
3674 + WriteReg(state, 0x42, 0x24);
3675 + WriteReg(state, 0xE1, 0x25);
3676 + WriteReg(state, 0x92, 0x7F);
3677 + WriteReg(state, 0x93, 0x91);
3678 + WriteReg(state, 0x95, 0x00);
3679 + WriteReg(state, 0x2B, 0x33);
3680 + WriteReg(state, 0x2A, 0x2A);
3681 + WriteReg(state, 0x2E, 0x80);
3682 + WriteReg(state, 0x25, 0x25);
3683 + WriteReg(state, 0x2D, 0xFF);
3684 + WriteReg(state, 0x26, 0xFF);
3685 + WriteReg(state, 0x27, 0x00);
3686 + WriteReg(state, 0x24, 0x25);
3687 + WriteReg(state, 0xA4, 0xFF);
3688 + WriteReg(state, 0xA3, 0x0D);
3689 + } else {
3690 + WriteReg(state, 0x30, 0xFF);
3691 + WriteReg(state, 0x31, 0x00);
3692 + WriteReg(state, 0x32, 0x00);
3693 + WriteReg(state, 0x33, 0x00);
3694 + WriteReg(state, 0x35, 0x32);
3695 + WriteReg(state, 0x39, 0x00);
3696 + WriteReg(state, 0x3A, 0x00);
3697 + WriteReg(state, 0xF1, 0x00);
3698 + WriteReg(state, 0xF4, 0x00);
3699 + WriteReg(state, 0xF5, 0x40);
3700 + WriteReg(state, 0x42, 0x24);
3701 + WriteReg(state, 0xE1, 0x27);
3702 + WriteReg(state, 0x92, 0x7F);
3703 + WriteReg(state, 0x93, 0x91);
3704 + WriteReg(state, 0x95, 0x00);
3705 + WriteReg(state, 0x2B, 0x33);
3706 + WriteReg(state, 0x2A, 0x2A);
3707 + WriteReg(state, 0x2E, 0x80);
3708 + WriteReg(state, 0x25, 0x25);
3709 + WriteReg(state, 0x2D, 0xFF);
3710 + WriteReg(state, 0x26, 0xFF);
3711 + WriteReg(state, 0x27, 0x00);
3712 + WriteReg(state, 0x24, 0x25);
3713 + WriteReg(state, 0xA4, 0xFF);
3714 + WriteReg(state, 0xA3, 0x10);
3715 + }
3716 + WriteReg(state, 0xF6, 0x4E);
3717 + WriteReg(state, 0xF7, 0x20);
3718 + WriteReg(state, 0x89, 0x02);
3719 + WriteReg(state, 0x14, 0x08);
3720 + WriteReg(state, 0x6F, 0x0D);
3721 + WriteReg(state, 0x10, 0xFF);
3722 + WriteReg(state, 0x11, 0x00);
3723 + WriteReg(state, 0x12, 0x30);
3724 + WriteReg(state, 0x13, 0x23);
3725 + WriteReg(state, 0x60, 0x00);
3726 + WriteReg(state, 0x69, 0x00);
3727 + WriteReg(state, 0x6A, 0x03);
3728 + WriteReg(state, 0xE0, 0x75);
3729 + WriteReg(state, 0x8D, 0x29);
3730 + WriteReg(state, 0x4E, 0xD8);
3731 + WriteReg(state, 0x88, 0x80);
3732 + WriteReg(state, 0x52, 0x79);
3733 + WriteReg(state, 0x53, 0x03);
3734 + WriteReg(state, 0x59, 0x30);
3735 + WriteReg(state, 0x5E, 0x02);
3736 + WriteReg(state, 0x5F, 0x0F);
3737 + WriteReg(state, 0x71, 0x03);
3738 + WriteReg(state, 0x72, 0x12);
3739 + WriteReg(state, 0x73, 0x12);
3740 +
3741 + return 0;
3742 +}
3743 +
3744 +static int M88DC2000AutoTSClock_P(struct m88dc2800_state *state, u32 sym,
3745 + u16 qam)
3746 +{
3747 + u32 dataRate;
3748 + u8 clk_div, value;
3749 + printk(KERN_INFO
3750 + "m88dc2800: M88DC2000AutoTSClock_P, symrate=%d qam=%d\n",
3751 + sym, qam);
3752 + switch (qam) {
3753 + case 16:
3754 + dataRate = 4;
3755 + break;
3756 + case 32:
3757 + dataRate = 5;
3758 + break;
3759 + case 128:
3760 + dataRate = 7;
3761 + break;
3762 + case 256:
3763 + dataRate = 8;
3764 + break;
3765 + case 64:
3766 + default:
3767 + dataRate = 6;
3768 + break;
3769 + }
3770 + dataRate *= sym * 105;
3771 + dataRate /= 800;
3772 + if (dataRate <= 4115)
3773 + clk_div = 0x05;
3774 + else if (dataRate <= 4800)
3775 + clk_div = 0x04;
3776 + else if (dataRate <= 5760)
3777 + clk_div = 0x03;
3778 + else if (dataRate <= 7200)
3779 + clk_div = 0x02;
3780 + else if (dataRate <= 9600)
3781 + clk_div = 0x01;
3782 + else
3783 + clk_div = 0x00;
3784 + value = ReadReg(state, 0xC2);
3785 + value &= 0xc0;
3786 + value |= clk_div;
3787 + WriteReg(state, 0xC2, value);
3788 + return 0;
3789 +}
3790 +
3791 +static int M88DC2000AutoTSClock_C(struct m88dc2800_state *state, u32 sym,
3792 + u16 qam)
3793 +{
3794 + u32 dataRate;
3795 + u8 clk_div, value;
3796 + printk(KERN_INFO
3797 + "m88dc2800: M88DC2000AutoTSClock_C, symrate=%d qam=%d\n",
3798 + sym, qam);
3799 + switch (qam) {
3800 + case 16:
3801 + dataRate = 4;
3802 + break;
3803 + case 32:
3804 + dataRate = 5;
3805 + break;
3806 + case 128:
3807 + dataRate = 7;
3808 + break;
3809 + case 256:
3810 + dataRate = 8;
3811 + break;
3812 + case 64:
3813 + default:
3814 + dataRate = 6;
3815 + break;
3816 + }
3817 + dataRate *= sym * 105;
3818 + dataRate /= 800;
3819 + if (dataRate <= 4115)
3820 + clk_div = 0x3F;
3821 + else if (dataRate <= 4800)
3822 + clk_div = 0x36;
3823 + else if (dataRate <= 5760)
3824 + clk_div = 0x2D;
3825 + else if (dataRate <= 7200)
3826 + clk_div = 0x24;
3827 + else if (dataRate <= 9600)
3828 + clk_div = 0x1B;
3829 + else
3830 + clk_div = 0x12;
3831 + value = ReadReg(state, 0xC2);
3832 + value &= 0xc0;
3833 + value |= clk_div;
3834 + WriteReg(state, 0xC2, value);
3835 + return 0;
3836 +}
3837 +
3838 +static int M88DC2000SetTxMode(struct m88dc2800_state *state, u8 inverted,
3839 + u8 j83)
3840 +{
3841 + u8 value = 0;
3842 + if (inverted)
3843 + value |= 0x08; /* spectrum inverted */
3844 + if (j83)
3845 + value |= 0x01; /* J83C */
3846 + WriteReg(state, 0x83, value);
3847 + return 0;
3848 +}
3849 +
3850 +static int M88DC2000SoftReset(struct m88dc2800_state *state)
3851 +{
3852 + WriteReg(state, 0x80, 0x01);
3853 + WriteReg(state, 0x82, 0x00);
3854 + msleep(1);
3855 + WriteReg(state, 0x80, 0x00);
3856 + return 0;
3857 +}
3858 +
3859 +static int M88DC2000SetSym(struct m88dc2800_state *state, u32 sym, u32 xtal)
3860 +{
3861 + u8 value;
3862 + u8 reg6FH, reg12H;
3863 + u64 fValue;
3864 + u32 dwValue;
3865 +
3866 + printk(KERN_INFO "%s, sym=%d, xtal=%d\n", __func__, sym, xtal);
3867 + fValue = 4294967296 * (sym + 10);
3868 + do_div(fValue, xtal);
3869 +
3870 + /* fValue = 4294967296 * (sym + 10) / xtal; */
3871 + dwValue = (u32) fValue;
3872 + printk(KERN_INFO "%s, fvalue1=%x\n", __func__, dwValue);
3873 + WriteReg(state, 0x58, (u8) ((dwValue >> 24) & 0xff));
3874 + WriteReg(state, 0x57, (u8) ((dwValue >> 16) & 0xff));
3875 + WriteReg(state, 0x56, (u8) ((dwValue >> 8) & 0xff));
3876 + WriteReg(state, 0x55, (u8) ((dwValue >> 0) & 0xff));
3877 +
3878 + /* fValue = 2048 * xtal / sym; */
3879 + fValue = 2048 * xtal;
3880 + do_div(fValue, sym);
3881 + dwValue = (u32) fValue;
3882 + printk(KERN_INFO "%s, fvalue2=%x\n", __func__, dwValue);
3883 + WriteReg(state, 0x5D, (u8) ((dwValue >> 8) & 0xff));
3884 + WriteReg(state, 0x5C, (u8) ((dwValue >> 0) & 0xff));
3885 + value = ReadReg(state, 0x5A);
3886 + if (((dwValue >> 16) & 0x0001) == 0)
3887 + value &= 0x7F;
3888 + else
3889 + value |= 0x80;
3890 + WriteReg(state, 0x5A, value);
3891 + value = ReadReg(state, 0x89);
3892 + if (sym <= 1800)
3893 + value |= 0x01;
3894 + else
3895 + value &= 0xFE;
3896 + WriteReg(state, 0x89, value);
3897 + if (sym >= 6700) {
3898 + reg6FH = 0x0D;
3899 + reg12H = 0x30;
3900 + } else if (sym >= 4000) {
3901 + fValue = 22 * 4096 / sym;
3902 + reg6FH = (u8) fValue;
3903 + reg12H = 0x30;
3904 + } else if (sym >= 2000) {
3905 + fValue = 14 * 4096 / sym;
3906 + reg6FH = (u8) fValue;
3907 + reg12H = 0x20;
3908 + } else {
3909 + fValue = 7 * 4096 / sym;
3910 + reg6FH = (u8) fValue;
3911 + reg12H = 0x10;
3912 + }
3913 + WriteReg(state, 0x6F, reg6FH);
3914 + WriteReg(state, 0x12, reg12H);
3915 + if (((ReadReg(state, 0xE3) & 0x80) == 0x80)
3916 + && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) {
3917 + if (sym < 3000) {
3918 + WriteReg(state, 0x6C, 0x16);
3919 + WriteReg(state, 0x6D, 0x10);
3920 + WriteReg(state, 0x6E, 0x18);
3921 + } else {
3922 + WriteReg(state, 0x6C, 0x14);
3923 + WriteReg(state, 0x6D, 0x0E);
3924 + WriteReg(state, 0x6E, 0x36);
3925 + }
3926 + } else {
3927 + WriteReg(state, 0x6C, 0x16);
3928 + WriteReg(state, 0x6D, 0x10);
3929 + WriteReg(state, 0x6E, 0x18);
3930 + }
3931 + return 0;
3932 +}
3933 +
3934 +static int M88DC2000SetQAM(struct m88dc2800_state *state, u16 qam)
3935 +{
3936 + u8 reg00H, reg4AH, regC2H, reg44H, reg4CH, reg4DH, reg74H, value;
3937 + u8 reg8BH, reg8EH;
3938 + printk(KERN_INFO "%s, qam=%d\n", __func__, qam);
3939 + regC2H = ReadReg(state, 0xC2);
3940 + regC2H &= 0xF8;
3941 + switch (qam) {
3942 + case 16: /* 16 QAM */
3943 + reg00H = 0x08;
3944 + reg4AH = 0x0F;
3945 + regC2H |= 0x02;
3946 + reg44H = 0xAA;
3947 + reg4CH = 0x0C;
3948 + reg4DH = 0xF7;
3949 + reg74H = 0x0E;
3950 + if (((ReadReg(state, 0xE3) & 0x80) == 0x80)
3951 + && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) {
3952 + reg8BH = 0x5A;
3953 + reg8EH = 0xBD;
3954 + } else {
3955 + reg8BH = 0x5B;
3956 + reg8EH = 0x9D;
3957 + }
3958 + WriteReg(state, 0x6E, 0x18);
3959 + break;
3960 + case 32: /* 32 QAM */
3961 + reg00H = 0x18;
3962 + reg4AH = 0xFB;
3963 + regC2H |= 0x02;
3964 + reg44H = 0xAA;
3965 + reg4CH = 0x0C;
3966 + reg4DH = 0xF7;
3967 + reg74H = 0x0E;
3968 + if (((ReadReg(state, 0xE3) & 0x80) == 0x80)
3969 + && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) {
3970 + reg8BH = 0x5A;
3971 + reg8EH = 0xBD;
3972 + } else {
3973 + reg8BH = 0x5B;
3974 + reg8EH = 0x9D;
3975 + }
3976 + WriteReg(state, 0x6E, 0x18);
3977 + break;
3978 + case 64: /* 64 QAM */
3979 + reg00H = 0x48;
3980 + reg4AH = 0xCD;
3981 + regC2H |= 0x02;
3982 + reg44H = 0xAA;
3983 + reg4CH = 0x0C;
3984 + reg4DH = 0xF7;
3985 + reg74H = 0x0E;
3986 + if (((ReadReg(state, 0xE3) & 0x80) == 0x80)
3987 + && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) {
3988 + reg8BH = 0x5A;
3989 + reg8EH = 0xBD;
3990 + } else {
3991 + reg8BH = 0x5B;
3992 + reg8EH = 0x9D;
3993 + }
3994 + break;
3995 + case 128: /* 128 QAM */
3996 + reg00H = 0x28;
3997 + reg4AH = 0xFF;
3998 + regC2H |= 0x02;
3999 + reg44H = 0xA9;
4000 + reg4CH = 0x08;
4001 + reg4DH = 0xF5;
4002 + reg74H = 0x0E;
4003 + reg8BH = 0x5B;
4004 + reg8EH = 0x9D;
4005 + break;
4006 + case 256: /* 256 QAM */
4007 + reg00H = 0x38;
4008 + reg4AH = 0xCD;
4009 + if (((ReadReg(state, 0xE3) & 0x80) == 0x80)
4010 + && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) {
4011 + regC2H |= 0x02;
4012 + } else {
4013 + regC2H |= 0x01;
4014 + }
4015 + reg44H = 0xA9;
4016 + reg4CH = 0x08;
4017 + reg4DH = 0xF5;
4018 + reg74H = 0x0E;
4019 + reg8BH = 0x5B;
4020 + reg8EH = 0x9D;
4021 + break;
4022 + default: /* 64 QAM */
4023 + reg00H = 0x48;
4024 + reg4AH = 0xCD;
4025 + regC2H |= 0x02;
4026 + reg44H = 0xAA;
4027 + reg4CH = 0x0C;
4028 + reg4DH = 0xF7;
4029 + reg74H = 0x0E;
4030 + if (((ReadReg(state, 0xE3) & 0x80) == 0x80)
4031 + && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) {
4032 + reg8BH = 0x5A;
4033 + reg8EH = 0xBD;
4034 + } else {
4035 + reg8BH = 0x5B;
4036 + reg8EH = 0x9D;
4037 + }
4038 + break;
4039 + }
4040 + WriteReg(state, 0x00, reg00H);
4041 + value = ReadReg(state, 0x88);
4042 + value |= 0x08;
4043 + WriteReg(state, 0x88, value);
4044 + WriteReg(state, 0x4B, 0xFF);
4045 + WriteReg(state, 0x4A, reg4AH);
4046 + value &= 0xF7;
4047 + WriteReg(state, 0x88, value);
4048 + WriteReg(state, 0xC2, regC2H);
4049 + WriteReg(state, 0x44, reg44H);
4050 + WriteReg(state, 0x4C, reg4CH);
4051 + WriteReg(state, 0x4D, reg4DH);
4052 + WriteReg(state, 0x74, reg74H);
4053 + WriteReg(state, 0x8B, reg8BH);
4054 + WriteReg(state, 0x8E, reg8EH);
4055 + return 0;
4056 +}
4057 +
4058 +static int M88DC2000WriteTuner_TC2800(struct m88dc2800_state *state,
4059 + u32 freq_KHz)
4060 +{
4061 + printk(KERN_INFO "%s, freq=%d KHz\n", __func__, freq_KHz);
4062 + return mt_fe_tn_set_freq_tc2800(state, freq_KHz);
4063 +}
4064 +
4065 +static int m88dc2800_init(struct dvb_frontend *fe)
4066 +{
4067 + dprintk("%s()\n", __func__);
4068 + return 0;
4069 +}
4070 +
4071 +static int m88dc2800_set_parameters(struct dvb_frontend *fe)
4072 +{
4073 + struct dtv_frontend_properties *c = &fe->dtv_property_cache;
4074 + u8 is_annex_c, is_update;
4075 + u16 temp_qam;
4076 + s32 waiting_time;
4077 + struct m88dc2800_state *state = fe->demodulator_priv;
4078 +
4079 + is_annex_c = c->delivery_system == SYS_DVBC_ANNEX_C ? 1 : 0;
4080 +
4081 + switch (c->modulation) {
4082 + case QAM_16:
4083 + temp_qam = 16;
4084 + break;
4085 + case QAM_32:
4086 + temp_qam = 32;
4087 + break;
4088 + case QAM_128:
4089 + temp_qam = 128;
4090 + break;
4091 + case QAM_256:
4092 + temp_qam = 256;
4093 + break;
4094 + default: /* QAM_64 */
4095 + temp_qam = 64;
4096 + break;
4097 + }
4098 +
4099 + state->inverted = c->inversion == INVERSION_ON ? 1 : 0;
4100 +
4101 + printk(KERN_INFO
4102 + "m88dc2800: state, freq=%d qam=%d sym=%d inverted=%d xtal=%d\n",
4103 + state->freq, state->qam, state->sym, state->inverted,
4104 + state->xtal);
4105 + printk(KERN_INFO
4106 + "m88dc2800: set frequency to %d qam=%d symrate=%d annex-c=%d\n",
4107 + c->frequency, temp_qam, c->symbol_rate, is_annex_c);
4108 +
4109 + is_update = 0;
4110 + WriteReg(state, 0x80, 0x01);
4111 + if (c->frequency != state->freq) {
4112 + M88DC2000WriteTuner_TC2800(state, c->frequency / 1000);
4113 + state->freq = c->frequency;
4114 + }
4115 + if (c->symbol_rate != state->sym) {
4116 + M88DC2000SetSym(state, c->symbol_rate / 1000, state->xtal);
4117 + state->sym = c->symbol_rate;
4118 + is_update = 1;
4119 + }
4120 + if (temp_qam != state->qam) {
4121 + M88DC2000SetQAM(state, temp_qam);
4122 + state->qam = temp_qam;
4123 + is_update = 1;
4124 + }
4125 +
4126 + if (is_update != 0) {
4127 + if (state->config->ts_mode == 3)
4128 + M88DC2000AutoTSClock_C(state, state->sym / 1000,
4129 + temp_qam);
4130 + else
4131 + M88DC2000AutoTSClock_P(state, state->sym / 1000,
4132 + temp_qam);
4133 + }
4134 +
4135 + M88DC2000SetTxMode(state, state->inverted, is_annex_c);
4136 + M88DC2000SoftReset(state);
4137 + if (((ReadReg(state, 0xE3) & 0x80) == 0x80)
4138 + && ((ReadReg(state, 0xE4) & 0x80) == 0x80))
4139 + waiting_time = 800;
4140 + else
4141 + waiting_time = 500;
4142 + while (waiting_time > 0) {
4143 + msleep(50);
4144 + waiting_time -= 50;
4145 + if (M88DC2000GetLock(state))
4146 + return 0;
4147 + }
4148 +
4149 + state->inverted = (state->inverted != 0) ? 0 : 1;
4150 + M88DC2000SetTxMode(state, state->inverted, is_annex_c);
4151 + M88DC2000SoftReset(state);
4152 + if (((ReadReg(state, 0xE3) & 0x80) == 0x80) &&
4153 + ((ReadReg(state, 0xE4) & 0x80) == 0x80))
4154 + waiting_time = 800;
4155 + else
4156 + waiting_time = 500;
4157 + while (waiting_time > 0) {
4158 + msleep(50);
4159 + waiting_time -= 50;
4160 + if (M88DC2000GetLock(state))
4161 + return 0;
4162 + }
4163 + return 0;
4164 +}
4165 +
4166 +static int m88dc2800_read_status(struct dvb_frontend *fe,
4167 + fe_status_t * status)
4168 +{
4169 + struct m88dc2800_state *state = fe->demodulator_priv;
4170 + *status = 0;
4171 +
4172 + if (M88DC2000GetLock(state)) {
4173 + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER
4174 + |FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_LOCK;
4175 + }
4176 + return 0;
4177 +}
4178 +
4179 +static int m88dc2800_read_ber(struct dvb_frontend *fe, u32 * ber)
4180 +{
4181 + struct m88dc2800_state *state = fe->demodulator_priv;
4182 + u16 tmp;
4183 +
4184 + if (M88DC2000GetLock(state) == 0) {
4185 + state->ber = 0;
4186 + } else if ((ReadReg(state, 0xA0) & 0x80) != 0x80) {
4187 + tmp = ReadReg(state, 0xA2) << 8;
4188 + tmp += ReadReg(state, 0xA1);
4189 + state->ber = tmp;
4190 + WriteReg(state, 0xA0, 0x05);
4191 + WriteReg(state, 0xA0, 0x85);
4192 + }
4193 + *ber = state->ber;
4194 + return 0;
4195 +}
4196 +
4197 +static int m88dc2800_read_signal_strength(struct dvb_frontend *fe,
4198 + u16 * strength)
4199 +{
4200 + struct m88dc2800_state *state = fe->demodulator_priv;
4201 + s16 tuner_strength;
4202 +
4203 + tuner_strength = mt_fe_tn_get_signal_strength_tc2800(state);
4204 + *strength = tuner_strength < -107 ? 0 : tuner_strength + 107;
4205 +
4206 + return 0;
4207 +}
4208 +
4209 +static int m88dc2800_read_snr(struct dvb_frontend *fe, u16 * snr)
4210 +{
4211 + static const u32 mes_log[] = {
4212 + 0, 3010, 4771, 6021, 6990, 7781, 8451, 9031, 9542, 10000,
4213 + 10414, 10792, 11139, 11461, 11761, 12041, 12304, 12553, 12788,
4214 + 13010, 13222, 13424, 13617, 13802, 13979, 14150, 14314, 14472,
4215 + 14624, 14771, 14914, 15052, 15185, 15315, 15441, 15563, 15682,
4216 + 15798, 15911, 16021, 16128, 16232, 16335, 16435, 16532, 16628,
4217 + 16721, 16812, 16902, 16990, 17076, 17160, 17243, 17324, 17404,
4218 + 17482, 17559, 17634, 17709, 17782, 17853, 17924, 17993, 18062,
4219 + 18129, 18195, 18261, 18325, 18388, 18451, 18513, 18573, 18633,
4220 + 18692, 18751, 18808, 18865, 18921, 18976, 19031
4221 + };
4222 + struct m88dc2800_state *state = fe->demodulator_priv;
4223 + u8 i;
4224 + u32 _snr, mse;
4225 +
4226 + if ((ReadReg(state, 0x91) & 0x23) != 0x03) {
4227 + *snr = 0;
4228 + return 0;
4229 + }
4230 + mse = 0;
4231 + for (i = 0; i < 30; i++) {
4232 + mse += (ReadReg(state, 0x08) << 8) + ReadReg(state, 0x07);
4233 + }
4234 + mse /= 30;
4235 + if (mse > 80)
4236 + mse = 80;
4237 + switch (state->qam) {
4238 + case 16:
4239 + _snr = 34080;
4240 + break; /* 16QAM */
4241 + case 32:
4242 + _snr = 37600;
4243 + break; /* 32QAM */
4244 + case 64:
4245 + _snr = 40310;
4246 + break; /* 64QAM */
4247 + case 128:
4248 + _snr = 43720;
4249 + break; /* 128QAM */
4250 + case 256:
4251 + _snr = 46390;
4252 + break; /* 256QAM */
4253 + default:
4254 + _snr = 40310;
4255 + break;
4256 + }
4257 + _snr -= mes_log[mse - 1]; /* C - 10*log10(MSE) */
4258 + _snr /= 1000;
4259 + if (_snr > 0xff)
4260 + _snr = 0xff;
4261 + *snr = _snr;
4262 + return 0;
4263 +}
4264 +
4265 +static int m88dc2800_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks)
4266 +{
4267 + struct m88dc2800_state *state = fe->demodulator_priv;
4268 + u8 u8Value;
4269 +
4270 + u8Value = ReadReg(state, 0xdf);
4271 + u8Value |= 0x02; /* Hold */
4272 + WriteReg(state, 0xdf, u8Value);
4273 +
4274 + *ucblocks = ReadReg(state, 0xd5);
4275 + *ucblocks = (*ucblocks << 8) | ReadReg(state, 0xd4);
4276 +
4277 + u8Value &= 0xfe; /* Clear */
4278 + WriteReg(state, 0xdf, u8Value);
4279 + u8Value &= 0xfc; /* Update */
4280 + u8Value |= 0x01;
4281 + WriteReg(state, 0xdf, u8Value);
4282 +
4283 + return 0;
4284 +}
4285 +
4286 +static int m88dc2800_sleep(struct dvb_frontend *fe)
4287 +{
4288 + struct m88dc2800_state *state = fe->demodulator_priv;
4289 +
4290 + mt_fe_tn_sleep_tc2800(state);
4291 + state->freq = 0;
4292 +
4293 + return 0;
4294 +}
4295 +
4296 +static void m88dc2800_release(struct dvb_frontend *fe)
4297 +{
4298 + struct m88dc2800_state *state = fe->demodulator_priv;
4299 + kfree(state);
4300 +}
4301 +
4302 +static struct dvb_frontend_ops m88dc2800_ops;
4303 +
4304 +struct dvb_frontend *m88dc2800_attach(const struct m88dc2800_config
4305 + *config, struct i2c_adapter *i2c)
4306 +{
4307 + struct m88dc2800_state *state = NULL;
4308 +
4309 + /* allocate memory for the internal state */
4310 + state = kzalloc(sizeof(struct m88dc2800_state), GFP_KERNEL);
4311 + if (state == NULL)
4312 + goto error;
4313 +
4314 + /* setup the state */
4315 + state->config = config;
4316 + state->i2c = i2c;
4317 + state->xtal = 28800;
4318 +
4319 + WriteReg(state, 0x80, 0x01);
4320 + M88DC2000RegInitial_TC2800(state);
4321 + M88DC2000SetTsType(state, state->config->ts_mode);
4322 + mt_fe_tn_init_tc2800(state);
4323 +
4324 + /* create dvb_frontend */
4325 + memcpy(&state->frontend.ops, &m88dc2800_ops,
4326 + sizeof(struct dvb_frontend_ops));
4327 + state->frontend.demodulator_priv = state;
4328 + return &state->frontend;
4329 +
4330 + error:
4331 + kfree(state);
4332 + return NULL;
4333 +}
4334 +
4335 +EXPORT_SYMBOL(m88dc2800_attach);
4336 +
4337 +static struct dvb_frontend_ops m88dc2800_ops = {
4338 + .delsys = {SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_C},
4339 + .info = {
4340 + .name = "Montage M88DC2800 DVB-C",
4341 + .frequency_stepsize = 62500,
4342 + .frequency_min = 48000000,
4343 + .frequency_max = 870000000,
4344 + .symbol_rate_min = 870000,
4345 + .symbol_rate_max = 9000000,
4346 + .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
4347 + FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO
4348 + },
4349 + .release = m88dc2800_release,
4350 + .init = m88dc2800_init,
4351 + .sleep = m88dc2800_sleep,
4352 + .set_frontend = m88dc2800_set_parameters,
4353 + .read_status = m88dc2800_read_status,
4354 + .read_ber = m88dc2800_read_ber,
4355 + .read_signal_strength = m88dc2800_read_signal_strength,
4356 + .read_snr = m88dc2800_read_snr,
4357 + .read_ucblocks = m88dc2800_read_ucblocks,
4358 +};
4359 +
4360 +MODULE_DESCRIPTION("Montage DVB-C demodulator driver");
4361 +MODULE_AUTHOR("Max Nibble <nibble.max@gmail.com>");
4362 +MODULE_LICENSE("GPL");
4363 +MODULE_VERSION("1.00");
4364 diff --git a/drivers/media/dvb-frontends/m88dc2800.h b/drivers/media/dvb-frontends/m88dc2800.h
4365 new file mode 100644
4366 index 0000000..2184322
4367 --- /dev/null
4368 +++ b/drivers/media/dvb-frontends/m88dc2800.h
4369 @@ -0,0 +1,44 @@
4370 +/*
4371 + M88DC2800/M88TC2800 - DVB-C demodulator and tuner from Montage
4372 +
4373 + Copyright (C) 2012 Max Nibble <nibble.max@gmail.com>
4374 + Copyright (C) 2011 Montage Technology - www.montage-tech.com
4375 +
4376 + This program is free software; you can redistribute it and/or modify
4377 + it under the terms of the GNU General Public License as published by
4378 + the Free Software Foundation; either version 2 of the License, or
4379 + (at your option) any later version.
4380 +
4381 + This program is distributed in the hope that it will be useful,
4382 + but WITHOUT ANY WARRANTY; without even the implied warranty of
4383 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4384 + GNU General Public License for more details.
4385 +
4386 + You should have received a copy of the GNU General Public License
4387 + along with this program; if not, write to the Free Software
4388 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
4389 +*/
4390 +
4391 +#ifndef M88DC2800_H
4392 +#define M88DC2800_H
4393 +
4394 +#include <linux/kconfig.h>
4395 +#include <linux/dvb/frontend.h>
4396 +
4397 +struct m88dc2800_config {
4398 + u8 demod_address;
4399 + u8 ts_mode;
4400 +};
4401 +
4402 +#if IS_ENABLED(CONFIG_DVB_M88DC2800)
4403 +extern struct dvb_frontend* m88dc2800_attach(const struct m88dc2800_config* config,
4404 + struct i2c_adapter* i2c);
4405 +#else
4406 +static inline struct dvb_frontend* m88dc2800_attach(const struct m88dc2800_config* config,
4407 + struct i2c_adapter* i2c)
4408 +{
4409 + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
4410 + return NULL;
4411 +}
4412 +#endif /* CONFIG_DVB_M88DC2800 */
4413 +#endif /* M88DC2800_H */
4414 diff --git a/drivers/media/pci/cx23885/Kconfig b/drivers/media/pci/cx23885/Kconfig
4415 index d1dcb1d..285c1ad 100644
4416 --- a/drivers/media/pci/cx23885/Kconfig
4417 +++ b/drivers/media/pci/cx23885/Kconfig
4418 @@ -23,6 +23,8 @@ config VIDEO_CX23885
4419 select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT
4420 select DVB_STV6110 if MEDIA_SUBDRV_AUTOSELECT
4421 select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT
4422 + select DVB_DVBSKY_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT
4423 + select DVB_M88DC2800 if MEDIA_SUBDRV_AUTOSELECT
4424 select DVB_CX24117 if MEDIA_SUBDRV_AUTOSELECT
4425 select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT
4426 select DVB_DS3000 if MEDIA_SUBDRV_AUTOSELECT
4427 diff --git a/drivers/media/pci/cx23885/cimax2.c b/drivers/media/pci/cx23885/cimax2.c
4428 index 16fa7ea..2b63f78 100644
4429 --- a/drivers/media/pci/cx23885/cimax2.c
4430 +++ b/drivers/media/pci/cx23885/cimax2.c
4431 @@ -426,7 +426,7 @@ int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221,
4432 return state->status;
4433 }
4434
4435 -int netup_ci_init(struct cx23885_tsport *port)
4436 +int netup_ci_init(struct cx23885_tsport *port, bool isDVBSky)
4437 {
4438 struct netup_ci_state *state;
4439 u8 cimax_init[34] = {
4440 @@ -475,6 +475,11 @@ int netup_ci_init(struct cx23885_tsport *port)
4441 goto err;
4442 }
4443
4444 + if(isDVBSky) {
4445 + cimax_init[32] = 0x22;
4446 + cimax_init[33] = 0x00;
4447 + }
4448 +
4449 port->port_priv = state;
4450
4451 switch (port->nr) {
4452 @@ -548,3 +553,19 @@ void netup_ci_exit(struct cx23885_tsport *port)
4453 dvb_ca_en50221_release(&state->ca);
4454 kfree(state);
4455 }
4456 +
4457 +/* CI irq handler for DVBSky board*/
4458 +int dvbsky_ci_slot_status(struct cx23885_dev *dev)
4459 +{
4460 + struct cx23885_tsport *port = NULL;
4461 + struct netup_ci_state *state = NULL;
4462 +
4463 + ci_dbg_print("%s:\n", __func__);
4464 +
4465 + port = &dev->ts1;
4466 + state = port->port_priv;
4467 + schedule_work(&state->work);
4468 + ci_dbg_print("%s: Wakeup CI0\n", __func__);
4469 +
4470 + return 1;
4471 +}
4472 diff --git a/drivers/media/pci/cx23885/cimax2.h b/drivers/media/pci/cx23885/cimax2.h
4473 index 518744a..39f3db7 100644
4474 --- a/drivers/media/pci/cx23885/cimax2.h
4475 +++ b/drivers/media/pci/cx23885/cimax2.h
4476 @@ -41,7 +41,9 @@ extern int netup_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot);
4477 extern int netup_ci_slot_status(struct cx23885_dev *dev, u32 pci_status);
4478 extern int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221,
4479 int slot, int open);
4480 -extern int netup_ci_init(struct cx23885_tsport *port);
4481 +extern int netup_ci_init(struct cx23885_tsport *port, bool isDVBSky);
4482 extern void netup_ci_exit(struct cx23885_tsport *port);
4483
4484 +extern int dvbsky_ci_slot_status(struct cx23885_dev *dev);
4485 +
4486 #endif
4487 diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c
4488 old mode 100644
4489 new mode 100755
4490 index 79f20c8..889bd4c
4491 --- a/drivers/media/pci/cx23885/cx23885-cards.c
4492 +++ b/drivers/media/pci/cx23885/cx23885-cards.c
4493 @@ -613,6 +613,49 @@ struct cx23885_board cx23885_boards[] = {
4494 .name = "TeVii S471",
4495 .portb = CX23885_MPEG_DVB,
4496 },
4497 + [CX23885_BOARD_BST_PS8512] = {
4498 + .name = "Bestunar PS8512",
4499 + .portb = CX23885_MPEG_DVB,
4500 + },
4501 + [CX23885_BOARD_DVBSKY_S950] = {
4502 + .name = "DVBSKY S950",
4503 + .portb = CX23885_MPEG_DVB,
4504 + },
4505 + [CX23885_BOARD_DVBSKY_S952] = {
4506 + .name = "DVBSKY S952",
4507 + .portb = CX23885_MPEG_DVB,
4508 + .portc = CX23885_MPEG_DVB,
4509 + },
4510 + [CX23885_BOARD_DVBSKY_S950_CI] = {
4511 + .ci_type = 3,
4512 + .name = "DVBSKY S950CI DVB-S2 CI",
4513 + .portb = CX23885_MPEG_DVB,
4514 + },
4515 + [CX23885_BOARD_DVBSKY_C2800E_CI] = {
4516 + .ci_type = 3,
4517 + .name = "DVBSKY C2800E DVB-C CI",
4518 + .portb = CX23885_MPEG_DVB,
4519 + },
4520 + [CX23885_BOARD_DVBSKY_T9580] = {
4521 + .name = "DVBSKY T9580",
4522 + .portb = CX23885_MPEG_DVB,
4523 + .portc = CX23885_MPEG_DVB,
4524 + },
4525 + [CX23885_BOARD_DVBSKY_T980_CI] = {
4526 + .ci_type = 3,
4527 + .name = "DVBSKY T980CI DVB-T2/C CI",
4528 + .portb = CX23885_MPEG_DVB,
4529 + },
4530 + [CX23885_BOARD_DVBSKY_T982] = {
4531 + .name = "DVBSKY T982",
4532 + .portb = CX23885_MPEG_DVB,
4533 + .portc = CX23885_MPEG_DVB,
4534 + },
4535 + [CX23885_BOARD_TT_4500_CI] = {
4536 + .ci_type = 3,
4537 + .name = "TT-budget CT2-4500 CI",
4538 + .portb = CX23885_MPEG_DVB,
4539 + },
4540 [CX23885_BOARD_PROF_8000] = {
4541 .name = "Prof Revolution DVB-S2 8000",
4542 .portb = CX23885_MPEG_DVB,
4543 @@ -874,6 +917,42 @@ struct cx23885_subid cx23885_subids[] = {
4544 .subdevice = 0x9022,
4545 .card = CX23885_BOARD_TEVII_S471,
4546 }, {
4547 + .subvendor = 0x14f1,
4548 + .subdevice = 0x8512,
4549 + .card = CX23885_BOARD_BST_PS8512,
4550 + }, {
4551 + .subvendor = 0x4254,
4552 + .subdevice = 0x0950,
4553 + .card = CX23885_BOARD_DVBSKY_S950,
4554 + }, {
4555 + .subvendor = 0x4254,
4556 + .subdevice = 0x0952,
4557 + .card = CX23885_BOARD_DVBSKY_S952,
4558 + }, {
4559 + .subvendor = 0x4254,
4560 + .subdevice = 0x950C,
4561 + .card = CX23885_BOARD_DVBSKY_S950_CI,
4562 + }, {
4563 + .subvendor = 0x4254,
4564 + .subdevice = 0x2800,
4565 + .card = CX23885_BOARD_DVBSKY_C2800E_CI,
4566 + }, {
4567 + .subvendor = 0x4254,
4568 + .subdevice = 0x9580,
4569 + .card = CX23885_BOARD_DVBSKY_T9580,
4570 + }, {
4571 + .subvendor = 0x4254,
4572 + .subdevice = 0x980C,
4573 + .card = CX23885_BOARD_DVBSKY_T980_CI,
4574 + }, {
4575 + .subvendor = 0x4254,
4576 + .subdevice = 0x0982,
4577 + .card = CX23885_BOARD_DVBSKY_T982,
4578 + }, {
4579 + .subvendor = 0x13C2,
4580 + .subdevice = 0x3013,
4581 + .card = CX23885_BOARD_TT_4500_CI,
4582 + }, {
4583 .subvendor = 0x8000,
4584 .subdevice = 0x3034,
4585 .card = CX23885_BOARD_PROF_8000,
4586 @@ -1483,9 +1562,75 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
4587 cx_set(GP0_IO, 0x00040004);
4588 mdelay(60);
4589 break;
4590 + case CX23885_BOARD_DVBSKY_S950:
4591 + case CX23885_BOARD_BST_PS8512:
4592 + cx23885_gpio_enable(dev, GPIO_2, 1);
4593 + cx23885_gpio_clear(dev, GPIO_2);
4594 + msleep(100);
4595 + cx23885_gpio_set(dev, GPIO_2);
4596 + break;
4597 + case CX23885_BOARD_DVBSKY_S952:
4598 + case CX23885_BOARD_DVBSKY_T9580:
4599 + case CX23885_BOARD_DVBSKY_T982:
4600 + cx_write(MC417_CTL, 0x00000037);/* enable GPIO3-18 pins */
4601 +
4602 + cx23885_gpio_enable(dev, GPIO_2, 1);
4603 + cx23885_gpio_enable(dev, GPIO_11, 1);
4604 +
4605 + cx23885_gpio_clear(dev, GPIO_2);
4606 + cx23885_gpio_clear(dev, GPIO_11);
4607 + msleep(100);
4608 + cx23885_gpio_set(dev, GPIO_2);
4609 + cx23885_gpio_set(dev, GPIO_11);
4610 + break;
4611 + case CX23885_BOARD_DVBSKY_S950_CI:
4612 + case CX23885_BOARD_DVBSKY_C2800E_CI:
4613 + case CX23885_BOARD_DVBSKY_T980_CI:
4614 + case CX23885_BOARD_TT_4500_CI:
4615 + cx_set(GP0_IO, 0x00060002); /* GPIO 1/2 as output */
4616 + cx_clear(GP0_IO, 0x00010004); /*GPIO 0 as input*/
4617 + mdelay(100);/* reset delay */
4618 + cx_set(GP0_IO, 0x00060004); /* GPIO as out, reset high */
4619 + cx_clear(GP0_IO, 0x00010002);
4620 + cx_write(MC417_CTL, 0x00000037);/* enable GPIO3-18 pins */
4621 + /* GPIO-15 IN as ~ACK, rest as OUT */
4622 + cx_write(MC417_OEN, 0x00001000);
4623 + /* ~RD, ~WR high; ADL0, ADL1 low; ~CS0, ~CS1 high */
4624 + cx_write(MC417_RWD, 0x0000c300);
4625 + /* enable irq */
4626 + cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/
4627 + break;
4628 }
4629 }
4630
4631 +static int cx23885_ir_patch(struct i2c_adapter *i2c, u8 reg, u8 mask)
4632 +{
4633 + struct i2c_msg msgs[2];
4634 + u8 tx_buf[2], rx_buf[1];
4635 + /* Write register address */
4636 + tx_buf[0] = reg;
4637 + msgs[0].addr = 0x4c;
4638 + msgs[0].flags = 0;
4639 + msgs[0].len = 1;
4640 + msgs[0].buf = (char *) tx_buf;
4641 + /* Read data from register */
4642 + msgs[1].addr = 0x4c;
4643 + msgs[1].flags = I2C_M_RD;
4644 + msgs[1].len = 1;
4645 + msgs[1].buf = (char *) rx_buf;
4646 +
4647 + i2c_transfer(i2c, msgs, 2);
4648 +
4649 + tx_buf[0] = reg;
4650 + tx_buf[1] = rx_buf[0] | mask;
4651 + msgs[0].addr = 0x4c;
4652 + msgs[0].flags = 0;
4653 + msgs[0].len = 2;
4654 + msgs[0].buf = (char *) tx_buf;
4655 +
4656 + return i2c_transfer(i2c, msgs, 1);
4657 +}
4658 +
4659 int cx23885_ir_init(struct cx23885_dev *dev)
4660 {
4661 static struct v4l2_subdev_io_pin_config ir_rxtx_pin_cfg[] = {
4662 @@ -1573,6 +1718,26 @@ int cx23885_ir_init(struct cx23885_dev *dev)
4663 v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
4664 ir_rx_pin_cfg_count, ir_rx_pin_cfg);
4665 break;
4666 + case CX23885_BOARD_BST_PS8512:
4667 + case CX23885_BOARD_DVBSKY_S950:
4668 + case CX23885_BOARD_DVBSKY_S952:
4669 + case CX23885_BOARD_DVBSKY_S950_CI:
4670 + case CX23885_BOARD_DVBSKY_C2800E_CI:
4671 + case CX23885_BOARD_DVBSKY_T9580:
4672 + case CX23885_BOARD_DVBSKY_T980_CI:
4673 + case CX23885_BOARD_DVBSKY_T982:
4674 + case CX23885_BOARD_TT_4500_CI:
4675 + dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE);
4676 + if (dev->sd_ir == NULL) {
4677 + ret = -ENODEV;
4678 + break;
4679 + }
4680 + v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
4681 + ir_rx_pin_cfg_count, ir_rx_pin_cfg);
4682 +
4683 + cx23885_ir_patch(&(dev->i2c_bus[2].i2c_adap),0x1f,0x80);
4684 + cx23885_ir_patch(&(dev->i2c_bus[2].i2c_adap),0x23,0x80);
4685 + break;
4686 case CX23885_BOARD_HAUPPAUGE_HVR1250:
4687 if (!enable_885_ir)
4688 break;
4689 @@ -1608,13 +1773,22 @@ void cx23885_ir_fini(struct cx23885_dev *dev)
4690 case CX23885_BOARD_MYGICA_X8507:
4691 case CX23885_BOARD_TBS_6980:
4692 case CX23885_BOARD_TBS_6981:
4693 + case CX23885_BOARD_BST_PS8512:
4694 + case CX23885_BOARD_DVBSKY_S950:
4695 + case CX23885_BOARD_DVBSKY_S952:
4696 + case CX23885_BOARD_DVBSKY_S950_CI:
4697 + case CX23885_BOARD_DVBSKY_C2800E_CI:
4698 + case CX23885_BOARD_DVBSKY_T9580:
4699 + case CX23885_BOARD_DVBSKY_T980_CI:
4700 + case CX23885_BOARD_DVBSKY_T982:
4701 + case CX23885_BOARD_TT_4500_CI:
4702 cx23885_irq_remove(dev, PCI_MSK_AV_CORE);
4703 /* sd_ir is a duplicate pointer to the AV Core, just clear it */
4704 dev->sd_ir = NULL;
4705 break;
4706 }
4707 }
4708 -
4709 +#if 0
4710 static int netup_jtag_io(void *device, int tms, int tdi, int read_tdo)
4711 {
4712 int data;
4713 @@ -1639,7 +1813,7 @@ static int netup_jtag_io(void *device, int tms, int tdi, int read_tdo)
4714
4715 return tdo;
4716 }
4717 -
4718 +#endif
4719 void cx23885_ir_pci_int_enable(struct cx23885_dev *dev)
4720 {
4721 switch (dev->board) {
4722 @@ -1655,6 +1829,15 @@ void cx23885_ir_pci_int_enable(struct cx23885_dev *dev)
4723 case CX23885_BOARD_MYGICA_X8507:
4724 case CX23885_BOARD_TBS_6980:
4725 case CX23885_BOARD_TBS_6981:
4726 + case CX23885_BOARD_BST_PS8512:
4727 + case CX23885_BOARD_DVBSKY_S950:
4728 + case CX23885_BOARD_DVBSKY_S952:
4729 + case CX23885_BOARD_DVBSKY_S950_CI:
4730 + case CX23885_BOARD_DVBSKY_C2800E_CI:
4731 + case CX23885_BOARD_DVBSKY_T9580:
4732 + case CX23885_BOARD_DVBSKY_T980_CI:
4733 + case CX23885_BOARD_DVBSKY_T982:
4734 + case CX23885_BOARD_TT_4500_CI:
4735 if (dev->sd_ir)
4736 cx23885_irq_add_enable(dev, PCI_MSK_AV_CORE);
4737 break;
4738 @@ -1752,6 +1935,12 @@ void cx23885_card_setup(struct cx23885_dev *dev)
4739 ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
4740 ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
4741 break;
4742 + case CX23885_BOARD_BST_PS8512:
4743 + case CX23885_BOARD_DVBSKY_S950:
4744 + case CX23885_BOARD_DVBSKY_S950_CI:
4745 + case CX23885_BOARD_DVBSKY_C2800E_CI:
4746 + case CX23885_BOARD_DVBSKY_T980_CI:
4747 + case CX23885_BOARD_TT_4500_CI:
4748 case CX23885_BOARD_TEVII_S470:
4749 case CX23885_BOARD_TEVII_S471:
4750 case CX23885_BOARD_DVBWORLD_2005:
4751 @@ -1795,6 +1984,23 @@ void cx23885_card_setup(struct cx23885_dev *dev)
4752 ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
4753 ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
4754 break;
4755 + case CX23885_BOARD_DVBSKY_S952:
4756 + ts1->gen_ctrl_val = 0x5; /* Parallel */
4757 + ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
4758 + ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
4759 + ts2->gen_ctrl_val = 0xe; /* Serial bus + punctured clock */
4760 + ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
4761 + ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
4762 + break;
4763 + case CX23885_BOARD_DVBSKY_T9580:
4764 + case CX23885_BOARD_DVBSKY_T982:
4765 + ts1->gen_ctrl_val = 0x5; /* Parallel */
4766 + ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
4767 + ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
4768 + ts2->gen_ctrl_val = 0x8; /* Serial bus */
4769 + ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
4770 + ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
4771 + break;
4772 case CX23885_BOARD_HAUPPAUGE_HVR4400:
4773 ts1->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */
4774 ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
4775 @@ -1860,6 +2066,15 @@ void cx23885_card_setup(struct cx23885_dev *dev)
4776 case CX23885_BOARD_AVERMEDIA_HC81R:
4777 case CX23885_BOARD_TBS_6980:
4778 case CX23885_BOARD_TBS_6981:
4779 + case CX23885_BOARD_BST_PS8512:
4780 + case CX23885_BOARD_DVBSKY_S950:
4781 + case CX23885_BOARD_DVBSKY_S952:
4782 + case CX23885_BOARD_DVBSKY_S950_CI:
4783 + case CX23885_BOARD_DVBSKY_C2800E_CI:
4784 + case CX23885_BOARD_DVBSKY_T9580:
4785 + case CX23885_BOARD_DVBSKY_T980_CI:
4786 + case CX23885_BOARD_DVBSKY_T982:
4787 + case CX23885_BOARD_TT_4500_CI:
4788 dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
4789 &dev->i2c_bus[2].i2c_adap,
4790 "cx25840", 0x88 >> 1, NULL);
4791 @@ -1879,13 +2094,13 @@ void cx23885_card_setup(struct cx23885_dev *dev)
4792 int ret;
4793 const struct firmware *fw;
4794 const char *filename = "dvb-netup-altera-01.fw";
4795 - char *action = "configure";
4796 +// char *action = "configure";
4797 static struct netup_card_info cinfo;
4798 - struct altera_config netup_config = {
4799 - .dev = dev,
4800 - .action = action,
4801 - .jtag_io = netup_jtag_io,
4802 - };
4803 +// struct altera_config netup_config = {
4804 +// .dev = dev,
4805 +// .action = action,
4806 +// .jtag_io = netup_jtag_io,
4807 +// };
4808
4809 netup_initialize(dev);
4810
4811 @@ -1909,8 +2124,8 @@ void cx23885_card_setup(struct cx23885_dev *dev)
4812 printk(KERN_ERR "did not find the firmware file. (%s) "
4813 "Please see linux/Documentation/dvb/ for more details "
4814 "on firmware-problems.", filename);
4815 - else
4816 - altera_init(&netup_config, fw);
4817 + //else
4818 + // altera_init(&netup_config, fw);
4819
4820 release_firmware(fw);
4821 break;
4822 diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c
4823 index edcd79d..c9afeab 100644
4824 --- a/drivers/media/pci/cx23885/cx23885-core.c
4825 +++ b/drivers/media/pci/cx23885/cx23885-core.c
4826 @@ -450,9 +450,9 @@ void cx23885_wakeup(struct cx23885_tsport *port,
4827 del_timer(&q->timeout);
4828 else
4829 mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
4830 - if (bc != 1)
4831 +/* if (bc != 1)
4832 printk(KERN_WARNING "%s: %d buffers handled (should be 1)\n",
4833 - __func__, bc);
4834 + __func__, bc);*/
4835 }
4836
4837 int cx23885_sram_channel_setup(struct cx23885_dev *dev,
4838 @@ -1909,6 +1909,10 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
4839 (pci_status & PCI_MSK_GPIO0))
4840 handled += altera_ci_irq(dev);
4841
4842 + if (cx23885_boards[dev->board].ci_type == 3 &&
4843 + (pci_status & PCI_MSK_GPIO0))
4844 + handled += dvbsky_ci_slot_status(dev);
4845 +
4846 if (ts1_status) {
4847 if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
4848 handled += cx23885_irq_ts(ts1, ts1_status);
4849 @@ -2141,6 +2145,10 @@ static int cx23885_initdev(struct pci_dev *pci_dev,
4850 cx23885_irq_add_enable(dev, PCI_MSK_GPIO1 | PCI_MSK_GPIO0);
4851 break;
4852 case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
4853 + case CX23885_BOARD_DVBSKY_S950_CI:
4854 + case CX23885_BOARD_DVBSKY_C2800E_CI:
4855 + case CX23885_BOARD_DVBSKY_T980_CI:
4856 + case CX23885_BOARD_TT_4500_CI:
4857 cx23885_irq_add_enable(dev, PCI_MSK_GPIO0);
4858 break;
4859 }
4860 diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
4861 index 0549205..7816112 100644
4862 --- a/drivers/media/pci/cx23885/cx23885-dvb.c
4863 +++ b/drivers/media/pci/cx23885/cx23885-dvb.c
4864 @@ -51,6 +51,8 @@
4865 #include "stv6110.h"
4866 #include "lnbh24.h"
4867 #include "cx24116.h"
4868 +#include "dvbsky_m88ds3103.h"
4869 +#include "m88dc2800.h"
4870 #include "cx24117.h"
4871 #include "cimax2.h"
4872 #include "lgs8gxx.h"
4873 @@ -473,6 +475,7 @@ static struct ds3000_config tevii_ds3000_config = {
4874 static struct ts2020_config tevii_ts2020_config = {
4875 .tuner_address = 0x60,
4876 .clk_out_div = 1,
4877 + .frequency_div = 1146000,
4878 };
4879
4880 static struct cx24116_config dvbworld_cx24116_config = {
4881 @@ -507,6 +510,93 @@ static struct xc5000_config mygica_x8507_xc5000_config = {
4882 .if_khz = 4000,
4883 };
4884
4885 +/* bst control */
4886 +int bst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
4887 +{
4888 + struct cx23885_tsport *port = fe->dvb->priv;
4889 + struct cx23885_dev *dev = port->dev;
4890 +
4891 + cx23885_gpio_enable(dev, GPIO_1, 1);
4892 + cx23885_gpio_enable(dev, GPIO_0, 1);
4893 +
4894 + switch (voltage) {
4895 + case SEC_VOLTAGE_13:
4896 + cx23885_gpio_set(dev, GPIO_1);
4897 + cx23885_gpio_clear(dev, GPIO_0);
4898 + break;
4899 + case SEC_VOLTAGE_18:
4900 + cx23885_gpio_set(dev, GPIO_1);
4901 + cx23885_gpio_set(dev, GPIO_0);
4902 + break;
4903 + case SEC_VOLTAGE_OFF:
4904 + cx23885_gpio_clear(dev, GPIO_1);
4905 + cx23885_gpio_clear(dev, GPIO_0);
4906 + break;
4907 + }
4908 + return 0;
4909 +}
4910 +
4911 +int dvbsky_set_voltage_sec(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
4912 +{
4913 + struct cx23885_tsport *port = fe->dvb->priv;
4914 + struct cx23885_dev *dev = port->dev;
4915 +
4916 + cx23885_gpio_enable(dev, GPIO_12, 1);
4917 + cx23885_gpio_enable(dev, GPIO_13, 1);
4918 +
4919 + switch (voltage) {
4920 + case SEC_VOLTAGE_13:
4921 + cx23885_gpio_set(dev, GPIO_13);
4922 + cx23885_gpio_clear(dev, GPIO_12);
4923 + break;
4924 + case SEC_VOLTAGE_18:
4925 + cx23885_gpio_set(dev, GPIO_13);
4926 + cx23885_gpio_set(dev, GPIO_12);
4927 + break;
4928 + case SEC_VOLTAGE_OFF:
4929 + cx23885_gpio_clear(dev, GPIO_13);
4930 + cx23885_gpio_clear(dev, GPIO_12);
4931 + break;
4932 + }
4933 + return 0;
4934 +}
4935 +
4936 +/* bestunar single dvb-s2 */
4937 +static struct dvbsky_m88ds3103_config bst_ds3103_config = {
4938 + .demod_address = 0x68,
4939 + .ci_mode = 0,
4940 + .pin_ctrl = 0x82,
4941 + .ts_mode = 0,
4942 + .set_voltage = bst_set_voltage,
4943 +};
4944 +/* DVBSKY dual dvb-s2 */
4945 +static struct dvbsky_m88ds3103_config dvbsky_ds3103_config_pri = {
4946 + .demod_address = 0x68,
4947 + .ci_mode = 0,
4948 + .pin_ctrl = 0x82,
4949 + .ts_mode = 0,
4950 + .set_voltage = bst_set_voltage,
4951 +};
4952 +static struct dvbsky_m88ds3103_config dvbsky_ds3103_config_sec = {
4953 + .demod_address = 0x68,
4954 + .ci_mode = 0,
4955 + .pin_ctrl = 0x82,
4956 + .ts_mode = 1,
4957 + .set_voltage = dvbsky_set_voltage_sec,
4958 +};
4959 +
4960 +static struct dvbsky_m88ds3103_config dvbsky_ds3103_ci_config = {
4961 + .demod_address = 0x68,
4962 + .ci_mode = 2,
4963 + .pin_ctrl = 0x82,
4964 + .ts_mode = 0,
4965 +};
4966 +
4967 +static struct m88dc2800_config dvbsky_dc2800_config = {
4968 + .demod_address = 0x1c,
4969 + .ts_mode = 3,
4970 +};
4971 +
4972 static struct stv090x_config prof_8000_stv090x_config = {
4973 .device = STV0903,
4974 .demod_mode = STV090x_SINGLE,
4975 @@ -1311,6 +1401,92 @@ static int dvb_register(struct cx23885_tsport *port)
4976 &tevii_ts2020_config, &i2c_bus->i2c_adap);
4977 }
4978 break;
4979 + case CX23885_BOARD_BST_PS8512:
4980 + case CX23885_BOARD_DVBSKY_S950:
4981 + i2c_bus = &dev->i2c_bus[1];
4982 + fe0->dvb.frontend = dvb_attach(dvbsky_m88ds3103_attach,
4983 + &bst_ds3103_config,
4984 + &i2c_bus->i2c_adap);
4985 + break;
4986 +
4987 + case CX23885_BOARD_DVBSKY_S952:
4988 + switch (port->nr) {
4989 + /* port B */
4990 + case 1:
4991 + i2c_bus = &dev->i2c_bus[1];
4992 + fe0->dvb.frontend = dvb_attach(dvbsky_m88ds3103_attach,
4993 + &dvbsky_ds3103_config_pri,
4994 + &i2c_bus->i2c_adap);
4995 + break;
4996 + /* port C */
4997 + case 2:
4998 + i2c_bus = &dev->i2c_bus[0];
4999 + fe0->dvb.frontend = dvb_attach(dvbsky_m88ds3103_attach,
5000 + &dvbsky_ds3103_config_sec,
5001 + &i2c_bus->i2c_adap);
5002 + break;
5003 + }
5004 + break;
5005 +
5006 + case CX23885_BOARD_DVBSKY_S950_CI:
5007 + i2c_bus = &dev->i2c_bus[1];
5008 + fe0->dvb.frontend = dvb_attach(dvbsky_m88ds3103_attach,
5009 + &dvbsky_ds3103_ci_config,
5010 + &i2c_bus->i2c_adap);
5011 + break;
5012 +
5013 + case CX23885_BOARD_DVBSKY_C2800E_CI:
5014 + i2c_bus = &dev->i2c_bus[1];
5015 + fe0->dvb.frontend = dvb_attach(m88dc2800_attach,
5016 + &dvbsky_dc2800_config,
5017 + &i2c_bus->i2c_adap);
5018 + break;
5019 +
5020 + case CX23885_BOARD_DVBSKY_T9580:
5021 + switch (port->nr) {
5022 + /* port B */
5023 + case 1:
5024 + i2c_bus = &dev->i2c_bus[1];
5025 + fe0->dvb.frontend = dvb_attach(dvbsky_m88ds3103_attach,
5026 + &dvbsky_ds3103_config_pri,
5027 + &i2c_bus->i2c_adap);
5028 + break;
5029 + /* port C */
5030 +// case 2:
5031 +// i2c_bus = &dev->i2c_bus[0];
5032 +// fe0->dvb.frontend = dvb_attach(sit2_attach,
5033 +// &dvbsky_sit2_config_pci_s,
5034 +// &i2c_bus->i2c_adap);
5035 + break;
5036 + }
5037 + break;
5038 +
5039 +// case CX23885_BOARD_DVBSKY_T980_CI:
5040 +// case CX23885_BOARD_TT_4500_CI:
5041 +// i2c_bus = &dev->i2c_bus[1];
5042 +// fe0->dvb.frontend = dvb_attach(sit2_attach,
5043 +// &dvbsky_sit2_config_pci_p,
5044 +// &i2c_bus->i2c_adap);
5045 +// break;
5046 +
5047 +// case CX23885_BOARD_DVBSKY_T982:
5048 +// switch (port->nr) {
5049 +// /* port B */
5050 +// case 1:
5051 +// i2c_bus = &dev->i2c_bus[1];
5052 +// fe0->dvb.frontend = dvb_attach(sit2_attach,
5053 +// &dvbsky_sit2_config_pci_p,
5054 +// &i2c_bus->i2c_adap);
5055 +// break;
5056 +// /* port C */
5057 +// case 2:
5058 +// i2c_bus = &dev->i2c_bus[0];
5059 +// fe0->dvb.frontend = dvb_attach(sit2_attach,
5060 +// &dvbsky_sit2_config_pci_s,
5061 +// &i2c_bus->i2c_adap);
5062 +// break;
5063 +// }
5064 +// break;
5065 case CX23885_BOARD_PROF_8000:
5066 i2c_bus = &dev->i2c_bus[0];
5067
5068 @@ -1386,7 +1562,7 @@ static int dvb_register(struct cx23885_tsport *port)
5069 printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=%pM\n",
5070 port->nr, port->frontends.adapter.proposed_mac);
5071
5072 - netup_ci_init(port);
5073 + netup_ci_init(port, false);
5074 break;
5075 }
5076 case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: {
5077 @@ -1413,6 +1589,44 @@ static int dvb_register(struct cx23885_tsport *port)
5078 memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xa0, 6);
5079 break;
5080 }
5081 + case CX23885_BOARD_BST_PS8512:
5082 + case CX23885_BOARD_DVBSKY_S950:
5083 + case CX23885_BOARD_DVBSKY_S952:
5084 + case CX23885_BOARD_DVBSKY_T9580:
5085 + case CX23885_BOARD_DVBSKY_T982:{
5086 + u8 eeprom[256]; /* 24C02 i2c eeprom */
5087 +
5088 + if(port->nr > 2)
5089 + break;
5090 +
5091 + dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
5092 + tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom));
5093 + printk(KERN_INFO "DVBSKY PCIe MAC= %pM\n", eeprom + 0xc0+(port->nr-1)*8);
5094 + memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0 +
5095 + (port->nr-1)*8, 6);
5096 + break;
5097 + }
5098 + case CX23885_BOARD_DVBSKY_S950_CI: {
5099 + u8 eeprom[256]; /* 24C02 i2c eeprom */
5100 +
5101 + if(port->nr > 2)
5102 + break;
5103 +
5104 + dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
5105 + tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom));
5106 + printk(KERN_INFO "DVBSKY PCIe MAC= %pM\n", eeprom + 0xc0+(port->nr-1)*8);
5107 + memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0 +
5108 + (port->nr-1)*8, 6);
5109 +
5110 + netup_ci_init(port, true);
5111 + break;
5112 + }
5113 + case CX23885_BOARD_DVBSKY_C2800E_CI:
5114 + case CX23885_BOARD_DVBSKY_T980_CI:
5115 + case CX23885_BOARD_TT_4500_CI: {
5116 + netup_ci_init(port, true);
5117 + break;
5118 + }
5119 }
5120
5121 return ret;
5122 @@ -1495,6 +1709,10 @@ int cx23885_dvb_unregister(struct cx23885_tsport *port)
5123
5124 switch (port->dev->board) {
5125 case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
5126 + case CX23885_BOARD_DVBSKY_S950_CI:
5127 + case CX23885_BOARD_DVBSKY_C2800E_CI:
5128 + case CX23885_BOARD_DVBSKY_T980_CI:
5129 + case CX23885_BOARD_TT_4500_CI:
5130 netup_ci_exit(port);
5131 break;
5132 case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
5133 diff --git a/drivers/media/pci/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c
5134 index 8a49e7c..1642ae8 100644
5135 --- a/drivers/media/pci/cx23885/cx23885-input.c
5136 +++ b/drivers/media/pci/cx23885/cx23885-input.c
5137 @@ -92,6 +92,15 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
5138 case CX23885_BOARD_MYGICA_X8507:
5139 case CX23885_BOARD_TBS_6980:
5140 case CX23885_BOARD_TBS_6981:
5141 + case CX23885_BOARD_BST_PS8512:
5142 + case CX23885_BOARD_DVBSKY_S950:
5143 + case CX23885_BOARD_DVBSKY_S952:
5144 + case CX23885_BOARD_DVBSKY_S950_CI:
5145 + case CX23885_BOARD_DVBSKY_C2800E_CI:
5146 + case CX23885_BOARD_DVBSKY_T9580:
5147 + case CX23885_BOARD_DVBSKY_T980_CI:
5148 + case CX23885_BOARD_DVBSKY_T982:
5149 + case CX23885_BOARD_TT_4500_CI:
5150 /*
5151 * The only boards we handle right now. However other boards
5152 * using the CX2388x integrated IR controller should be similar
5153 @@ -144,6 +153,15 @@ static int cx23885_input_ir_start(struct cx23885_dev *dev)
5154 case CX23885_BOARD_HAUPPAUGE_HVR1290:
5155 case CX23885_BOARD_HAUPPAUGE_HVR1250:
5156 case CX23885_BOARD_MYGICA_X8507:
5157 + case CX23885_BOARD_BST_PS8512:
5158 + case CX23885_BOARD_DVBSKY_S950:
5159 + case CX23885_BOARD_DVBSKY_S952:
5160 + case CX23885_BOARD_DVBSKY_S950_CI:
5161 + case CX23885_BOARD_DVBSKY_C2800E_CI:
5162 + case CX23885_BOARD_DVBSKY_T9580:
5163 + case CX23885_BOARD_DVBSKY_T980_CI:
5164 + case CX23885_BOARD_DVBSKY_T982:
5165 + case CX23885_BOARD_TT_4500_CI:
5166 /*
5167 * The IR controller on this board only returns pulse widths.
5168 * Any other mode setting will fail to set up the device.
5169 @@ -302,6 +320,26 @@ int cx23885_input_init(struct cx23885_dev *dev)
5170 /* A guess at the remote */
5171 rc_map = RC_MAP_TOTAL_MEDIA_IN_HAND_02;
5172 break;
5173 + case CX23885_BOARD_BST_PS8512:
5174 + case CX23885_BOARD_DVBSKY_S950:
5175 + case CX23885_BOARD_DVBSKY_S952:
5176 + case CX23885_BOARD_DVBSKY_S950_CI:
5177 + case CX23885_BOARD_DVBSKY_C2800E_CI:
5178 + case CX23885_BOARD_DVBSKY_T9580:
5179 + case CX23885_BOARD_DVBSKY_T980_CI:
5180 + case CX23885_BOARD_DVBSKY_T982:
5181 + /* Integrated CX2388[58] IR controller */
5182 + driver_type = RC_DRIVER_IR_RAW;
5183 + allowed_protos = RC_BIT_ALL;
5184 + /* A guess at the remote */
5185 + rc_map = RC_MAP_DVBSKY;
5186 + break;
5187 + case CX23885_BOARD_TT_4500_CI:
5188 + /* Integrated CX2388[58] IR controller */
5189 + driver_type = RC_DRIVER_IR_RAW;
5190 + allowed_protos = RC_BIT_ALL;
5191 + rc_map = RC_MAP_TT_1500;
5192 + break;
5193 case CX23885_BOARD_TBS_6980:
5194 case CX23885_BOARD_TBS_6981:
5195 /* Integrated CX23885 IR controller */
5196 diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h
5197 index 0fa4048..7a39d82 100644
5198 --- a/drivers/media/pci/cx23885/cx23885.h
5199 +++ b/drivers/media/pci/cx23885/cx23885.h
5200 @@ -97,6 +97,17 @@
5201 #define CX23885_BOARD_TBS_6980 41
5202 #define CX23885_BOARD_LEADTEK_WINFAST_PXPVR2200 42
5203
5204 +#define CX23885_BOARD_DVBSKY_PCIE 43
5205 +#define CX23885_BOARD_BST_PS8512 (CX23885_BOARD_DVBSKY_PCIE+0)
5206 +#define CX23885_BOARD_DVBSKY_S952 (CX23885_BOARD_DVBSKY_PCIE+1)
5207 +#define CX23885_BOARD_DVBSKY_S950 (CX23885_BOARD_DVBSKY_PCIE+2)
5208 +#define CX23885_BOARD_DVBSKY_S950_CI (CX23885_BOARD_DVBSKY_PCIE+3)
5209 +#define CX23885_BOARD_DVBSKY_C2800E_CI (CX23885_BOARD_DVBSKY_PCIE+4)
5210 +#define CX23885_BOARD_DVBSKY_T9580 (CX23885_BOARD_DVBSKY_PCIE+5)
5211 +#define CX23885_BOARD_DVBSKY_T980_CI (CX23885_BOARD_DVBSKY_PCIE+6)
5212 +#define CX23885_BOARD_DVBSKY_T982 (CX23885_BOARD_DVBSKY_PCIE+7)
5213 +#define CX23885_BOARD_TT_4500_CI (CX23885_BOARD_DVBSKY_PCIE+8)
5214 +
5215 #define GPIO_0 0x00000001
5216 #define GPIO_1 0x00000002
5217 #define GPIO_2 0x00000004
5218 @@ -234,7 +245,7 @@ struct cx23885_board {
5219 */
5220 u32 clk_freq;
5221 struct cx23885_input input[MAX_CX23885_INPUT];
5222 - int ci_type; /* for NetUP */
5223 + int ci_type; /* 1 and 2 for NetUP, 3 for DVBSky. */
5224 /* Force bottom field first during DMA (888 workaround) */
5225 u32 force_bff;
5226 };
5227 diff --git a/drivers/media/pci/cx88/Kconfig b/drivers/media/pci/cx88/Kconfig
5228 index a63a9ad..7deb300 100644
5229 --- a/drivers/media/pci/cx88/Kconfig
5230 +++ b/drivers/media/pci/cx88/Kconfig
5231 @@ -57,6 +57,7 @@ config VIDEO_CX88_DVB
5232 select DVB_ISL6421 if MEDIA_SUBDRV_AUTOSELECT
5233 select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT
5234 select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT
5235 + select DVB_DVBSKY_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT
5236 select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
5237 select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT
5238 select DVB_STB6000 if MEDIA_SUBDRV_AUTOSELECT
5239 diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c
5240 index e18a7ac..317511d 100644
5241 --- a/drivers/media/pci/cx88/cx88-cards.c
5242 +++ b/drivers/media/pci/cx88/cx88-cards.c
5243 @@ -2314,6 +2314,18 @@ static const struct cx88_board cx88_boards[] = {
5244 } },
5245 .mpeg = CX88_MPEG_DVB,
5246 },
5247 + [CX88_BOARD_BST_PS8312] = {
5248 + .name = "Bestunar PS8312 DVB-S/S2",
5249 + .tuner_type = UNSET,
5250 + .radio_type = UNSET,
5251 + .tuner_addr = ADDR_UNSET,
5252 + .radio_addr = ADDR_UNSET,
5253 + .input = { {
5254 + .type = CX88_VMUX_DVB,
5255 + .vmux = 0,
5256 + } },
5257 + .mpeg = CX88_MPEG_DVB,
5258 + },
5259 };
5260
5261 /* ------------------------------------------------------------------ */
5262 @@ -2818,6 +2830,10 @@ static const struct cx88_subid cx88_subids[] = {
5263 .subvendor = 0x1822,
5264 .subdevice = 0x0023,
5265 .card = CX88_BOARD_TWINHAN_VP1027_DVBS,
5266 + }, {
5267 + .subvendor = 0x14f1,
5268 + .subdevice = 0x8312,
5269 + .card = CX88_BOARD_BST_PS8312,
5270 },
5271 };
5272
5273 @@ -3551,6 +3567,12 @@ static void cx88_card_setup(struct cx88_core *core)
5274 cx_write(MO_SRST_IO, 1);
5275 msleep(100);
5276 break;
5277 + case CX88_BOARD_BST_PS8312:
5278 + cx_write(MO_GP1_IO, 0x808000);
5279 + msleep(100);
5280 + cx_write(MO_GP1_IO, 0x808080);
5281 + msleep(100);
5282 + break;
5283 } /*end switch() */
5284
5285
5286 diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c
5287 index 053ed1b..955b916 100644
5288 --- a/drivers/media/pci/cx88/cx88-dvb.c
5289 +++ b/drivers/media/pci/cx88/cx88-dvb.c
5290 @@ -54,6 +54,7 @@
5291 #include "stv0288.h"
5292 #include "stb6000.h"
5293 #include "cx24116.h"
5294 +#include "dvbsky_m88ds3103.h"
5295 #include "stv0900.h"
5296 #include "stb6100.h"
5297 #include "stb6100_proc.h"
5298 @@ -459,6 +460,56 @@ static int tevii_dvbs_set_voltage(struct dvb_frontend *fe,
5299 return core->prev_set_voltage(fe, voltage);
5300 return 0;
5301 }
5302 +/*CX88_BOARD_BST_PS8312*/
5303 +static int bst_dvbs_set_voltage(struct dvb_frontend *fe,
5304 + fe_sec_voltage_t voltage)
5305 +{
5306 + struct cx8802_dev *dev= fe->dvb->priv;
5307 + struct cx88_core *core = dev->core;
5308 +
5309 + cx_write(MO_GP1_IO, 0x111111);
5310 + switch (voltage) {
5311 + case SEC_VOLTAGE_13:
5312 + cx_write(MO_GP1_IO, 0x020200);
5313 + break;
5314 + case SEC_VOLTAGE_18:
5315 + cx_write(MO_GP1_IO, 0x020202);
5316 + break;
5317 + case SEC_VOLTAGE_OFF:
5318 + cx_write(MO_GP1_IO, 0x111100);
5319 + break;
5320 + }
5321 +
5322 + if (core->prev_set_voltage)
5323 + return core->prev_set_voltage(fe, voltage);
5324 + return 0;
5325 +}
5326 +
5327 +static int bst_dvbs_set_voltage_v2(struct dvb_frontend *fe,
5328 + fe_sec_voltage_t voltage)
5329 +{
5330 + struct cx8802_dev *dev= fe->dvb->priv;
5331 + struct cx88_core *core = dev->core;
5332 +
5333 + cx_write(MO_GP1_IO, 0x111101);
5334 + switch (voltage) {
5335 + case SEC_VOLTAGE_13:
5336 + cx_write(MO_GP1_IO, 0x020200);
5337 + break;
5338 + case SEC_VOLTAGE_18:
5339 +
5340 + cx_write(MO_GP1_IO, 0x020202);
5341 + break;
5342 + case SEC_VOLTAGE_OFF:
5343 +
5344 + cx_write(MO_GP1_IO, 0x111110);
5345 + break;
5346 + }
5347 +
5348 + if (core->prev_set_voltage)
5349 + return core->prev_set_voltage(fe, voltage);
5350 + return 0;
5351 +}
5352
5353 static int vp1027_set_voltage(struct dvb_frontend *fe,
5354 fe_sec_voltage_t voltage)
5355 @@ -706,6 +757,11 @@ static struct ts2020_config tevii_ts2020_config = {
5356 .clk_out_div = 1,
5357 };
5358
5359 +static struct dvbsky_m88ds3103_config dvbsky_ds3103_config = {
5360 + .demod_address = 0x68,
5361 + .set_ts_params = ds3000_set_ts_param,
5362 +};
5363 +
5364 static const struct stv0900_config prof_7301_stv0900_config = {
5365 .demod_address = 0x6a,
5366 /* demod_mode = 0,*/
5367 @@ -1487,6 +1543,35 @@ static int dvb_register(struct cx8802_dev *dev)
5368 tevii_dvbs_set_voltage;
5369 }
5370 break;
5371 + case CX88_BOARD_BST_PS8312:
5372 + fe0->dvb.frontend = dvb_attach(dvbsky_m88ds3103_attach,
5373 + &dvbsky_ds3103_config,
5374 + &core->i2c_adap);
5375 + if (fe0->dvb.frontend != NULL){
5376 + int ret;
5377 + u8 b0[] = { 0x60 };
5378 + u8 b1[2] = { 0 };
5379 + struct i2c_msg msg[] = {
5380 + {
5381 + .addr = 0x50,
5382 + .flags = 0,
5383 + .buf = b0,
5384 + .len = 1
5385 + }, {
5386 + .addr = 0x50,
5387 + .flags = I2C_M_RD,
5388 + .buf = b1,
5389 + .len = 2
5390 + }
5391 + };
5392 + ret = i2c_transfer(&core->i2c_adap, msg, 2);
5393 + printk("PS8312: config = %02x, %02x", b1[0],b1[1]);
5394 + if(b1[0] == 0xaa)
5395 + fe0->dvb.frontend->ops.set_voltage = bst_dvbs_set_voltage_v2;
5396 + else
5397 + fe0->dvb.frontend->ops.set_voltage = bst_dvbs_set_voltage;
5398 + }
5399 + break;
5400 case CX88_BOARD_OMICOM_SS4_PCI:
5401 case CX88_BOARD_TBS_8920:
5402 case CX88_BOARD_PROF_7300:
5403 diff --git a/drivers/media/pci/cx88/cx88-input.c b/drivers/media/pci/cx88/cx88-input.c
5404 index f29e18c..9581f4e 100644
5405 --- a/drivers/media/pci/cx88/cx88-input.c
5406 +++ b/drivers/media/pci/cx88/cx88-input.c
5407 @@ -129,7 +129,7 @@ static void cx88_ir_handle_key(struct cx88_IR *ir)
5408 u32 gpio_key = cx_read(MO_GP0_IO);
5409
5410 data = (data << 4) | ((gpio_key & 0xf0) >> 4);
5411 -
5412 +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0)
5413 rc_keydown(ir->dev, data, 0);
5414
5415 } else if (ir->mask_keydown) {
5416 @@ -151,6 +151,45 @@ static void cx88_ir_handle_key(struct cx88_IR *ir)
5417 rc_keydown_notimeout(ir->dev, data, 0);
5418 rc_keyup(ir->dev);
5419 }
5420 +#else
5421 + rc_keydown(ir->dev, RC_TYPE_UNKNOWN, data, 0);
5422 +
5423 + } else if (ir->core->boardnr == CX88_BOARD_PROLINK_PLAYTVPVR ||
5424 + ir->core->boardnr == CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO) {
5425 + /* bit cleared on keydown, NEC scancode, 0xAAAACC, A = 0x866b */
5426 + u16 addr;
5427 + u8 cmd;
5428 + u32 scancode;
5429 +
5430 + addr = (data >> 8) & 0xffff;
5431 + cmd = (data >> 0) & 0x00ff;
5432 + scancode = RC_SCANCODE_NECX(addr, cmd);
5433 +
5434 + if (0 == (gpio & ir->mask_keyup))
5435 + rc_keydown_notimeout(ir->dev, RC_TYPE_NEC, scancode, 0);
5436 + else
5437 + rc_keyup(ir->dev);
5438 +
5439 + } else if (ir->mask_keydown) {
5440 + /* bit set on keydown */
5441 + if (gpio & ir->mask_keydown)
5442 + rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
5443 + else
5444 + rc_keyup(ir->dev);
5445 +
5446 + } else if (ir->mask_keyup) {
5447 + /* bit cleared on keydown */
5448 + if (0 == (gpio & ir->mask_keyup))
5449 + rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
5450 + else
5451 + rc_keyup(ir->dev);
5452 +
5453 + } else {
5454 + /* can't distinguish keydown/up :-/ */
5455 + rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
5456 + rc_keyup(ir->dev);
5457 + }
5458 +#endif
5459 }
5460
5461 static enum hrtimer_restart cx88_ir_work(struct hrtimer *timer)
5462 @@ -419,6 +458,10 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
5463 rc_type = RC_BIT_NEC;
5464 ir->sampling = 0xff00; /* address */
5465 break;
5466 + case CX88_BOARD_BST_PS8312:
5467 + ir_codes = RC_MAP_DVBSKY;
5468 + ir->sampling = 0xff00; /* address */
5469 + break;
5470 }
5471
5472 if (!ir_codes) {
5473 @@ -471,7 +514,6 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
5474 dev->driver_type = RC_DRIVER_SCANCODE;
5475 dev->allowed_protos = rc_type;
5476 }
5477 -
5478 ir->core = core;
5479 core->ir = ir;
5480
5481 @@ -538,8 +580,12 @@ void cx88_ir_irq(struct cx88_core *core)
5482 }
5483 ir_raw_event_handle(ir->dev);
5484 }
5485 -
5486 +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0)
5487 static int get_key_pvr2000(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
5488 +#else
5489 +static int get_key_pvr2000(struct IR_i2c *ir, enum rc_type *protocol,
5490 + u32 *scancode, u8 *toggle)
5491 +#endif
5492 {
5493 int flags, code;
5494
5495 @@ -562,9 +608,14 @@ static int get_key_pvr2000(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
5496
5497 dprintk("IR Key/Flags: (0x%02x/0x%02x)\n",
5498 code & 0xff, flags & 0xff);
5499 -
5500 +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0)
5501 *ir_key = code & 0xff;
5502 *ir_raw = code;
5503 +#else
5504 + *protocol = RC_TYPE_UNKNOWN;
5505 + *scancode = code & 0xff;
5506 + *toggle = 0;
5507 +#endif
5508 return 1;
5509 }
5510
5511 diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
5512 index 28893a6..5fa5f48 100644
5513 --- a/drivers/media/pci/cx88/cx88.h
5514 +++ b/drivers/media/pci/cx88/cx88.h
5515 @@ -237,6 +237,7 @@ extern const struct sram_channel cx88_sram_channels[];
5516 #define CX88_BOARD_WINFAST_DTV1800H_XC4000 88
5517 #define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36 89
5518 #define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43 90
5519 +#define CX88_BOARD_BST_PS8312 91
5520
5521 enum cx88_itype {
5522 CX88_VMUX_COMPOSITE1 = 1,
5523 diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile
5524 index 0b8c549..abf6079 100644
5525 --- a/drivers/media/rc/keymaps/Makefile
5526 +++ b/drivers/media/rc/keymaps/Makefile
5527 @@ -28,6 +28,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
5528 rc-dm1105-nec.o \
5529 rc-dntv-live-dvb-t.o \
5530 rc-dntv-live-dvbt-pro.o \
5531 + rc-dvbsky.o \
5532 rc-em-terratec.o \
5533 rc-encore-enltv2.o \
5534 rc-encore-enltv.o \
5535 diff --git a/drivers/media/rc/keymaps/rc-dvbsky.c b/drivers/media/rc/keymaps/rc-dvbsky.c
5536 new file mode 100644
5537 index 0000000..bfc41fb
5538 --- /dev/null
5539 +++ b/drivers/media/rc/keymaps/rc-dvbsky.c
5540 @@ -0,0 +1,78 @@
5541 +/* rc-dvbsky.c - Keytable for Dvbsky Remote Controllers
5542 + *
5543 + * keymap imported from ir-keymaps.c
5544 + *
5545 + *
5546 + * Copyright (c) 2010-2012 by Nibble Max <nibble.max@gmail.com>
5547 + *
5548 + * This program is free software; you can redistribute it and/or modify
5549 + * it under the terms of the GNU General Public License as published by
5550 + * the Free Software Foundation; either version 2 of the License, or
5551 + * (at your option) any later version.
5552 + */
5553 +
5554 +#include <media/rc-map.h>
5555 +#include <linux/module.h>
5556 +/*
5557 + * This table contains the complete RC5 code, instead of just the data part
5558 + */
5559 +
5560 +static struct rc_map_table rc5_dvbsky[] = {
5561 + { 0x0000, KEY_0 },
5562 + { 0x0001, KEY_1 },
5563 + { 0x0002, KEY_2 },
5564 + { 0x0003, KEY_3 },
5565 + { 0x0004, KEY_4 },
5566 + { 0x0005, KEY_5 },
5567 + { 0x0006, KEY_6 },
5568 + { 0x0007, KEY_7 },
5569 + { 0x0008, KEY_8 },
5570 + { 0x0009, KEY_9 },
5571 + { 0x000a, KEY_MUTE },
5572 + { 0x000d, KEY_OK },
5573 + { 0x000b, KEY_STOP },
5574 + { 0x000c, KEY_EXIT },
5575 + { 0x000e, KEY_CAMERA }, /*Snap shot*/
5576 + { 0x000f, KEY_SUBTITLE }, /*PIP*/
5577 + { 0x0010, KEY_VOLUMEUP },
5578 + { 0x0011, KEY_VOLUMEDOWN },
5579 + { 0x0012, KEY_FAVORITES },
5580 + { 0x0013, KEY_LIST }, /*Info*/
5581 + { 0x0016, KEY_PAUSE },
5582 + { 0x0017, KEY_PLAY },
5583 + { 0x001f, KEY_RECORD },
5584 + { 0x0020, KEY_CHANNELDOWN },
5585 + { 0x0021, KEY_CHANNELUP },
5586 + { 0x0025, KEY_POWER2 },
5587 + { 0x0026, KEY_REWIND },
5588 + { 0x0027, KEY_FASTFORWARD },
5589 + { 0x0029, KEY_LAST },
5590 + { 0x002b, KEY_MENU },
5591 + { 0x002c, KEY_EPG },
5592 + { 0x002d, KEY_ZOOM },
5593 +};
5594 +
5595 +static struct rc_map_list rc5_dvbsky_map = {
5596 + .map = {
5597 + .scan = rc5_dvbsky,
5598 + .size = ARRAY_SIZE(rc5_dvbsky),
5599 + .rc_type = RC_TYPE_RC5,
5600 + .name = RC_MAP_DVBSKY,
5601 + }
5602 +};
5603 +
5604 +static int __init init_rc_map_rc5_dvbsky(void)
5605 +{
5606 + return rc_map_register(&rc5_dvbsky_map);
5607 +}
5608 +
5609 +static void __exit exit_rc_map_rc5_dvbsky(void)
5610 +{
5611 + rc_map_unregister(&rc5_dvbsky_map);
5612 +}
5613 +
5614 +module_init(init_rc_map_rc5_dvbsky)
5615 +module_exit(exit_rc_map_rc5_dvbsky)
5616 +
5617 +MODULE_LICENSE("GPL");
5618 +MODULE_AUTHOR("Nibble Max <nibble.max@gmail.com>");
5619 diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig
5620 index 2059d0c..5ff51aa 100644
5621 --- a/drivers/media/usb/dvb-usb-v2/Kconfig
5622 +++ b/drivers/media/usb/dvb-usb-v2/Kconfig
5623 @@ -147,3 +147,11 @@ config DVB_USB_RTL28XXU
5624 help
5625 Say Y here to support the Realtek RTL28xxU DVB USB receiver.
5626
5627 +config DVB_USB_DVBSKY
5628 + tristate "DVBSky USB2.0 support"
5629 + depends on DVB_USB_V2
5630 + select DVB_SIT2 if MEDIA_SUBDRV_AUTOSELECT
5631 + select DVB_DVBSKY_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT
5632 + help
5633 + Say Y here to support the USB receivers from DVBSky.
5634 +
5635 diff --git a/drivers/media/usb/dvb-usb-v2/Makefile b/drivers/media/usb/dvb-usb-v2/Makefile
5636 index 2c06714..926f12d 100644
5637 --- a/drivers/media/usb/dvb-usb-v2/Makefile
5638 +++ b/drivers/media/usb/dvb-usb-v2/Makefile
5639 @@ -40,6 +40,9 @@ obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o
5640 dvb-usb-rtl28xxu-objs := rtl28xxu.o
5641 obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o
5642
5643 +dvb-usb-dvbsky-objs := dvbsky.o
5644 +obj-$(CONFIG_DVB_USB_DVBSKY) += dvb-usb-dvbsky.o
5645 +
5646 ccflags-y += -I$(srctree)/drivers/media/dvb-core
5647 ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
5648 ccflags-y += -I$(srctree)/drivers/media/tuners
5649 diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c
5650 new file mode 100644
5651 index 0000000..cd9c039
5652 --- /dev/null
5653 +++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c
5654 @@ -0,0 +1,892 @@
5655 +/*
5656 + * Driver for DVBSky receiver
5657 + *
5658 + * Copyright (C) 2013 Max nibble <nibble.max@gmail.com>
5659 + *
5660 + * CIMax code is copied and modified from:
5661 + * CIMax2(R) SP2 driver in conjunction with NetUp Dual DVB-S2 CI card
5662 + * Copyright (C) 2009 NetUP Inc.
5663 + * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
5664 + * Copyright (C) 2009 Abylay Ospan <aospan@netup.ru>
5665 + *
5666 + * This program is free software; you can redistribute it and/or modify
5667 + * it under the terms of the GNU General Public License as published by
5668 + * the Free Software Foundation; either version 2 of the License, or
5669 + * (at your option) any later version.
5670 + *
5671 + * This program is distributed in the hope that it will be useful,
5672 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5673 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5674 + * GNU General Public License for more details.
5675 + *
5676 + * You should have received a copy of the GNU General Public License
5677 + * along with this program; if not, write to the Free Software
5678 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
5679 + */
5680 +
5681 +#include "dvb_ca_en50221.h"
5682 +#include "dvb_usb.h"
5683 +#include "dvbsky_m88ds3103.h"
5684 +
5685 +static int dvbsky_debug;
5686 +module_param(dvbsky_debug, int, 0644);
5687 +MODULE_PARM_DESC(dvbsky_debug, "Activates dvbsky usb debugging (default:0)");
5688 +
5689 +#define DVBSKY_MSG_DELAY 0/*2000*/
5690 +#define DVBSKY_CI_CTL 0x04
5691 +#define DVBSKY_CI_RD 1
5692 +#define DVBSKY_BUF_LEN 64
5693 +
5694 +#define dprintk(args...) \
5695 + do { \
5696 + if (dvbsky_debug) \
5697 + printk(KERN_INFO "dvbsky_usb: " args); \
5698 + } while (0)
5699 +
5700 +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
5701 +
5702 +struct dvbsky_state {
5703 + struct mutex stream_mutex;
5704 + u8 ibuf[DVBSKY_BUF_LEN];
5705 + u8 obuf[DVBSKY_BUF_LEN];
5706 + u8 has_ci;
5707 + u8 ci_attached;
5708 + struct dvb_ca_en50221 ci;
5709 + unsigned long next_status_checked_time;
5710 + u8 ci_i2c_addr;
5711 + u8 current_ci_flag;
5712 + int ci_status;
5713 +};
5714 +
5715 +static int dvbsky_usb_generic_rw(struct dvb_usb_device *d,
5716 + u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
5717 +{
5718 + int ret;
5719 + struct dvbsky_state *state = d_to_priv(d);
5720 +
5721 + mutex_lock(&d->usb_mutex);
5722 + if (wlen != 0)
5723 + memcpy(state->obuf, wbuf, wlen);
5724 +
5725 + ret = dvb_usbv2_generic_rw_locked(d, state->obuf, wlen,
5726 + state->ibuf, rlen);
5727 +
5728 + if (!ret && (rlen != 0))
5729 + memcpy(rbuf, state->ibuf, rlen);
5730 +
5731 + mutex_unlock(&d->usb_mutex);
5732 + return ret;
5733 +}
5734 +
5735 +static int dvbsky_stream_ctrl(struct dvb_usb_device *d, u8 onoff)
5736 +{
5737 + struct dvbsky_state *state = d_to_priv(d);
5738 + int ret;
5739 + u8 obuf_pre[3] = { 0x37, 0, 0 };
5740 + u8 obuf_post[3] = { 0x36, 3, 0 };
5741 + dprintk("%s() -off \n", __func__);
5742 + mutex_lock(&state->stream_mutex);
5743 + ret = dvbsky_usb_generic_rw(d, obuf_pre, 3, NULL, 0);
5744 + if (!ret && onoff) {
5745 + msleep(20);
5746 + ret = dvbsky_usb_generic_rw(d, obuf_post, 3, NULL, 0);
5747 + dprintk("%s() -on \n", __func__);
5748 + }
5749 + mutex_unlock(&state->stream_mutex);
5750 + return ret;
5751 +}
5752 +
5753 +/* CI opertaions */
5754 +static int dvbsky_ci_read_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
5755 + u8 *buf, int len)
5756 +{
5757 + int ret;
5758 + struct i2c_msg msg[] = {
5759 + {
5760 + .addr = addr,
5761 + .flags = 0,
5762 + .buf = &reg,
5763 + .len = 1
5764 + }, {
5765 + .addr = addr,
5766 + .flags = I2C_M_RD,
5767 + .buf = buf,
5768 + .len = len
5769 + }
5770 + };
5771 +
5772 + ret = i2c_transfer(i2c_adap, msg, 2);
5773 +
5774 + if (ret != 2) {
5775 + dprintk("%s: error, Reg = 0x%02x, Status = %d\n", __func__, reg, ret);
5776 + return -1;
5777 + }
5778 + return 0;
5779 +}
5780 +
5781 +static int dvbsky_ci_write_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
5782 + u8 *buf, int len)
5783 +{
5784 + int ret;
5785 + u8 buffer[64];
5786 +
5787 + struct i2c_msg msg = {
5788 + .addr = addr,
5789 + .flags = 0,
5790 + .buf = &buffer[0],
5791 + .len = len + 1
5792 + };
5793 +
5794 + if(len + 1 > sizeof(buffer)) {
5795 + dprintk("%s: len overflow.\n", __func__);
5796 + return -1;
5797 + }
5798 +
5799 + buffer[0] = reg;
5800 + memcpy(&buffer[1], buf, len);
5801 +
5802 + ret = i2c_transfer(i2c_adap, &msg, 1);
5803 +
5804 + if (ret != 1) {
5805 + dprintk("%s: error, Reg=[0x%02x], Status=%d\n", __func__, reg, ret);
5806 + return -1;
5807 + }
5808 + return 0;
5809 +}
5810 +
5811 +static int dvbsky_ci_op_cam(struct dvb_ca_en50221 *ci, int slot,
5812 + u8 flag, u8 read, int addr, u8 data)
5813 +{
5814 + struct dvb_usb_device *d = ci->data;
5815 + struct dvbsky_state *state = d_to_priv(d);
5816 + u8 store;
5817 + int ret;
5818 + u8 command[4], respond[2], command_size, respond_size;
5819 +
5820 + /*dprintk("%s()\n", __func__);*/
5821 + if (0 != slot)
5822 + return -EINVAL;
5823 +
5824 + if (state->current_ci_flag != flag) {
5825 + ret = dvbsky_ci_read_i2c(&d->i2c_adap, state->ci_i2c_addr,
5826 + 0, &store, 1);
5827 + if (ret != 0)
5828 + return ret;
5829 +
5830 + store &= ~0x0c;
5831 + store |= flag;
5832 +
5833 + ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr,
5834 + 0, &store, 1);
5835 + if (ret != 0)
5836 + return ret;
5837 + }
5838 + state->current_ci_flag = flag;
5839 +
5840 + command[1] = (u8)((addr >> 8) & 0xff); /*high part of address*/
5841 + command[2] = (u8)(addr & 0xff); /*low part of address*/
5842 + if (read) {
5843 + command[0] = 0x71;
5844 + command_size = 3;
5845 + respond_size = 2;
5846 + } else {
5847 + command[0] = 0x70;
5848 + command[3] = data;
5849 + command_size = 4;
5850 + respond_size = 1;
5851 + }
5852 + ret = dvbsky_usb_generic_rw(d, command, command_size, respond, respond_size);
5853 + if(ret)
5854 + dev_err(&d->udev->dev, "%s: %s() " \
5855 + "failed=%d\n", KBUILD_MODNAME, __func__, ret);
5856 +
5857 + return (read) ? respond[1] : 0;
5858 +}
5859 +
5860 +static int dvbsky_ci_read_attribute_mem(struct dvb_ca_en50221 *ci,
5861 + int slot, int addr)
5862 +{
5863 + return dvbsky_ci_op_cam(ci, slot, 0, DVBSKY_CI_RD, addr, 0);
5864 +}
5865 +
5866 +static int dvbsky_ci_write_attribute_mem(struct dvb_ca_en50221 *ci,
5867 + int slot, int addr, u8 data)
5868 +{
5869 + return dvbsky_ci_op_cam(ci, slot, 0, 0, addr, data);
5870 +}
5871 +
5872 +static int dvbsky_ci_read_cam_ctl(struct dvb_ca_en50221 *ci, int slot, u8 addr)
5873 +{
5874 + return dvbsky_ci_op_cam(ci, slot, DVBSKY_CI_CTL, DVBSKY_CI_RD, addr, 0);
5875 +}
5876 +
5877 +static int dvbsky_ci_write_cam_ctl(struct dvb_ca_en50221 *ci, int slot,
5878 + u8 addr, u8 data)
5879 +{
5880 + return dvbsky_ci_op_cam(ci, slot, DVBSKY_CI_CTL, 0, addr, data);
5881 +}
5882 +
5883 +static int dvbsky_ci_slot_reset(struct dvb_ca_en50221 *ci, int slot)
5884 +{
5885 + struct dvb_usb_device *d = ci->data;
5886 + struct dvbsky_state *state = d_to_priv(d);
5887 + u8 buf = 0x80;
5888 + int ret;
5889 + dprintk("%s() slot=%d\n", __func__, slot);
5890 +
5891 + if (0 != slot)
5892 + return -EINVAL;
5893 +
5894 + udelay(500);
5895 + ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr,
5896 + 0, &buf, 1);
5897 +
5898 + if (ret != 0)
5899 + return ret;
5900 +
5901 + udelay(500);
5902 +
5903 + buf = 0x00;
5904 + ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr,
5905 + 0, &buf, 1);
5906 + msleep(1000);
5907 + dprintk("%s() slot=%d complete\n", __func__, slot);
5908 + return 0;
5909 +
5910 +}
5911 +
5912 +static int dvbsky_ci_slot_shutdown(struct dvb_ca_en50221 *ci, int slot)
5913 +{
5914 + /* not implemented */
5915 + dprintk("%s()\n", __func__);
5916 + return 0;
5917 +}
5918 +
5919 +static int dvbsky_ci_slot_ts_enable(struct dvb_ca_en50221 *ci, int slot)
5920 +{
5921 + struct dvb_usb_device *d = ci->data;
5922 + struct dvbsky_state *state = d_to_priv(d);
5923 + u8 buf;
5924 + int ret;
5925 +
5926 + dprintk("%s()\n", __func__);
5927 + if (0 != slot)
5928 + return -EINVAL;
5929 +
5930 + dvbsky_ci_read_i2c(&d->i2c_adap, state->ci_i2c_addr,
5931 + 0, &buf, 1);
5932 + buf |= 0x60;
5933 +
5934 + ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr,
5935 + 0, &buf, 1);
5936 + return ret;
5937 +}
5938 +
5939 +static int dvbsky_ci_poll_slot_status(struct dvb_ca_en50221 *ci, int slot,
5940 + int open)
5941 +{
5942 + struct dvb_usb_device *d = ci->data;
5943 + struct dvbsky_state *state = d_to_priv(d);
5944 + int ret = 0;
5945 + u8 buf = 0;
5946 + /*dprintk("%s()\n", __func__);*/
5947 +
5948 + /* CAM module INSERT/REMOVE processing. slow operation because of i2c
5949 + * transfers */
5950 + if (time_after(jiffies, state->next_status_checked_time)) {
5951 + ret = dvbsky_ci_read_i2c(&d->i2c_adap, state->ci_i2c_addr,
5952 + 0, &buf, 1);
5953 +
5954 + /*dprintk("%s() status=%x\n", __func__, buf);*/
5955 +
5956 + state->next_status_checked_time = jiffies
5957 + + msecs_to_jiffies(1000);
5958 +
5959 + if (ret != 0)
5960 + return 0;
5961 +
5962 + if (buf & 1) {
5963 + state->ci_status = DVB_CA_EN50221_POLL_CAM_PRESENT |
5964 + DVB_CA_EN50221_POLL_CAM_READY;
5965 + }
5966 + else
5967 + state->ci_status = 0;
5968 + }
5969 + /*dprintk("%s() ret=%x\n", __func__, state->ci_status);*/
5970 + return state->ci_status;
5971 +}
5972 +
5973 +static int dvbsky_ci_init(struct dvb_usb_device *d)
5974 +{
5975 + struct dvbsky_state *state = d_to_priv(d);
5976 + int ret;
5977 + u8 cimax_init[34] = {
5978 + 0x00, /* module A control*/
5979 + 0x00, /* auto select mask high A */
5980 + 0x00, /* auto select mask low A */
5981 + 0x00, /* auto select pattern high A */
5982 + 0x00, /* auto select pattern low A */
5983 + 0x44, /* memory access time A */
5984 + 0x00, /* invert input A */
5985 + 0x00, /* RFU */
5986 + 0x00, /* RFU */
5987 + 0x00, /* module B control*/
5988 + 0x00, /* auto select mask high B */
5989 + 0x00, /* auto select mask low B */
5990 + 0x00, /* auto select pattern high B */
5991 + 0x00, /* auto select pattern low B */
5992 + 0x44, /* memory access time B */
5993 + 0x00, /* invert input B */
5994 + 0x00, /* RFU */
5995 + 0x00, /* RFU */
5996 + 0x00, /* auto select mask high Ext */
5997 + 0x00, /* auto select mask low Ext */
5998 + 0x00, /* auto select pattern high Ext */
5999 + 0x00, /* auto select pattern low Ext */
6000 + 0x00, /* RFU */
6001 + 0x02, /* destination - module A */
6002 + 0x01, /* power on (use it like store place) */
6003 + 0x00, /* RFU */
6004 + 0x00, /* int status read only */
6005 + 0x00, /* Max: Disable the interrupt in USB solution.*/
6006 + 0x05, /* EXTINT=active-high, INT=push-pull */
6007 + 0x00, /* USCG1 */
6008 + 0x04, /* ack active low */
6009 + 0x00, /* LOCK = 0 */
6010 + 0x22, /* serial mode, rising in, rising out, MSB first*/
6011 + 0x00 /* synchronization */
6012 + };
6013 + dprintk("%s()\n", __func__);
6014 + state->current_ci_flag = 0xff;
6015 + state->ci_status = 0;
6016 + state->next_status_checked_time = jiffies + msecs_to_jiffies(1000);
6017 + state->ci_i2c_addr = 0x40;
6018 +
6019 + state->ci.owner = THIS_MODULE;
6020 + state->ci.read_attribute_mem = dvbsky_ci_read_attribute_mem;
6021 + state->ci.write_attribute_mem = dvbsky_ci_write_attribute_mem;
6022 + state->ci.read_cam_control = dvbsky_ci_read_cam_ctl;
6023 + state->ci.write_cam_control = dvbsky_ci_write_cam_ctl;
6024 + state->ci.slot_reset = dvbsky_ci_slot_reset;
6025 + state->ci.slot_shutdown = dvbsky_ci_slot_shutdown;
6026 + state->ci.slot_ts_enable = dvbsky_ci_slot_ts_enable;
6027 + state->ci.poll_slot_status = dvbsky_ci_poll_slot_status;
6028 + state->ci.data = d;
6029 +
6030 + ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr,
6031 + 0, &cimax_init[0], 34);
6032 + /* lock registers */
6033 + ret |= dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr,
6034 + 0x1f, &cimax_init[0x18], 1);
6035 + /* power on slots */
6036 + ret |= dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr,
6037 + 0x18, &cimax_init[0x18], 1);
6038 + if (0 != ret)
6039 + return ret;
6040 +
6041 + ret = dvb_ca_en50221_init(&d->adapter[0].dvb_adap, &state->ci, 0, 1);
6042 + if (ret)
6043 + return ret;
6044 + state->ci_attached = 1;
6045 + dprintk("%s() complete.\n", __func__);
6046 + return 0;
6047 +}
6048 +
6049 +static void dvbsky_ci_release(struct dvb_usb_device *d)
6050 +{
6051 + struct dvbsky_state *state = d_to_priv(d);
6052 +
6053 + /* detach CI */
6054 + if (state->ci_attached)
6055 + dvb_ca_en50221_release(&state->ci);
6056 +
6057 + return;
6058 +}
6059 +
6060 +static int dvbsky_streaming_ctrl(struct dvb_frontend *fe, int onoff)
6061 +{
6062 + struct dvb_usb_device *d = fe_to_d(fe);
6063 + /*dprintk("%s() %d\n", __func__, onoff);*/
6064 + return dvbsky_stream_ctrl(d, (onoff == 0) ? 0 : 1);
6065 +}
6066 +
6067 +/* GPIO */
6068 +static int dvbsky_gpio_ctrl(struct dvb_usb_device *d, u8 gport, u8 value)
6069 +{
6070 + int ret;
6071 + u8 obuf[64], ibuf[64];
6072 + obuf[0] = 0x0e;
6073 + obuf[1] = gport;
6074 + obuf[2] = value;
6075 + ret = dvbsky_usb_generic_rw(d, obuf, 3, ibuf, 1);
6076 + if(ret)
6077 + dev_err(&d->udev->dev, "%s: %s() " \
6078 + "failed=%d\n", KBUILD_MODNAME, __func__, ret);
6079 + return ret;
6080 +}
6081 +
6082 +/* I2C */
6083 +static int dvbsky_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
6084 + int num)
6085 +{
6086 + struct dvb_usb_device *d = i2c_get_adapdata(adap);
6087 + int ret = 0;
6088 + u8 ibuf[64], obuf[64];
6089 +
6090 + if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
6091 + return -EAGAIN;
6092 +
6093 + if (num > 2) {
6094 + printk(KERN_ERR "dvbsky_usb: too many i2c messages[%d] than 2.", num);
6095 + ret = -EOPNOTSUPP;
6096 + goto i2c_error;
6097 + }
6098 +
6099 + if(num == 1) {
6100 + if (msg[0].len > 60) {
6101 + printk(KERN_ERR "dvbsky_usb: too many i2c bytes[%d] than 60.", msg[0].len);
6102 + ret = -EOPNOTSUPP;
6103 + goto i2c_error;
6104 + }
6105 + if (msg[0].flags & I2C_M_RD) {
6106 + /* single read */
6107 + obuf[0] = 0x09;
6108 + obuf[1] = 0;
6109 + obuf[2] = msg[0].len;
6110 + obuf[3] = msg[0].addr;
6111 + ret = dvbsky_usb_generic_rw(d, obuf, 4, ibuf, msg[0].len + 1);
6112 + if(ret)
6113 + dev_err(&d->udev->dev, "%s: %s() " \
6114 + "failed=%d\n", KBUILD_MODNAME, __func__, ret);
6115 + /*dprintk("%s(): read status = %d\n", __func__, ibuf[0]);*/
6116 + if (!ret)
6117 + memcpy(msg[0].buf, &ibuf[1], msg[0].len);
6118 + } else {
6119 + /* write */
6120 + obuf[0] = 0x08;
6121 + obuf[1] = msg[0].addr;
6122 + obuf[2] = msg[0].len;
6123 + memcpy(&obuf[3], msg[0].buf, msg[0].len);
6124 + ret = dvbsky_usb_generic_rw(d, obuf, msg[0].len + 3, ibuf, 1);
6125 + if(ret)
6126 + dev_err(&d->udev->dev, "%s: %s() " \
6127 + "failed=%d\n", KBUILD_MODNAME, __func__, ret);
6128 + /*dprintk("%s(): write status = %d\n", __func__, ibuf[0]);*/
6129 + }
6130 + } else {
6131 + if ((msg[0].len > 60) || (msg[1].len > 60)) {
6132 + printk(KERN_ERR "dvbsky_usb: too many i2c bytes[w-%d][r-%d] than 60.", msg[0].len, msg[1].len);
6133 + ret = -EOPNOTSUPP;
6134 + goto i2c_error;
6135 + }
6136 + /* write then read */
6137 + obuf[0] = 0x09;
6138 + obuf[1] = msg[0].len;
6139 + obuf[2] = msg[1].len;
6140 + obuf[3] = msg[0].addr;
6141 + memcpy(&obuf[4], msg[0].buf, msg[0].len);
6142 + ret = dvbsky_usb_generic_rw(d, obuf, msg[0].len + 4, ibuf, msg[1].len + 1);
6143 + if(ret)
6144 + dev_err(&d->udev->dev, "%s: %s() " \
6145 + "failed=%d\n", KBUILD_MODNAME, __func__, ret);
6146 + /*dprintk("%s(): write then read status = %d\n", __func__, ibuf[0]);*/
6147 + if (!ret)
6148 + memcpy(msg[1].buf, &ibuf[1], msg[1].len);
6149 + }
6150 +i2c_error:
6151 + mutex_unlock(&d->i2c_mutex);
6152 + return (ret) ? ret : num;
6153 +}
6154 +
6155 +static u32 dvbsky_i2c_func(struct i2c_adapter *adapter)
6156 +{
6157 + return I2C_FUNC_I2C;
6158 +}
6159 +
6160 +static struct i2c_algorithm dvbsky_i2c_algo = {
6161 + .master_xfer = dvbsky_i2c_xfer,
6162 + .functionality = dvbsky_i2c_func,
6163 +};
6164 +
6165 +#if IS_ENABLED(CONFIG_RC_CORE)
6166 +static int dvbsky_rc_query(struct dvb_usb_device *d)
6167 +{
6168 +
6169 + u32 code = 0xffff, scancode;
6170 + u8 rc5_command, rc5_system;
6171 + u8 obuf[2], ibuf[2], toggle;
6172 + int ret;
6173 + obuf[0] = 0x10;
6174 + ret = dvbsky_usb_generic_rw(d, obuf, 1, ibuf, 2);
6175 + if(ret)
6176 + dev_err(&d->udev->dev, "%s: %s() " \
6177 + "failed=%d\n", KBUILD_MODNAME, __func__, ret);
6178 + if(ret == 0)
6179 + code = (ibuf[0] << 8) | ibuf[1];
6180 +
6181 + if (code != 0xffff) {
6182 + dprintk("rc code: %x \n", code);
6183 + rc5_command = code & 0x3F;
6184 + rc5_system = (code & 0x7C0) >> 6;
6185 + toggle = (code & 0x800) ? 1 : 0;
6186 + scancode = rc5_system << 8 | rc5_command;
6187 + rc_keydown(d->rc_dev, scancode, toggle);
6188 + }
6189 + return 0;
6190 +}
6191 +
6192 +static int dvbsky_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
6193 +{
6194 + rc->allowed_protos = RC_BIT_RC5;
6195 + rc->query = dvbsky_rc_query;
6196 + rc->interval = 300;
6197 + return 0;
6198 +}
6199 +#else
6200 + #define dvbsky_get_rc_config NULL
6201 +#endif
6202 +
6203 +static int dvbsky_sync_ctrl(struct dvb_frontend *fe)
6204 +{
6205 + struct dvb_usb_device *d = fe_to_d(fe);
6206 + return dvbsky_stream_ctrl(d, 1);
6207 +}
6208 +
6209 +static int dvbsky_usb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
6210 +{
6211 + struct dvb_usb_device *d = fe_to_d(fe);
6212 + u8 value;
6213 +
6214 + if (voltage == SEC_VOLTAGE_OFF)
6215 + value = 0;
6216 + else
6217 + value = 1;
6218 + return dvbsky_gpio_ctrl(d, 0x80, value);
6219 +}
6220 +
6221 +static int dvbsky_usb_ci_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
6222 +{
6223 + struct dvb_usb_device *d = fe_to_d(fe);
6224 + u8 value;
6225 +
6226 + if (voltage == SEC_VOLTAGE_OFF)
6227 + value = 0;
6228 + else
6229 + value = 1;
6230 + return dvbsky_gpio_ctrl(d, 0x00, value);
6231 +}
6232 +
6233 +static int dvbsky_t680c_attach(struct dvb_usb_adapter *adap)
6234 +{
6235 + struct dvbsky_state *state = adap_to_priv(adap);
6236 + struct dvb_usb_device *d = adap_to_d(adap);
6237 + int ret = 0;
6238 +
6239 + /*dprintk("%s, build on %s %s()\n", __func__, __DATE__,__TIME__);*/
6240 +
6241 +// adap->fe[0] = dvb_attach(sit2_attach,
6242 +// &dvbsky_usb_sit2_config,
6243 +// &d->i2c_adap);
6244 + if (!adap->fe[0]) {
6245 + printk(KERN_ERR "dvbsky_t680c_attach fail.");
6246 + ret = -ENODEV;
6247 + }
6248 +
6249 + state->has_ci = 1;
6250 +
6251 + return ret;
6252 +}
6253 +
6254 +static int dvbsky_t330_attach(struct dvb_usb_adapter *adap)
6255 +{
6256 + struct dvbsky_state *state = adap_to_priv(adap);
6257 + struct dvb_usb_device *d = adap_to_d(adap);
6258 + int ret = 0;
6259 +
6260 + /*dprintk("%s, build on %s %s()\n", __func__, __DATE__,__TIME__);*/
6261 +
6262 +// adap->fe[0] = dvb_attach(sit2_attach,
6263 +// &dvbsky_t330_sit2_config,
6264 +// &d->i2c_adap);
6265 + if (!adap->fe[0]) {
6266 + printk(KERN_ERR "dvbsky_t330_attach fail.");
6267 + ret = -ENODEV;
6268 + }
6269 +
6270 + state->has_ci = 0;
6271 +
6272 + return ret;
6273 +}
6274 +
6275 +static int dvbsky_read_mac_addr(struct dvb_usb_adapter *adap, u8 mac[6])
6276 +{
6277 + struct dvb_usb_device *d = adap_to_d(adap);
6278 + u8 obuf[] = { 0x1e, 0x00 };
6279 + u8 ibuf[6] = { 0 };
6280 + struct i2c_msg msg[] = {
6281 + {
6282 + .addr = 0x51,
6283 + .flags = 0,
6284 + .buf = obuf,
6285 + .len = 2,
6286 + }, {
6287 + .addr = 0x51,
6288 + .flags = I2C_M_RD,
6289 + .buf = ibuf,
6290 + .len = 6,
6291 +
6292 + }
6293 + };
6294 +
6295 + if (i2c_transfer(&d->i2c_adap, msg, 2) == 2)
6296 + memcpy(mac, ibuf, 6);
6297 +
6298 + printk(KERN_INFO "dvbsky_usb MAC address=%pM\n", mac);
6299 +
6300 + return 0;
6301 +}
6302 +
6303 +static struct dvbsky_m88ds3103_config dvbsky_usb_ds3103_config = {
6304 + .demod_address = 0x68,
6305 + .ci_mode = 1,
6306 + .pin_ctrl = 0x83,
6307 + .ts_mode = 0,
6308 + .start_ctrl = dvbsky_sync_ctrl,
6309 + .set_voltage = dvbsky_usb_set_voltage,
6310 +};
6311 +
6312 +static int dvbsky_s960_attach(struct dvb_usb_adapter *adap)
6313 +{
6314 + struct dvbsky_state *state = adap_to_priv(adap);
6315 + struct dvb_usb_device *d = adap_to_d(adap);
6316 + int ret = 0;
6317 +
6318 + dprintk("%s()\n", __func__);
6319 +
6320 + adap->fe[0] = dvb_attach(dvbsky_m88ds3103_attach,
6321 + &dvbsky_usb_ds3103_config,
6322 + &d->i2c_adap);
6323 + if (!adap->fe[0]) {
6324 + printk(KERN_ERR "dvbsky_s960_attach fail.");
6325 + ret = -ENODEV;
6326 + }
6327 +
6328 + state->has_ci = 0;
6329 +
6330 + return ret;
6331 +}
6332 +
6333 +static struct dvbsky_m88ds3103_config dvbsky_usb_ds3103_ci_config = {
6334 + .demod_address = 0x68,
6335 + .ci_mode = 2,
6336 + .pin_ctrl = 0x82,
6337 + .ts_mode = 0,
6338 + .start_ctrl = dvbsky_sync_ctrl,
6339 + .set_voltage = dvbsky_usb_ci_set_voltage,
6340 +};
6341 +static int dvbsky_s960c_attach(struct dvb_usb_adapter *adap)
6342 +{
6343 + struct dvbsky_state *state = adap_to_priv(adap);
6344 + struct dvb_usb_device *d = adap_to_d(adap);
6345 + int ret = 0;
6346 +
6347 + /*dprintk("%s, build on %s %s()\n", __func__, __DATE__,__TIME__);*/
6348 +
6349 + adap->fe[0] = dvb_attach(dvbsky_m88ds3103_attach,
6350 + &dvbsky_usb_ds3103_ci_config,
6351 + &d->i2c_adap);
6352 + if (!adap->fe[0]) {
6353 + printk(KERN_ERR "dvbsky_s960c_attach fail.");
6354 + ret = -ENODEV;
6355 + }
6356 +
6357 + state->has_ci = 1;
6358 +
6359 + return ret;
6360 +}
6361 +
6362 +static int dvbsky_identify_state(struct dvb_usb_device *d, const char **name)
6363 +{
6364 + /*
6365 + printk(KERN_INFO "%s, build on %s %s(),delay=%d\n",
6366 + __func__, __DATE__,__TIME__,d->props->generic_bulk_ctrl_delay);
6367 + */
6368 + dvbsky_gpio_ctrl(d, 0x04, 1);
6369 + msleep(20);
6370 + dvbsky_gpio_ctrl(d, 0x83, 0);
6371 + dvbsky_gpio_ctrl(d, 0xc0, 1);
6372 + msleep(100);
6373 + dvbsky_gpio_ctrl(d, 0x83, 1);
6374 + dvbsky_gpio_ctrl(d, 0xc0, 0);
6375 + msleep(50);
6376 +
6377 + return WARM;
6378 +}
6379 +
6380 +static int dvbsky_init(struct dvb_usb_device *d)
6381 +{
6382 + struct dvbsky_state *state = d_to_priv(d);
6383 + int ret;
6384 +
6385 + /* use default interface */
6386 + /*
6387 + ret = usb_set_interface(d->udev, 0, 0);
6388 + if (ret)
6389 + return ret;
6390 + */
6391 + mutex_init(&state->stream_mutex);
6392 +
6393 + /* attach CI */
6394 + if (state->has_ci) {
6395 + state->ci_attached = 0;
6396 + ret = dvbsky_ci_init(d);
6397 + if (ret)
6398 + return ret;
6399 + }
6400 + return 0;
6401 +}
6402 +
6403 +static void dvbsky_exit(struct dvb_usb_device *d)
6404 +{
6405 + return dvbsky_ci_release(d);
6406 +}
6407 +
6408 +/* DVB USB Driver stuff */
6409 +static struct dvb_usb_device_properties dvbsky_t330_props = {
6410 + .driver_name = KBUILD_MODNAME,
6411 + .owner = THIS_MODULE,
6412 + .adapter_nr = adapter_nr,
6413 + .size_of_priv = sizeof(struct dvbsky_state),
6414 +
6415 + .generic_bulk_ctrl_endpoint = 0x01,
6416 + .generic_bulk_ctrl_endpoint_response = 0x81,
6417 + .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
6418 +
6419 + .i2c_algo = &dvbsky_i2c_algo,
6420 + .frontend_attach = dvbsky_t330_attach,
6421 + .init = dvbsky_init,
6422 + .get_rc_config = dvbsky_get_rc_config,
6423 + .streaming_ctrl = dvbsky_streaming_ctrl,
6424 + .identify_state = dvbsky_identify_state,
6425 + .exit = dvbsky_exit,
6426 + .read_mac_address = dvbsky_read_mac_addr,
6427 +
6428 + .num_adapters = 1,
6429 + .adapter = {
6430 + {
6431 + .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
6432 + }
6433 + }
6434 +};
6435 +
6436 +static struct dvb_usb_device_properties dvbsky_s960c_props = {
6437 + .driver_name = KBUILD_MODNAME,
6438 + .owner = THIS_MODULE,
6439 + .adapter_nr = adapter_nr,
6440 + .size_of_priv = sizeof(struct dvbsky_state),
6441 +
6442 + .generic_bulk_ctrl_endpoint = 0x01,
6443 + .generic_bulk_ctrl_endpoint_response = 0x81,
6444 + .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
6445 +
6446 + .i2c_algo = &dvbsky_i2c_algo,
6447 + .frontend_attach = dvbsky_s960c_attach,
6448 + .init = dvbsky_init,
6449 + .get_rc_config = dvbsky_get_rc_config,
6450 + .streaming_ctrl = dvbsky_streaming_ctrl,
6451 + .identify_state = dvbsky_identify_state,
6452 + .exit = dvbsky_exit,
6453 + .read_mac_address = dvbsky_read_mac_addr,
6454 +
6455 + .num_adapters = 1,
6456 + .adapter = {
6457 + {
6458 + .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
6459 + }
6460 + }
6461 +};
6462 +
6463 +static struct dvb_usb_device_properties dvbsky_t680c_props = {
6464 + .driver_name = KBUILD_MODNAME,
6465 + .owner = THIS_MODULE,
6466 + .adapter_nr = adapter_nr,
6467 + .size_of_priv = sizeof(struct dvbsky_state),
6468 +
6469 + .generic_bulk_ctrl_endpoint = 0x01,
6470 + .generic_bulk_ctrl_endpoint_response = 0x81,
6471 + .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
6472 +
6473 + .i2c_algo = &dvbsky_i2c_algo,
6474 + .frontend_attach = dvbsky_t680c_attach,
6475 + .init = dvbsky_init,
6476 + .get_rc_config = dvbsky_get_rc_config,
6477 + .streaming_ctrl = dvbsky_streaming_ctrl,
6478 + .identify_state = dvbsky_identify_state,
6479 + .exit = dvbsky_exit,
6480 + .read_mac_address = dvbsky_read_mac_addr,
6481 +
6482 + .num_adapters = 1,
6483 + .adapter = {
6484 + {
6485 + .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
6486 + }
6487 + }
6488 +};
6489 +
6490 +static struct dvb_usb_device_properties dvbsky_s960_props = {
6491 + .driver_name = KBUILD_MODNAME,
6492 + .owner = THIS_MODULE,
6493 + .adapter_nr = adapter_nr,
6494 + .size_of_priv = sizeof(struct dvbsky_state),
6495 +
6496 + .generic_bulk_ctrl_endpoint = 0x01,
6497 + .generic_bulk_ctrl_endpoint_response = 0x81,
6498 + .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
6499 +
6500 + .i2c_algo = &dvbsky_i2c_algo,
6501 + .frontend_attach = dvbsky_s960_attach,
6502 + .init = dvbsky_init,
6503 + .get_rc_config = dvbsky_get_rc_config,
6504 + .streaming_ctrl = dvbsky_streaming_ctrl,
6505 + .identify_state = dvbsky_identify_state,
6506 + .exit = dvbsky_exit,
6507 + .read_mac_address = dvbsky_read_mac_addr,
6508 +
6509 + .num_adapters = 1,
6510 + .adapter = {
6511 + {
6512 + .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
6513 + }
6514 + }
6515 +};
6516 +
6517 +static const struct usb_device_id dvbsky_id_table[] = {
6518 + { DVB_USB_DEVICE(0x0572, 0x0320,
6519 + &dvbsky_t330_props, "DVBSky T330 USB Stick", RC_MAP_DVBSKY) },
6520 + { DVB_USB_DEVICE(0x0572, 0x960c,
6521 + &dvbsky_s960c_props, "DVBSky S960CI", RC_MAP_DVBSKY) },
6522 + { DVB_USB_DEVICE(0x0572, 0x680c,
6523 + &dvbsky_t680c_props, "DVBSky T680CI", RC_MAP_DVBSKY) },
6524 + { DVB_USB_DEVICE(0x0572, 0x6831,
6525 + &dvbsky_s960_props, "DVBSky S960/S860", RC_MAP_DVBSKY) },
6526 + { }
6527 +};
6528 +MODULE_DEVICE_TABLE(usb, dvbsky_id_table);
6529 +
6530 +static struct usb_driver dvbsky_usb_driver = {
6531 + .name = KBUILD_MODNAME,
6532 + .id_table = dvbsky_id_table,
6533 + .probe = dvb_usbv2_probe,
6534 + .disconnect = dvb_usbv2_disconnect,
6535 + .suspend = dvb_usbv2_suspend,
6536 + .resume = dvb_usbv2_resume,
6537 + .reset_resume = dvb_usbv2_reset_resume,
6538 + .no_dynamic_id = 1,
6539 + .soft_unbind = 1,
6540 +};
6541 +
6542 +module_usb_driver(dvbsky_usb_driver);
6543 +
6544 +MODULE_AUTHOR("Max nibble <nibble.max@gmail.com>");
6545 +MODULE_DESCRIPTION("Driver for DVBSky USB2.0");
6546 +MODULE_LICENSE("GPL");
6547 diff --git a/include/media/rc-map.h b/include/media/rc-map.h
6548 index a20ed97..73f8c92 100644
6549 --- a/include/media/rc-map.h
6550 +++ b/include/media/rc-map.h
6551 @@ -119,6 +119,7 @@ void rc_map_init(void);
6552 #define RC_MAP_DM1105_NEC "rc-dm1105-nec"
6553 #define RC_MAP_DNTV_LIVE_DVBT_PRO "rc-dntv-live-dvbt-pro"
6554 #define RC_MAP_DNTV_LIVE_DVB_T "rc-dntv-live-dvb-t"
6555 +#define RC_MAP_DVBSKY "rc-dvbsky"
6556 #define RC_MAP_EMPTY "rc-empty"
6557 #define RC_MAP_EM_TERRATEC "rc-em-terratec"
6558 #define RC_MAP_ENCORE_ENLTV2 "rc-encore-enltv2"