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)
9 +config DVB_DVBSKY_M88DS3103
10 + tristate "Montage M88DS3103 based(DVBSky)"
11 + depends on DVB_CORE && I2C
12 + default m if !MEDIA_SUBDRV_AUTOSELECT
14 + A DVB-S/S2 tuner module. Say Y when you want to support this frontend.
17 + tristate "Montage M88DC2800 based"
18 + depends on DVB_CORE && I2C
19 + default m if !MEDIA_SUBDRV_AUTOSELECT
21 + A DVB-C tuner module. Say Y when you want to support this frontend.
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
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
38 index 0000000..5ad1157
40 +++ b/drivers/media/dvb-frontends/dvbsky_m88ds3103.c
43 + Montage Technology M88DS3103/M88TS2022 - DVBS/S2 Satellite demod/tuner driver
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.
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.
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.
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.
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>
71 +#include "dvb_frontend.h"
72 +#include "dvbsky_m88ds3103.h"
73 +#include "dvbsky_m88ds3103_priv.h"
76 +module_param(debug, int, 0644);
77 +MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
79 +#define dprintk(args...) \
82 + printk(KERN_INFO "m88ds3103: " args); \
87 +/*demod register operations.*/
88 +static int m88ds3103_writereg(struct m88ds3103_state *state, int reg, int data)
90 + u8 buf[] = { reg, data };
91 + struct i2c_msg msg = { .addr = state->config->demod_address,
92 + .flags = 0, .buf = buf, .len = 2 };
96 + printk("m88ds3103: %s: write reg 0x%02x, value 0x%02x\n",
97 + __func__, reg, data);
99 + err = i2c_transfer(state->i2c, &msg, 1);
101 + printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x,"
102 + " value == 0x%02x)\n", __func__, err, reg, data);
108 +static int m88ds3103_readreg(struct m88ds3103_state *state, u8 reg)
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 }
119 + ret = i2c_transfer(state->i2c, msg, 2);
122 + printk(KERN_ERR "%s: reg=0x%x (error=%d)\n",
123 + __func__, reg, ret);
128 + printk(KERN_INFO "m88ds3103: read reg 0x%02x, value 0x%02x\n",
134 +/*tuner register operations.*/
135 +static int m88ds3103_tuner_writereg(struct m88ds3103_state *state, int reg, int data)
137 + u8 buf[] = { reg, data };
138 + struct i2c_msg msg = { .addr = 0x60,
139 + .flags = 0, .buf = buf, .len = 2 };
142 + m88ds3103_writereg(state, 0x03, 0x11);
143 + err = i2c_transfer(state->i2c, &msg, 1);
146 + printk("%s: writereg error(err == %i, reg == 0x%02x,"
147 + " value == 0x%02x)\n", __func__, err, reg, data);
154 +static int m88ds3103_tuner_readreg(struct m88ds3103_state *state, u8 reg)
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 }
166 + m88ds3103_writereg(state, 0x03, (0x11 + state->config->tuner_readstops));
167 + ret = i2c_transfer(state->i2c, msg, 2);
170 + printk(KERN_ERR "%s: reg=0x%x(error=%d)\n", __func__, reg, ret);
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)
181 + int ret = -EREMOTEIO;
182 + struct i2c_msg msg;
185 + buf = kmalloc(len + 1, GFP_KERNEL);
187 + printk("Unable to kmalloc\n");
193 + memcpy(buf + 1, data, len);
195 + msg.addr = state->config->demod_address;
201 + printk(KERN_INFO "m88ds3103: %s: write regN 0x%02x, len = %d\n",
202 + __func__, reg, len);
204 + ret = i2c_transfer(state->i2c, &msg, 1);
206 + printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x\n",
207 + __func__, ret, reg);
217 +static int m88ds3103_load_firmware(struct dvb_frontend *fe)
219 + struct m88ds3103_state *state = fe->demodulator_priv;
220 + const struct firmware *fw;
223 + dprintk("%s()\n", __func__);
225 + if (state->skip_fw_load)
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);
241 + printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n", __func__);
243 + printk(KERN_ERR "%s: No firmware uploaded (timeout or file not "
244 + "found?)\n", __func__);
248 + /* Make sure we don't recurse back through here during loading */
249 + state->skip_fw_load = 1;
251 + dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n",
255 + fw->data[fw->size - 2],
256 + fw->data[fw->size - 1]);
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;
265 + /* start internal mcu. */
267 + m88ds3103_writereg(state, 0xb2, 0x00);
269 + release_firmware(fw);
271 + dprintk("%s: Firmware upload %s\n", __func__,
272 + ret == 1 ? "complete" : "failed");
274 + if(ret == 1) ret = 0;
276 + /* Ensure firmware is always loaded if required */
277 + state->skip_fw_load = 0;
283 +static int m88ds3103_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
285 + struct m88ds3103_state *state = fe->demodulator_priv;
288 + dprintk("%s(%d)\n", __func__, voltage);
290 + dprintk("m88ds3103:pin_ctrl = (%02x)\n", state->config->pin_ctrl);
292 + if(state->config->set_voltage)
293 + state->config->set_voltage(fe, voltage);
295 + data = m88ds3103_readreg(state, 0xa2);
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)
303 + case SEC_VOLTAGE_18:
304 + if((state->config->pin_ctrl & 0x01) == 0)
307 + case SEC_VOLTAGE_13:
308 + if(state->config->pin_ctrl & 0x01)
311 + case SEC_VOLTAGE_OFF:
312 + if(state->config->pin_ctrl & 0x02)
320 + m88ds3103_writereg(state, 0xa2, data);
325 +static int m88ds3103_read_status(struct dvb_frontend *fe, fe_status_t* status)
327 + struct m88ds3103_state *state = fe->demodulator_priv;
332 + switch (state->delivery_system){
334 + lock = m88ds3103_readreg(state, 0xd1);
335 + dprintk("%s: SYS_DVBS status=%x.\n", __func__, lock);
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;
345 + lock = m88ds3103_readreg(state, 0x0d);
346 + dprintk("%s: SYS_DVBS2 status=%x.\n", __func__, lock);
348 + if ((lock & 0x8f) == 0x8f)
349 + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER
350 + | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
360 +static int m88ds3103_read_ber(struct dvb_frontend *fe, u32* ber)
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;
366 + dprintk("%s()\n", __func__);
368 + switch (state->delivery_system) {
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);
376 + m88ds3103_writereg(state, 0xf8, tmp3);
377 + state->preBer = (tmp1<<8) | tmp2;
381 + tmp1 = m88ds3103_readreg(state, 0x7e) & 0x0f;
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;
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;
401 + tmp1 = m88ds3103_readreg(state, 0xf8) & 0xff;
402 + tmp2 = m88ds3103_readreg(state, 0xf7) & 0xff;
403 + pre_err_packags = tmp1<<8 | tmp2;
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;
416 + *ber = state->preBer;
421 +static int m88ds3103_read_signal_strength(struct dvb_frontend *fe,
422 + u16 *signal_strength)
424 + struct m88ds3103_state *state = fe->demodulator_priv;
426 + u8 gain1, gain2, gain3 = 0;
428 + dprintk("%s()\n", __func__);
430 + gain1 = m88ds3103_tuner_readreg(state, 0x3d) & 0x1f;
431 + dprintk("%s: gain1 = 0x%02x \n", __func__, gain1);
433 + if (gain1 > 15) gain1 = 15;
434 + gain2 = m88ds3103_tuner_readreg(state, 0x21) & 0x1f;
435 + dprintk("%s: gain2 = 0x%02x \n", __func__, gain2);
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);
441 + if (gain2 > 16) gain2 = 16;
442 + if (gain2 < 2) gain2 = 2;
443 + if (gain3 > 6) gain3 = 6;
445 + if (gain2 > 13) gain2 = 13;
449 + gain = gain1*23 + gain2*35 + gain3*29;
450 + *signal_strength = 60000 - gain*55;
456 +static int m88ds3103_read_snr(struct dvb_frontend *fe, u16 *p_snr)
458 + struct m88ds3103_state *state = fe->demodulator_priv;
459 + u8 val, npow1, npow2, spow1, cnt;
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
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,
479 + dprintk("%s()\n", __func__);
483 + switch (state->delivery_system){
485 + cnt = 10; snr_total = 0;
487 + val = m88ds3103_readreg(state, 0xff);
491 + tmp = (u16)(snr_total/80);
493 + if (tmp > 32) tmp = 32;
494 + snr = (mes_loge[tmp - 1] * 100) / 45;
500 + cnt = 10; npow = 0; spow = 0;
502 + npow1 = m88ds3103_readreg(state, 0x8c) & 0xff;
503 + npow2 = m88ds3103_readreg(state, 0x8d) & 0xff;
504 + npow += (((npow1 & 0x3f) + (u16)(npow2 << 6)) >> 2);
506 + spow1 = m88ds3103_readreg(state, 0x8e) & 0xff;
507 + spow += ((spow1 * spow1) >> 1);
510 + npow /= 10; spow /= 10;
513 + }else if(npow == 0){
517 + tmp = (u16)(spow / npow);
518 + if (tmp > 80) tmp = 80;
519 + snr = mes_log10[tmp - 1]*3;
521 + tmp = (u16)(npow / spow);
522 + if (tmp > 80) tmp = 80;
523 + snr = -(mes_log10[tmp - 1] / 1000);
536 +static int m88ds3103_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
538 + struct m88ds3103_state *state = fe->demodulator_priv;
539 + u8 tmp1, tmp2, tmp3, data;
541 + dprintk("%s()\n", __func__);
543 + switch (state->delivery_system) {
545 + data = m88ds3103_readreg(state, 0xf8);
547 + m88ds3103_writereg(state, 0xf8, data);
548 + tmp1 = m88ds3103_readreg(state, 0xf5);
549 + tmp2 = m88ds3103_readreg(state, 0xf4);
550 + *ucblocks = (tmp1 <<8) | tmp2;
552 + m88ds3103_writereg(state, 0xf8, data);
554 + m88ds3103_writereg(state, 0xf8, data);
556 + m88ds3103_writereg(state, 0xf8, data);
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);
565 + m88ds3103_writereg(state, 0xd1, data);
567 + m88ds3103_writereg(state, 0xd1, data);
575 +static int m88ds3103_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
577 + struct m88ds3103_state *state = fe->demodulator_priv;
578 + u8 data_a1, data_a2;
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);
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 */
592 + dprintk("%s: SEC_TONE_ON\n", __func__);
599 + dprintk("%s: SEC_TONE_OFF\n", __func__);
604 + m88ds3103_writereg(state, 0xa2, data_a2);
605 + m88ds3103_writereg(state, 0xa1, data_a1);
609 +static int m88ds3103_send_diseqc_msg(struct dvb_frontend *fe,
610 + struct dvb_diseqc_master_cmd *d)
612 + struct m88ds3103_state *state = fe->demodulator_priv;
616 + /* Dump DiSEqC message */
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 ", ");
626 + tmp = m88ds3103_readreg(state, 0xa2);
628 + if(state->demod_id == DS3103_ID)
630 + m88ds3103_writereg(state, 0xa2, tmp);
632 + for (i = 0; i < d->msg_len; i ++)
633 + m88ds3103_writereg(state, (0xa3+i), d->msg[i]);
635 + tmp = m88ds3103_readreg(state, 0xa1);
638 + tmp |= ((d->msg_len-1) << 3) | 0x07;
640 + m88ds3103_writereg(state, 0xa1, tmp);
641 + /* 1.5 * 9 * 8 = 108ms */
643 + while (time_out > 0){
646 + tmp = m88ds3103_readreg(state, 0xa1);
647 + if ((tmp & 0x40) == 0)
650 + if (time_out == 0){
651 + tmp = m88ds3103_readreg(state, 0xa1);
654 + m88ds3103_writereg(state, 0xa1, tmp);
657 + tmp = m88ds3103_readreg(state, 0xa2);
660 + m88ds3103_writereg(state, 0xa2, tmp);
665 +static int m88ds3103_diseqc_send_burst(struct dvb_frontend *fe,
666 + fe_sec_mini_cmd_t burst)
668 + struct m88ds3103_state *state = fe->demodulator_priv;
671 + dprintk("%s()\n", __func__);
673 + val = m88ds3103_readreg(state, 0xa2);
675 + if(state->demod_id == DS3103_ID)
676 + val &= 0xdf; /* Normal mode */
677 + m88ds3103_writereg(state, 0xa2, val);
679 + if (burst == SEC_MINI_B)
680 + m88ds3103_writereg(state, 0xa1, 0x01);
682 + m88ds3103_writereg(state, 0xa1, 0x02);
688 + val = m88ds3103_readreg(state, 0xa1);
689 + if ((val & 0x40) == 0)
693 + } while (time_out > 0);
695 + val = m88ds3103_readreg(state, 0xa2);
698 + m88ds3103_writereg(state, 0xa2, val);
703 +static void m88ds3103_release(struct dvb_frontend *fe)
705 + struct m88ds3103_state *state = fe->demodulator_priv;
707 + dprintk("%s\n", __func__);
711 +static int m88ds3103_check_id(struct m88ds3103_state *state)
713 + int val_00, val_01;
716 + val_01 = m88ds3103_readreg(state, 0x01);
717 + printk(KERN_INFO "DS3000 chip version: %x attached.\n", val_01);
720 + state->demod_id = DS3103_ID;
721 + else if(val_01 == 0xC0)
722 + state->demod_id = DS3000_ID;
724 + state->demod_id = UNKNOW_ID;
727 + val_00 = m88ds3103_tuner_readreg(state, 0x00);
728 + printk(KERN_INFO "TS202x chip version[1]: %x attached.\n", val_00);
732 + m88ds3103_tuner_writereg(state, 0x00, 0x01);
735 + m88ds3103_tuner_writereg(state, 0x00, 0x03);
738 + val_00 = m88ds3103_tuner_readreg(state, 0x00);
739 + printk(KERN_INFO "TS202x chip version[2]: %x attached.\n", val_00);
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;
746 + state->tuner_id = UNKNOW_ID;
748 + return state->demod_id;
751 +static struct dvb_frontend_ops m88ds3103_ops;
752 +static int m88ds3103_initilaze(struct dvb_frontend *fe);
754 +struct dvb_frontend *dvbsky_m88ds3103_attach(const struct dvbsky_m88ds3103_config *config,
755 + struct i2c_adapter *i2c)
757 + struct m88ds3103_state *state = NULL;
759 + dprintk("%s\n", __func__);
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");
768 + state->config = config;
770 + state->preBer = 0xffff;
771 + state->delivery_system = SYS_DVBS; /*Default to DVB-S.*/
773 + /* check demod id */
774 + if(m88ds3103_check_id(state) == UNKNOW_ID){
775 + printk(KERN_ERR "Unable to find Montage chip\n");
779 + memcpy(&state->frontend.ops, &m88ds3103_ops,
780 + sizeof(struct dvb_frontend_ops));
781 + state->frontend.demodulator_priv = state;
783 + m88ds3103_initilaze(&state->frontend);
785 + return &state->frontend;
792 +EXPORT_SYMBOL(dvbsky_m88ds3103_attach);
794 +static int m88ds3103_set_carrier_offset(struct dvb_frontend *fe,
795 + s32 carrier_offset_khz)
797 + struct m88ds3103_state *state = fe->demodulator_priv;
800 + tmp = carrier_offset_khz;
803 + tmp = (2*tmp + MT_FE_MCLK_KHZ) / (2*MT_FE_MCLK_KHZ);
808 + m88ds3103_writereg(state, 0x5f, tmp >> 8);
809 + m88ds3103_writereg(state, 0x5e, tmp & 0xff);
814 +static int m88ds3103_set_symrate(struct dvb_frontend *fe)
816 + struct m88ds3103_state *state = fe->demodulator_priv;
817 + struct dtv_frontend_properties *c = &fe->dtv_property_cache;
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);
827 +static int m88ds3103_set_CCI(struct dvb_frontend *fe)
829 + struct m88ds3103_state *state = fe->demodulator_priv;
832 + tmp = m88ds3103_readreg(state, 0x56);
834 + m88ds3103_writereg(state, 0x56, tmp);
836 + tmp = m88ds3103_readreg(state, 0x76);
838 + m88ds3103_writereg(state, 0x76, tmp);
843 +static int m88ds3103_init_reg(struct m88ds3103_state *state, const u8 *p_reg_tab, u32 size)
847 + for(i = 0; i < size; i+=2)
848 + m88ds3103_writereg(state, p_reg_tab[i], p_reg_tab[i+1]);
853 +static int m88ds3103_get_locked_sym_rate(struct m88ds3103_state *state, u32 *sym_rate_KSs)
857 + u8 val_0x6d, val_0x6e;
859 + val_0x6d = m88ds3103_readreg(state, 0x6d);
860 + val_0x6e = m88ds3103_readreg(state, 0x6e);
862 + tmp = (u16)((val_0x6e<<8) | val_0x6d);
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;
871 +static int m88ds3103_get_channel_info(struct m88ds3103_state *state, u8 *p_mode, u8 *p_coderate)
875 + if(state->delivery_system == SYS_DVBS2){
876 + val_0x7E = m88ds3103_readreg(state, 0x7e);
877 + tmp = (u8)((val_0x7E&0xC0) >> 6);
879 + tmp = (u8)(val_0x7E & 0x0f);
883 + tmp = m88ds3103_readreg(state, 0xe6);
884 + tmp = (u8)(tmp >> 5);
891 +static int m88ds3103_set_clock_ratio(struct m88ds3103_state *state)
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;
898 + locked_sym_rate_KSs = 0;
899 + m88ds3103_get_locked_sym_rate(state, &locked_sym_rate_KSs);
900 + if(locked_sym_rate_KSs == 0)
903 + m88ds3103_get_channel_info(state, &mod_mode, &code_rate);
905 + if (state->delivery_system == SYS_DVBS2)
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;
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;
929 + if(state->demod_id == DS3000_ID)
930 + input_datarate = input_datarate * 115 / 100;
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
954 + if(state->demod_id == DS3000_ID) {
955 + val = (u8)((tmp1<<4) + tmp2);
956 + m88ds3103_writereg(state, 0xfe, val);
958 + tmp1 = m88ds3103_readreg(state, 0x22);
959 + tmp2 = m88ds3103_readreg(state, 0x24);
966 + if((tmp1 == 0x00) && (tmp2 == 0x01))
968 + else if((tmp1 == 0x00) && (tmp2 == 0x03))
970 + else if((tmp1 == 0x01) && (tmp2 == 0x01))
972 + else if((tmp1 == 0x02) && (tmp2 == 0x01))
974 + else if((tmp1 == 0x03) && (tmp2 == 0x00))
979 + if(input_datarate < 5200) /*Max. 2011-12-23 11:55*/
980 + input_datarate = 5200;
982 + if(input_datarate != 0)
983 + divid_ratio = (u8)(MClk_KHz / input_datarate);
985 + divid_ratio = 0xFF;
987 + if(divid_ratio > 128)
990 + if(divid_ratio < 2)
993 + tmp1 = (u8)(divid_ratio / 2);
994 + tmp2 = (u8)(divid_ratio / 2);
996 + if((divid_ratio % 2) != 0)
1005 + val = m88ds3103_readreg(state, 0xfe);
1007 + val |= (tmp2 >> 2) & 0x0f;
1008 + m88ds3103_writereg(state, 0xfe, val);
1010 + val = (u8)((tmp2 & 0x03) << 6);
1012 + m88ds3103_writereg(state, 0xea, val);
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;
1026 + if(state->demod_id == DS3000_ID)
1027 + input_datarate = input_datarate * 115 / 100;
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
1041 + if(state->demod_id == DS3000_ID) {
1042 + val = m88ds3103_readreg(state, 0xfe);
1044 + val |= ((u8)((tmp1<<3) + tmp2));
1045 + m88ds3103_writereg(state, 0xfe, val);
1047 + if(input_datarate < 5200) /*Max. 2011-12-23 11:55*/
1048 + input_datarate = 5200;
1050 + if(input_datarate != 0)
1051 + divid_ratio = (u8)(MClk_KHz / input_datarate);
1053 + divid_ratio = 0xFF;
1055 + if(divid_ratio > 128)
1056 + divid_ratio = 128;
1058 + if(divid_ratio < 2)
1061 + tmp1 = (u8)(divid_ratio / 2);
1062 + tmp2 = (u8)(divid_ratio / 2);
1064 + if((divid_ratio % 2) != 0)
1073 + val = m88ds3103_readreg(state, 0xfe);
1075 + val |= (tmp2 >> 2) & 0x0f;
1076 + m88ds3103_writereg(state, 0xfe, val);
1078 + val = (u8)((tmp2 & 0x03) << 6);
1080 + m88ds3103_writereg(state, 0xea, val);
1086 +static int m88ds3103_demod_connect(struct dvb_frontend *fe, s32 carrier_offset_khz)
1088 + struct m88ds3103_state *state = fe->demodulator_priv;
1089 + struct dtv_frontend_properties *c = &fe->dtv_property_cache;
1091 + u8 val1,val2,data;
1093 + dprintk("connect delivery system = %d\n", state->delivery_system);
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);
1103 + switch (state->delivery_system) {
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));
1109 + value = m88ds3103_readreg(state, 0xfe);
1112 + m88ds3103_writereg(state, 0xfe, value);
1114 + if(state->config->ci_mode)
1116 + else if(state->config->ts_mode)
1120 + m88ds3103_writereg(state, 0xfd, val1);
1122 + }else if(state->demod_id == DS3103_ID){
1123 + m88ds3103_init_reg(state, ds3103_dvbs_init_tab, sizeof(ds3103_dvbs_init_tab));
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;
1131 + val1 = 0; val2 = 0;
1133 + val1 -= 1; val2 -= 1;
1134 + val1 &= 0x3f; val2 &= 0x3f;
1135 + data = m88ds3103_readreg(state, 0xfe);
1137 + data |= (val2 >> 2) & 0x0f;
1138 + m88ds3103_writereg(state, 0xfe, data);
1139 + data = (val2 & 0x03) << 6;
1141 + m88ds3103_writereg(state, 0xea, data);
1143 + m88ds3103_writereg(state, 0x4d, 0xfd & m88ds3103_readreg(state, 0x4d));
1144 + m88ds3103_writereg(state, 0x30, 0xef & m88ds3103_readreg(state, 0x30));
1146 + /* set master clock */
1147 + val1 = m88ds3103_readreg(state, 0x22);
1148 + val2 = m88ds3103_readreg(state, 0x24);
1155 + m88ds3103_writereg(state, 0x22, val1);
1156 + m88ds3103_writereg(state, 0x24, val2);
1158 + if(state->config->ci_mode){
1159 + if(state->config->ci_mode == 2)
1164 + else if(state->config->ts_mode)
1168 + m88ds3103_writereg(state, 0xfd, val1);
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));
1176 + if (c->symbol_rate >= 30000000)
1177 + m88ds3103_writereg(state, 0xfe, 0x54);
1179 + m88ds3103_writereg(state, 0xfe, 0x98);
1181 + }else if(state->demod_id == DS3103_ID){
1182 + m88ds3103_init_reg(state, ds3103_dvbs2_init_tab, sizeof(ds3103_dvbs2_init_tab));
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;
1190 + val1 = 0; val2 = 0;
1192 + val1 -= 1; val2 -= 1;
1193 + val1 &= 0x3f; val2 &= 0x3f;
1194 + data = m88ds3103_readreg(state, 0xfe);
1196 + data |= (val2 >> 2) & 0x0f;
1197 + m88ds3103_writereg(state, 0xfe, data);
1198 + data = (val2 & 0x03) << 6;
1200 + m88ds3103_writereg(state, 0xea, data);
1202 + m88ds3103_writereg(state, 0x4d, 0xfd & m88ds3103_readreg(state, 0x4d));
1203 + m88ds3103_writereg(state, 0x30, 0xef & m88ds3103_readreg(state, 0x30));
1205 + /* set master clock */
1206 + val1 = m88ds3103_readreg(state, 0x22);
1207 + val2 = m88ds3103_readreg(state, 0x24);
1211 + if((state->config->ci_mode == 2) || (state->config->ts_mode == 1)){
1215 + if (c->symbol_rate >= 28000000){
1217 + }else if (c->symbol_rate >= 18000000){
1224 + m88ds3103_writereg(state, 0x22, val1);
1225 + m88ds3103_writereg(state, 0x24, val2);
1228 + if(state->config->ci_mode){
1229 + if(state->config->ci_mode == 2)
1234 + else if(state->config->ts_mode)
1238 + m88ds3103_writereg(state, 0xfd, val1);
1244 + /* disable 27MHz clock output */
1245 + m88ds3103_writereg(state, 0x29, 0x80);
1246 + /* enable ac coupling */
1247 + m88ds3103_writereg(state, 0x25, 0x8a);
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);
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);
1266 + m88ds3103_set_symrate(fe);
1268 + m88ds3103_set_CCI(fe);
1270 + m88ds3103_set_carrier_offset(fe, carrier_offset_khz);
1272 + /* ds3000 out of software reset */
1273 + m88ds3103_writereg(state, 0x00, 0x00);
1274 + /* start ds3000 build-in uC */
1275 + m88ds3103_writereg(state, 0xb2, 0x00);
1280 +static int m88ds3103_set_frontend(struct dvb_frontend *fe)
1282 + struct m88ds3103_state *state = fe->demodulator_priv;
1283 + struct dtv_frontend_properties *c = &fe->dtv_property_cache;
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;
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);
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;
1305 + if (state->config->set_ts_params)
1306 + state->config->set_ts_params(fe, 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);
1316 + ndiv = (realFreq * (6 + 8) * 4)/MT_FE_CRYSTAL_KHZ;
1318 + ndiv = (realFreq * (6 + 8) * 2)/MT_FE_CRYSTAL_KHZ;
1320 + ndiv = ndiv + ndiv%2;
1323 + else if (ndiv < 6143)
1328 + m88ds3103_tuner_writereg(state, 0x01, (N & 0x3f00) >> 8);
1330 + m88ds3103_tuner_writereg(state, 0x10, 0x00);
1331 + if (realFreq < 1146000){
1332 + m88ds3103_tuner_writereg(state, 0x10, 0x11);
1334 + ndiv = (realFreq * (6 + 8) * 4) / MT_FE_CRYSTAL_KHZ;
1336 + m88ds3103_tuner_writereg(state, 0x10, 0x01);
1337 + ndiv = (realFreq * (6 + 8) * 2) / MT_FE_CRYSTAL_KHZ;
1339 + ndiv = ndiv + ndiv%2;
1341 + m88ds3103_tuner_writereg(state, 0x01, (N>>8)&0x0f);
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);
1351 + if(state->tuner_id == TS2022_ID){
1352 + if(( realFreq >= 1650000 ) && (realFreq <= 1850000)){
1354 + value = m88ds3103_tuner_readreg(state, 0x14);
1357 + m88ds3103_tuner_writereg(state, 0x10, 0x82);
1358 + m88ds3103_tuner_writereg(state, 0x11, 0x6f);
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);
1367 + value = m88ds3103_tuner_readreg(state, 0x14);
1371 + value = m88ds3103_tuner_readreg(state, 0x10);
1373 + m88ds3103_tuner_writereg(state, 0x10, value);
1377 + value = m88ds3103_tuner_readreg(state, 0x66);
1378 + changePLL = (((value & 0x80) >> 7) != div4);
1381 + m88ds3103_tuner_writereg(state, 0x10, 0x11);
1383 + ndiv = (realFreq * (6 + 8) * 4)/MT_FE_CRYSTAL_KHZ;
1384 + ndiv = ndiv + ndiv%2;
1387 + m88ds3103_tuner_writereg(state, 0x01, (N>>8) & 0x0f);
1388 + m88ds3103_tuner_writereg(state, 0x02, N & 0xff);
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);
1396 + /*set the RF gain*/
1397 + if(state->tuner_id == TS2020_ID)
1398 + m88ds3103_tuner_writereg(state, 0x60, 0x79);
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);
1406 + if(state->tuner_id == TS2020_ID){
1407 + RFgain = m88ds3103_tuner_readreg(state, 0x3d);
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);
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);
1431 + f3db = ((c->symbol_rate / 1000) *135) / 200 + 2000;
1432 + f3db += lpf_offset_KHz;
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);
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);
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);
1458 + value = m88ds3103_tuner_readreg(state, 0x26);
1460 + value = (capCode + value) / 2;
1465 + gdiv28 = gdiv28 * 207 / (value * 2 + 151);
1466 + mlpf_max = gdiv28 * 135 / 100;
1467 + mlpf_min = gdiv28 * 78 / 100;
1468 + if (mlpf_max > 63)
1471 + if(state->tuner_id == TS2022_ID)
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;
1480 + lpf_mxdiv = (nlpf * (MT_FE_CRYSTAL_KHZ / 1000) * lpf_coeff * 2 / f3db + 1) / 2;
1482 + if (lpf_mxdiv < mlpf_min){
1484 + lpf_mxdiv = (nlpf * (MT_FE_CRYSTAL_KHZ / 1000) * lpf_coeff * 2 / f3db + 1) / 2;
1487 + if (lpf_mxdiv > mlpf_max)
1488 + lpf_mxdiv = mlpf_max;
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);
1498 + if(state->tuner_id == TS2022_ID){
1500 + value = m88ds3103_tuner_readreg(state, 0x26);
1501 + capCode = value & 0x3f;
1503 + m88ds3103_tuner_writereg(state, 0x41, 0x09);
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);
1511 + value = m88ds3103_tuner_readreg(state, 0x26);
1513 + value = (capCode + value) / 2;
1515 + value = value | 0x80;
1516 + m88ds3103_tuner_writereg(state, 0x25, value);
1517 + m88ds3103_tuner_writereg(state, 0x27, 0x30);
1519 + m88ds3103_tuner_writereg(state, 0x08, 0x09);
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){
1530 + value = m88ds3103_tuner_readreg(state, 0x21);
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);
1543 + offset_khz = (ndiv) * MT_FE_CRYSTAL_KHZ
1544 + / (6 + 8) / (div4 + 1) / 2 - realFreq;
1546 + m88ds3103_demod_connect(fe, offset_khz+lpf_offset_KHz);
1548 + for (i = 0; i < 30 ; i++) {
1549 + m88ds3103_read_status(fe, &status);
1550 + if (status & FE_HAS_LOCK){
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);
1561 + for (i = 0; i < 30 ; i++) {
1562 + m88ds3103_read_status(fe, &status);
1563 + if (status & FE_HAS_LOCK){
1570 + state->delivery_system = c->delivery_system;
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;
1586 +static int m88ds3103_tune(struct dvb_frontend *fe,
1588 + unsigned int mode_flags,
1589 + unsigned int *delay,
1590 + fe_status_t *status)
1594 + dprintk("%s() ", __func__);
1595 + dprintk("re_tune = %d\n", re_tune);
1598 + int ret = m88ds3103_set_frontend(fe);
1603 + return m88ds3103_read_status(fe, status);
1606 +static enum dvbfe_algo m88ds3103_get_algo(struct dvb_frontend *fe)
1608 + return DVBFE_ALGO_HW;
1612 + * Power config will reset and load initial firmware if required
1614 +static int m88ds3103_initilaze(struct dvb_frontend *fe)
1616 + struct m88ds3103_state *state = fe->demodulator_priv;
1619 + dprintk("%s()\n", __func__);
1621 + m88ds3103_writereg(state, 0x07, 0x80);
1622 + m88ds3103_writereg(state, 0x07, 0x00);
1625 + m88ds3103_writereg(state, 0x08, 0x01 | m88ds3103_readreg(state, 0x08));
1628 + if(state->tuner_id == TS2020_ID){
1630 + m88ds3103_tuner_writereg(state, 0x42, 0x73);
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);
1637 + else if(state->tuner_id == TS2022_ID){
1639 + m88ds3103_tuner_writereg(state, 0x62, 0x6c);
1641 + m88ds3103_tuner_writereg(state, 0x42, 0x6c);
1643 + m88ds3103_tuner_writereg(state, 0x7d, 0x9d);
1644 + m88ds3103_tuner_writereg(state, 0x7c, 0x9a);
1645 + m88ds3103_tuner_writereg(state, 0x7a, 0x76);
1647 + m88ds3103_tuner_writereg(state, 0x3b, 0x01);
1648 + m88ds3103_tuner_writereg(state, 0x63, 0x88);
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);
1658 + if(state->demod_id == DS3103_ID){
1659 + m88ds3103_writereg(state, 0x07, 0xe0);
1660 + m88ds3103_writereg(state, 0x07, 0x00);
1663 + m88ds3103_writereg(state, 0xb2, 0x01);
1665 + /* Load the firmware if required */
1666 + ret = m88ds3103_load_firmware(fe);
1668 + printk(KERN_ERR "%s: Unable initialize firmware\n", __func__);
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));
1680 + * Initialise or wake up device
1682 +static int m88ds3103_initfe(struct dvb_frontend *fe)
1684 + struct m88ds3103_state *state = fe->demodulator_priv;
1687 + dprintk("%s()\n", __func__);
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));
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);
1700 + m88ds3103_tuner_writereg(state, 0x00, 0x03);
1706 +/* Put device to sleep */
1707 +static int m88ds3103_sleep(struct dvb_frontend *fe)
1709 + struct m88ds3103_state *state = fe->demodulator_priv;
1711 + dprintk("%s()\n", __func__);
1713 + /* 1st step to sleep tuner */
1714 + m88ds3103_tuner_writereg(state, 0x00, 0x00);
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));
1725 +static struct dvb_frontend_ops m88ds3103_ops = {
1726 + .delsys = { SYS_DVBS, SYS_DVBS2},
1728 + .name = "Montage DS3103/TS2022",
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
1744 + .release = m88ds3103_release,
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,
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
1769 +++ b/drivers/media/dvb-frontends/dvbsky_m88ds3103.h
1772 + Montage Technology M88DS3103/M88TS2022 - DVBS/S2 Satellite demod/tuner driver
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.
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.
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.
1789 +#ifndef DVBSKY_M88DS3103_H
1790 +#define DVBSKY_M88DS3103_H
1792 +#include <linux/kconfig.h>
1793 +#include <linux/dvb/frontend.h>
1795 +struct dvbsky_m88ds3103_config {
1796 + /* the demodulator's i2c address */
1800 + u8 ts_mode; /* 0: Parallel, 1: Serial */
1801 + u8 tuner_readstops;
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);
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);
1816 +static inline struct dvb_frontend *dvbsky_m88ds3103_attach(
1817 + const struct dvbsky_m88ds3103_config *config,
1818 + struct i2c_adapter *i2c)
1820 + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
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
1829 +++ b/drivers/media/dvb-frontends/dvbsky_m88ds3103_priv.h
1832 + Montage Technology M88DS3103/M88TS2022 - DVBS/S2 Satellite demod/tuner driver
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.
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.
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.
1849 +#ifndef DVBSKY_M88DS3103_PRIV_H
1850 +#define DVBSKY_M88DS3103_PRIV_H
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
1865 +struct m88ds3103_state {
1866 + struct i2c_adapter *i2c;
1867 + const struct dvbsky_m88ds3103_config *config;
1869 + struct dvb_frontend frontend;
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;
1879 +/* For M88DS3103 demod dvbs mode.*/
1880 +static u8 ds3103_dvbs_init_tab[] = {
1962 +/* For M88DS3103 demod dvbs2 mode.*/
1963 +static u8 ds3103_dvbs2_init_tab[] = {
2049 +/* For M88DS3000 demod dvbs mode.*/
2050 +static u8 ds3000_dvbs_init_tab[] = {
2133 +/* For M88DS3000 demod dvbs2 mode.*/
2134 +static u8 ds3000_dvbs2_init_tab[] = {
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
2238 +++ b/drivers/media/dvb-frontends/m88dc2800.c
2241 + M88DC2800/M88TC2800 - DVB-C demodulator and tuner from Montage
2243 + Copyright (C) 2012 Max nibble<nibble.max@gmail.com>
2244 + Copyright (C) 2011 Montage Technology / www.montage-tech.com
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.
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.
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.
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"
2272 +struct m88dc2800_state {
2273 + struct i2c_adapter *i2c;
2274 + const struct m88dc2800_config *config;
2275 + struct dvb_frontend frontend;
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 */
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 */
2299 +module_param(debug, int, 0644);
2300 +MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
2302 +#define dprintk(args...) \
2305 + printk(KERN_INFO "m88dc2800: " args); \
2309 +static int m88dc2800_i2c_write(struct m88dc2800_state *state, u8 addr,
2310 + u8 * p_data, u8 len)
2312 + struct i2c_msg msg = { .flags = 0 };
2318 + return i2c_transfer(state->i2c, &msg, 1);
2321 +static int m88dc2800_i2c_read(struct m88dc2800_state *state, u8 addr,
2322 + u8 * p_data, u8 len)
2324 + struct i2c_msg msg = { .flags = I2C_M_RD };
2330 + return i2c_transfer(state->i2c, &msg, 1);
2333 +/*demod register operations.*/
2334 +static int WriteReg(struct m88dc2800_state *state, u8 reg, u8 data)
2336 + u8 buf[] = { reg, data };
2337 + u8 addr = state->config->demod_address;
2340 + dprintk("%s: write reg 0x%02x, value 0x%02x\n", __func__, reg, data);
2342 + err = m88dc2800_i2c_write(state, addr, buf, 2);
2346 + "%s: writereg error(err == %i, reg == 0x%02x,"
2347 + " value == 0x%02x)\n", __func__, err, reg, data);
2353 +static int ReadReg(struct m88dc2800_state *state, u8 reg)
2356 + u8 b0[] = { reg };
2358 + u8 addr = state->config->demod_address;
2360 + ret = m88dc2800_i2c_write(state, addr, b0, 1);
2363 + printk(KERN_ERR "%s: reg=0x%x (error=%d)\n",
2364 + __func__, reg, ret);
2368 + ret = m88dc2800_i2c_read(state, addr, b1, 1);
2370 + dprintk("%s: read reg 0x%02x, value 0x%02x\n", __func__, reg, b1[0]);
2374 +static int _mt_fe_tn_set_reg(struct m88dc2800_state *state, u8 reg,
2379 + u8 addr = state->tuner_dev_addr;
2381 + buf[1] = ReadReg(state, 0x86);
2383 + ret = WriteReg(state, 0x86, buf[1]);
2388 + ret = m88dc2800_i2c_write(state, addr, buf, 2);
2394 +static int _mt_fe_tn_get_reg(struct m88dc2800_state *state, u8 reg,
2399 + u8 addr = state->tuner_dev_addr;
2401 + buf[1] = ReadReg(state, 0x86);
2403 + ret = WriteReg(state, 0x86, buf[1]);
2406 + ret = m88dc2800_i2c_write(state, addr, buf, 1);
2410 + buf[1] = ReadReg(state, 0x86);
2412 + ret = WriteReg(state, 0x86, buf[1]);
2414 + return m88dc2800_i2c_read(state, addr, p_data, 1);
2417 +/* Tuner operation functions.*/
2418 +static int _mt_fe_tn_set_RF_front_tc2800(struct m88dc2800_state *state)
2420 + u32 freq_KHz = state->tuner_freq;
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;
2439 + a = 0x70; b = 0x07; c = 0x38;
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);
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);
2472 + _mt_fe_tn_set_reg(state, 0x73, 0x0e);
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);
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);
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);
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);
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);
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);
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);
2560 + _mt_fe_tn_set_reg(state, 0x5b, 0x2a);
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);
2572 + _mt_fe_tn_set_reg(state, 0x5c, 0xa8);
2574 + _mt_fe_tn_set_reg(state, 0x5b, 0x08);
2577 + } /* end of 0xE1 */
2581 +static int _mt_fe_tn_cali_PLL_tc2800(struct m88dc2800_state *state,
2583 + u32 cali_freq_thres_div2,
2584 + u32 cali_freq_thres_div3r,
2585 + u32 cali_freq_thres_div3)
2588 + u8 buf, tmp, tmp2;
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) {
2596 + } else if (freq_KHz > 300000) {
2599 + } else if (freq_KHz > (cali_freq_thres_div2 / 2)) {
2602 + } else if (freq_KHz > (cali_freq_thres_div2 / 4)) {
2605 + } else if (freq_KHz > (cali_freq_thres_div2 / 8)) {
2608 + } else if (freq_KHz > (cali_freq_thres_div2 / 16)) {
2611 + } else { /* invalid */
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) {
2629 + tmp2 = M + 16; /* 48 */
2630 + } else if (freq_KHz > cali_freq_thres_div3r) {
2634 + tmp2 = M + 32; /* 32 */
2635 + } else if (freq_KHz > cali_freq_thres_div3) {
2639 + tmp2 = M; /* 16 */
2640 + } else if (freq_KHz > 304000) {
2644 + tmp2 = M + 16; /* 48 */
2645 + } else if (freq_KHz > (cali_freq_thres_div2 / 2)) {
2649 + tmp2 = M + 16; /* 48 */
2650 + } else if (freq_KHz > (cali_freq_thres_div3r / 2)) {
2654 + tmp2 = M + 32; /* 32 */
2655 + } else if (freq_KHz > (cali_freq_thres_div3 / 2)) {
2659 + tmp2 = M; /* 16 */
2660 + } else if (freq_KHz > (cali_freq_thres_div2 / 4)) {
2664 + tmp2 = M + 16; /* 48 */
2665 + } else if (freq_KHz > (cali_freq_thres_div3r / 4)) {
2669 + tmp2 = M + 32; /* 32 */
2670 + } else if (freq_KHz > (cali_freq_thres_div3 / 4)) {
2674 + tmp2 = M; /* 16 */
2675 + } else if (freq_KHz > (cali_freq_thres_div2 / 8)) {
2679 + tmp2 = M + 16; /* 48 */
2680 + } else if (freq_KHz > (cali_freq_thres_div3r / 8)) {
2684 + tmp2 = M + 32; /* 32 */
2685 + } else if (freq_KHz > (cali_freq_thres_div3 / 8)) {
2689 + tmp2 = M; /* 16 */
2690 + } else if (freq_KHz > (cali_freq_thres_div2 / 16)) {
2694 + tmp2 = M + 16; /* 48 */
2695 + } else if (freq_KHz > (cali_freq_thres_div3r / 16)) {
2699 + tmp2 = M + 32; /* 32 */
2700 + } else if (freq_KHz > (cali_freq_thres_div3 / 16)) {
2704 + tmp2 = M; /* 16 */
2705 + } else { /* invalid */
2712 + if (freq_KHz == 291000) {
2713 + M = state->tuner_crystal / 1000 / 3;
2716 + tmp2 = M + 32; /* 32 */
2719 + if (freq_KHz == 578000) {
2720 + M = state->tuner_crystal / 1000 / 4;
2723 + tmp2 = M + 16; // 48
2726 + if (freq_KHz == 690000) {
2727 + M = state->tuner_crystal / 1000 / 3;
2730 + tmp2 = M + 16; /* 48 */
2732 + _mt_fe_tn_get_reg(state, 0x33, &buf);
2735 + _mt_fe_tn_set_reg(state, 0x33, buf);
2739 + _mt_fe_tn_get_reg(state, 0x39, &buf);
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) {
2748 + _mt_fe_tn_set_reg(state, 0x34, buf);
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;
2754 + _mt_fe_tn_set_reg(state, 0x36, buf);
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);
2763 + _mt_fe_tn_set_reg(state, 0x3e, 0x9c);
2764 + _mt_fe_tn_set_reg(state, 0x3f, 0x34);
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);
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);
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);
2784 + _mt_fe_tn_set_reg(state, 0x39, buf);
2785 + _mt_fe_tn_get_reg(state, 0x32, &buf);
2787 + _mt_fe_tn_set_reg(state, 0x32, buf);
2792 + _mt_fe_tn_set_reg(state, 0x41, 0x00);
2793 + if (state->tuner_mtt == 0xD1) {
2795 + } else if (state->tuner_mtt == 0xE1) {
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);
2809 +static int _mt_fe_tn_set_PLL_freq_tc2800(struct m88dc2800_state *state)
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);
2826 + _mt_fe_tn_get_reg(state, 0x3a, &buf);
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,
2836 + _mt_fe_tn_get_reg(state, 0x3a, &buf);
2839 + freq_thres_div2_KHz = 520000;
2840 + _mt_fe_tn_cali_PLL_tc2800(state, freq_KHz,
2841 + freq_thres_div2_KHz,
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);
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);
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);
2862 + _mt_fe_tn_get_reg(state, 0x39, &buf);
2865 + _mt_fe_tn_get_reg(state, 0x39, &buf);
2868 + _mt_fe_tn_set_reg(state, 0x39, buf);
2869 + _mt_fe_tn_get_reg(state, 0x32, &buf);
2871 + _mt_fe_tn_set_reg(state, 0x32, buf);
2873 + _mt_fe_tn_get_reg(state, 0x37, &buf);
2876 + _mt_fe_tn_set_reg(state, 0x40, 0x40);
2878 + _mt_fe_tn_set_reg(state, 0x37, buf);
2879 + _mt_fe_tn_get_reg(state, 0x38, &buf);
2881 + buf = (buf & 0x0f) << 2;
2883 + _mt_fe_tn_set_reg(state, 0x37, buf);
2884 + } else if (buf < 0x1f) {
2886 + _mt_fe_tn_set_reg(state, 0x37, buf);
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);
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);
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);
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);
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);
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);
2923 + _mt_fe_tn_get_reg(state, 0x37, &buf);
2924 + _mt_fe_tn_set_reg(state, 0x37, buf);
2926 + if ((freq_KHz == 802000) || (freq_KHz == 826000)) {
2927 + _mt_fe_tn_set_reg(state, 0x37, 0x5e);
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);
2935 + _mt_fe_tn_set_reg(state, 0x41, 0x02);
2942 +static int _mt_fe_tn_set_BB_tc2800(struct m88dc2800_state *state)
2947 + static int _mt_fe_tn_set_appendix_tc2800(struct m88dc2800_state *state)
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);
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));
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));
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);
2985 + static int _mt_fe_tn_set_DAC_tc2800(struct m88dc2800_state *state)
2987 + u8 buf, tempnumber;
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;
3000 + if (state->tuner_mtt == 0xE1) {
3001 + _mt_fe_tn_get_reg(state, 0x33, &buf);
3006 + _mt_fe_tn_get_reg(state, 0x34, &buf);
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)) {
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)) {
3055 + _mt_fe_tn_set_reg(state, 0x0e, buf);
3056 + _mt_fe_tn_set_reg(state, 0x0d, buf);
3058 + (((DACFreq_KHz * M * buf) / crystal_KHz) << 16) / (N + 256) +
3059 + (((DACFreq_KHz * M * buf) % crystal_KHz) << 16) / ((N + 256) *
3061 + _mt_fe_tn_set_reg(state, 0xf1, (f1f2number & 0xff00) >> 8);
3062 + _mt_fe_tn_set_reg(state, 0xf2, f1f2number & 0x00ff);
3064 + (N + 256) * crystal_KHz / (M * buf) * 1000 +
3065 + (((N + 256) * crystal_KHz) % (M * buf)) * 1000 / (M * buf);
3067 + fc = FreqTrue108_Hz;
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;
3075 + cntin = Totalnum1;
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);
3095 + delta1 = ((f1 - f2) << 15) / f2;
3096 + Totalnum1 = ((f1 - f2) << 15) - delta1 * f2;
3097 + NCOI = (f1 << 15) / f2 - (1 << 15);
3099 + cntin = Totalnum1;
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);
3119 +static int _mt_fe_tn_preset_tc2800(struct m88dc2800_state *state)
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);
3163 + _mt_fe_tn_set_reg(state, 0x67, 0x05);
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);
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);
3194 +static int mt_fe_tn_wakeup_tc2800(struct m88dc2800_state *state)
3196 + _mt_fe_tn_set_reg(state, 0x16, 0xb1);
3197 + _mt_fe_tn_set_reg(state, 0x09, 0x7d);
3201 + static int mt_fe_tn_sleep_tc2800(struct m88dc2800_state *state)
3203 + _mt_fe_tn_set_reg(state, 0x16, 0xb0);
3204 + _mt_fe_tn_set_reg(state, 0x09, 0x6d);
3208 + static int mt_fe_tn_init_tc2800(struct m88dc2800_state *state)
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;
3225 + _mt_fe_tn_set_reg(state, 0x2b, 0x46);
3226 + _mt_fe_tn_set_reg(state, 0x2c, 0x75);
3227 + if (state->tuner_mtt == 0x00) {
3229 + _mt_fe_tn_get_reg(state, 0x01, &tmp);
3230 + printk(KERN_INFO "m88dc2800: tuner id = 0x%02x ", tmp);
3233 + state->tuner_mtt = 0xD1;
3237 + state->tuner_mtt = 0xE1;
3244 + static int mt_fe_tn_set_freq_tc2800(struct m88dc2800_state *state,
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);
3267 + _mt_fe_tn_set_reg(state, 0x41, 0x00);
3269 + _mt_fe_tn_set_reg(state, 0x41, 0x02);
3271 + _mt_fe_tn_get_reg(state, 0x69, &buf1);
3272 + buf1 = buf1 & 0x0f;
3273 + _mt_fe_tn_get_reg(state, 0x61, &buf);
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);
3283 + _mt_fe_tn_set_reg(state, 0x66, 0x74);
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);
3299 + _mt_fe_tn_set_reg(state, 0x87, 0x54);
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);
3315 + _mt_fe_tn_set_reg(state, 0x87, 0x54);
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);
3322 + _mt_fe_tn_get_reg(state, 0x32, &buf);
3323 + buf = (buf & 0xef) | 0x28;
3324 + _mt_fe_tn_set_reg(state, 0x32, buf);
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);
3332 + _mt_fe_tn_get_reg(state, 0x69, &buf);
3334 + _mt_fe_tn_set_reg(state, 0x2a, buf);
3337 + _mt_fe_tn_get_reg(state, 0x84, &buf);
3339 + _mt_fe_tn_set_reg(state, 0x68, 0x0a);
3340 + _mt_fe_tn_get_reg(state, 0x88, &buf1);
3341 + buf1 = buf1 & 0x1f;
3343 + _mt_fe_tn_set_reg(state, 0x66, 0x44);
3345 + _mt_fe_tn_set_reg(state, 0x66, 0x74);
3347 + if (freq_KHz <= 600000)
3348 + _mt_fe_tn_set_reg(state, 0x68, 0x0c);
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);
3356 + if (state->tuner_loopthrough != 0) {
3357 + _mt_fe_tn_get_reg(state, 0x28, &buf);
3359 + _mt_fe_tn_set_reg(state, 0x28, 0xff);
3360 + _mt_fe_tn_get_reg(state, 0x61, &buf);
3363 + _mt_fe_tn_set_reg(state, 0x67, 0x74);
3365 + _mt_fe_tn_set_reg(state, 0x67, 0x64);
3367 + _mt_fe_tn_set_reg(state, 0x67, 0x54);
3369 + _mt_fe_tn_set_reg(state, 0x67, 0x44);
3372 + _mt_fe_tn_set_reg(state, 0x67, 0x34);
3382 +static int mt_fe_tn_set_BB_filter_band_tc2800(struct m88dc2800_state *state,
3387 + _mt_fe_tn_get_reg(state, 0x53, &tmp);
3389 + if (bandwidth == 6)
3391 + else if (bandwidth == 7)
3393 + else if (bandwidth == 8)
3400 + _mt_fe_tn_set_reg(state, 0x53, tmp);
3401 + state->tuner_bandwidth = bandwidth;
3406 +static s32 mt_fe_tn_get_signal_strength_tc2800(struct m88dc2800_state
3410 + s32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
3411 + s32 val1, val2, val;
3412 + s32 result2, result3, result4, result5, result6;
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;
3431 + if (freq_KHz <= 200000) {
3432 + val2 = (tmp1 - 6) * 267;
3433 + } else if (freq_KHz <= 600000) {
3434 + val2 = (tmp1 - 6) * 280;
3436 + val2 = (tmp1 - 6) * 290;
3438 + val = val1 + val2;
3445 + if ((tmp1 < 4) && (freq_KHz >= 506000)) {
3449 + val = val1 + val2;
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;
3468 + result2 = tmp2 * 200;
3470 + result3 = (6 - tmp3) * 100;
3471 + result4 = 300 * tmp4;
3472 + result5 = 50 * tmp5;
3473 + result6 = 300 * tmp6;
3474 + if (freq_KHz < 105000) {
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;
3487 + level = append - (val + result2 + result3 + result4 +
3488 + result5 + result6);
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;
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;
3520 + result2 = (307 - freq_KHz / 1000) * 82 / 27 + 11270;
3528 + } else if (tmp1 > 0) {
3537 + level = val1 - (val2 * tmp1 + 500 * tmp2 + 3000 * tmp3 -
3538 + 500 * tmp4 + 3000 * tmp5 + val * tmp6) - 1000;
3545 +/* m88dc2800 operation functions */
3546 +u8 M88DC2000GetLock(struct m88dc2800_state * state)
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)
3557 + if ((ReadReg(state, 0x85) & 0x08) == 0x08)
3562 + dprintk("%s, lock=%d\n", __func__, u8ret);
3566 +static int M88DC2000SetTsType(struct m88dc2800_state *state, u8 type)
3571 + WriteReg(state, 0x84, 0x6A);
3572 + WriteReg(state, 0xC0, 0x43);
3573 + WriteReg(state, 0xE2, 0x06);
3574 + regC2H = ReadReg(state, 0xC2);
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);
3585 + WriteReg(state, 0xC2, regC2H);
3586 + WriteReg(state, 0xC1, 0x00);
3588 + WriteReg(state, 0x84, 0x6C);
3589 + WriteReg(state, 0xC0, 0x43); /* parallel format */
3590 + WriteReg(state, 0xE2, 0x06);
3591 + regC2H = ReadReg(state, 0xC2);
3593 + WriteReg(state, 0xC2, regC2H);
3594 + WriteReg(state, 0xC1, 0x00);
3599 +static int M88DC2000RegInitial_TC2800(struct m88dc2800_state *state)
3601 + u8 RegE3H, RegE4H;
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);
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);
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);
3744 +static int M88DC2000AutoTSClock_P(struct m88dc2800_state *state, u32 sym,
3748 + u8 clk_div, value;
3750 + "m88dc2800: M88DC2000AutoTSClock_P, symrate=%d qam=%d\n",
3770 + dataRate *= sym * 105;
3772 + if (dataRate <= 4115)
3774 + else if (dataRate <= 4800)
3776 + else if (dataRate <= 5760)
3778 + else if (dataRate <= 7200)
3780 + else if (dataRate <= 9600)
3784 + value = ReadReg(state, 0xC2);
3787 + WriteReg(state, 0xC2, value);
3791 +static int M88DC2000AutoTSClock_C(struct m88dc2800_state *state, u32 sym,
3795 + u8 clk_div, value;
3797 + "m88dc2800: M88DC2000AutoTSClock_C, symrate=%d qam=%d\n",
3817 + dataRate *= sym * 105;
3819 + if (dataRate <= 4115)
3821 + else if (dataRate <= 4800)
3823 + else if (dataRate <= 5760)
3825 + else if (dataRate <= 7200)
3827 + else if (dataRate <= 9600)
3831 + value = ReadReg(state, 0xC2);
3834 + WriteReg(state, 0xC2, value);
3838 +static int M88DC2000SetTxMode(struct m88dc2800_state *state, u8 inverted,
3843 + value |= 0x08; /* spectrum inverted */
3845 + value |= 0x01; /* J83C */
3846 + WriteReg(state, 0x83, value);
3850 +static int M88DC2000SoftReset(struct m88dc2800_state *state)
3852 + WriteReg(state, 0x80, 0x01);
3853 + WriteReg(state, 0x82, 0x00);
3855 + WriteReg(state, 0x80, 0x00);
3859 +static int M88DC2000SetSym(struct m88dc2800_state *state, u32 sym, u32 xtal)
3862 + u8 reg6FH, reg12H;
3866 + printk(KERN_INFO "%s, sym=%d, xtal=%d\n", __func__, sym, xtal);
3867 + fValue = 4294967296 * (sym + 10);
3868 + do_div(fValue, xtal);
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));
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)
3890 + WriteReg(state, 0x5A, value);
3891 + value = ReadReg(state, 0x89);
3896 + WriteReg(state, 0x89, value);
3897 + if (sym >= 6700) {
3900 + } else if (sym >= 4000) {
3901 + fValue = 22 * 4096 / sym;
3902 + reg6FH = (u8) fValue;
3904 + } else if (sym >= 2000) {
3905 + fValue = 14 * 4096 / sym;
3906 + reg6FH = (u8) fValue;
3909 + fValue = 7 * 4096 / sym;
3910 + reg6FH = (u8) fValue;
3913 + WriteReg(state, 0x6F, reg6FH);
3914 + WriteReg(state, 0x12, reg12H);
3915 + if (((ReadReg(state, 0xE3) & 0x80) == 0x80)
3916 + && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) {
3918 + WriteReg(state, 0x6C, 0x16);
3919 + WriteReg(state, 0x6D, 0x10);
3920 + WriteReg(state, 0x6E, 0x18);
3922 + WriteReg(state, 0x6C, 0x14);
3923 + WriteReg(state, 0x6D, 0x0E);
3924 + WriteReg(state, 0x6E, 0x36);
3927 + WriteReg(state, 0x6C, 0x16);
3928 + WriteReg(state, 0x6D, 0x10);
3929 + WriteReg(state, 0x6E, 0x18);
3934 +static int M88DC2000SetQAM(struct m88dc2800_state *state, u16 qam)
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);
3942 + case 16: /* 16 QAM */
3950 + if (((ReadReg(state, 0xE3) & 0x80) == 0x80)
3951 + && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) {
3958 + WriteReg(state, 0x6E, 0x18);
3960 + case 32: /* 32 QAM */
3968 + if (((ReadReg(state, 0xE3) & 0x80) == 0x80)
3969 + && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) {
3976 + WriteReg(state, 0x6E, 0x18);
3978 + case 64: /* 64 QAM */
3986 + if (((ReadReg(state, 0xE3) & 0x80) == 0x80)
3987 + && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) {
3995 + case 128: /* 128 QAM */
4006 + case 256: /* 256 QAM */
4009 + if (((ReadReg(state, 0xE3) & 0x80) == 0x80)
4010 + && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) {
4022 + default: /* 64 QAM */
4030 + if (((ReadReg(state, 0xE3) & 0x80) == 0x80)
4031 + && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) {
4040 + WriteReg(state, 0x00, reg00H);
4041 + value = ReadReg(state, 0x88);
4043 + WriteReg(state, 0x88, value);
4044 + WriteReg(state, 0x4B, 0xFF);
4045 + WriteReg(state, 0x4A, reg4AH);
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);
4058 +static int M88DC2000WriteTuner_TC2800(struct m88dc2800_state *state,
4061 + printk(KERN_INFO "%s, freq=%d KHz\n", __func__, freq_KHz);
4062 + return mt_fe_tn_set_freq_tc2800(state, freq_KHz);
4065 +static int m88dc2800_init(struct dvb_frontend *fe)
4067 + dprintk("%s()\n", __func__);
4071 +static int m88dc2800_set_parameters(struct dvb_frontend *fe)
4073 + struct dtv_frontend_properties *c = &fe->dtv_property_cache;
4074 + u8 is_annex_c, is_update;
4077 + struct m88dc2800_state *state = fe->demodulator_priv;
4079 + is_annex_c = c->delivery_system == SYS_DVBC_ANNEX_C ? 1 : 0;
4081 + switch (c->modulation) {
4094 + default: /* QAM_64 */
4099 + state->inverted = c->inversion == INVERSION_ON ? 1 : 0;
4102 + "m88dc2800: state, freq=%d qam=%d sym=%d inverted=%d xtal=%d\n",
4103 + state->freq, state->qam, state->sym, state->inverted,
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);
4110 + WriteReg(state, 0x80, 0x01);
4111 + if (c->frequency != state->freq) {
4112 + M88DC2000WriteTuner_TC2800(state, c->frequency / 1000);
4113 + state->freq = c->frequency;
4115 + if (c->symbol_rate != state->sym) {
4116 + M88DC2000SetSym(state, c->symbol_rate / 1000, state->xtal);
4117 + state->sym = c->symbol_rate;
4120 + if (temp_qam != state->qam) {
4121 + M88DC2000SetQAM(state, temp_qam);
4122 + state->qam = temp_qam;
4126 + if (is_update != 0) {
4127 + if (state->config->ts_mode == 3)
4128 + M88DC2000AutoTSClock_C(state, state->sym / 1000,
4131 + M88DC2000AutoTSClock_P(state, state->sym / 1000,
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;
4141 + waiting_time = 500;
4142 + while (waiting_time > 0) {
4144 + waiting_time -= 50;
4145 + if (M88DC2000GetLock(state))
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;
4156 + waiting_time = 500;
4157 + while (waiting_time > 0) {
4159 + waiting_time -= 50;
4160 + if (M88DC2000GetLock(state))
4166 +static int m88dc2800_read_status(struct dvb_frontend *fe,
4167 + fe_status_t * status)
4169 + struct m88dc2800_state *state = fe->demodulator_priv;
4172 + if (M88DC2000GetLock(state)) {
4173 + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER
4174 + |FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_LOCK;
4179 +static int m88dc2800_read_ber(struct dvb_frontend *fe, u32 * ber)
4181 + struct m88dc2800_state *state = fe->demodulator_priv;
4184 + if (M88DC2000GetLock(state) == 0) {
4186 + } else if ((ReadReg(state, 0xA0) & 0x80) != 0x80) {
4187 + tmp = ReadReg(state, 0xA2) << 8;
4188 + tmp += ReadReg(state, 0xA1);
4190 + WriteReg(state, 0xA0, 0x05);
4191 + WriteReg(state, 0xA0, 0x85);
4193 + *ber = state->ber;
4197 +static int m88dc2800_read_signal_strength(struct dvb_frontend *fe,
4200 + struct m88dc2800_state *state = fe->demodulator_priv;
4201 + s16 tuner_strength;
4203 + tuner_strength = mt_fe_tn_get_signal_strength_tc2800(state);
4204 + *strength = tuner_strength < -107 ? 0 : tuner_strength + 107;
4209 +static int m88dc2800_read_snr(struct dvb_frontend *fe, u16 * snr)
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
4222 + struct m88dc2800_state *state = fe->demodulator_priv;
4226 + if ((ReadReg(state, 0x91) & 0x23) != 0x03) {
4231 + for (i = 0; i < 30; i++) {
4232 + mse += (ReadReg(state, 0x08) << 8) + ReadReg(state, 0x07);
4237 + switch (state->qam) {
4240 + break; /* 16QAM */
4243 + break; /* 32QAM */
4246 + break; /* 64QAM */
4249 + break; /* 128QAM */
4252 + break; /* 256QAM */
4257 + _snr -= mes_log[mse - 1]; /* C - 10*log10(MSE) */
4265 +static int m88dc2800_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks)
4267 + struct m88dc2800_state *state = fe->demodulator_priv;
4270 + u8Value = ReadReg(state, 0xdf);
4271 + u8Value |= 0x02; /* Hold */
4272 + WriteReg(state, 0xdf, u8Value);
4274 + *ucblocks = ReadReg(state, 0xd5);
4275 + *ucblocks = (*ucblocks << 8) | ReadReg(state, 0xd4);
4277 + u8Value &= 0xfe; /* Clear */
4278 + WriteReg(state, 0xdf, u8Value);
4279 + u8Value &= 0xfc; /* Update */
4281 + WriteReg(state, 0xdf, u8Value);
4286 +static int m88dc2800_sleep(struct dvb_frontend *fe)
4288 + struct m88dc2800_state *state = fe->demodulator_priv;
4290 + mt_fe_tn_sleep_tc2800(state);
4296 +static void m88dc2800_release(struct dvb_frontend *fe)
4298 + struct m88dc2800_state *state = fe->demodulator_priv;
4302 +static struct dvb_frontend_ops m88dc2800_ops;
4304 +struct dvb_frontend *m88dc2800_attach(const struct m88dc2800_config
4305 + *config, struct i2c_adapter *i2c)
4307 + struct m88dc2800_state *state = NULL;
4309 + /* allocate memory for the internal state */
4310 + state = kzalloc(sizeof(struct m88dc2800_state), GFP_KERNEL);
4311 + if (state == NULL)
4314 + /* setup the state */
4315 + state->config = config;
4317 + state->xtal = 28800;
4319 + WriteReg(state, 0x80, 0x01);
4320 + M88DC2000RegInitial_TC2800(state);
4321 + M88DC2000SetTsType(state, state->config->ts_mode);
4322 + mt_fe_tn_init_tc2800(state);
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;
4335 +EXPORT_SYMBOL(m88dc2800_attach);
4337 +static struct dvb_frontend_ops m88dc2800_ops = {
4338 + .delsys = {SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_C},
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
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,
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
4368 +++ b/drivers/media/dvb-frontends/m88dc2800.h
4371 + M88DC2800/M88TC2800 - DVB-C demodulator and tuner from Montage
4373 + Copyright (C) 2012 Max Nibble <nibble.max@gmail.com>
4374 + Copyright (C) 2011 Montage Technology - www.montage-tech.com
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.
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.
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.
4391 +#ifndef M88DC2800_H
4392 +#define M88DC2800_H
4394 +#include <linux/kconfig.h>
4395 +#include <linux/dvb/frontend.h>
4397 +struct m88dc2800_config {
4402 +#if IS_ENABLED(CONFIG_DVB_M88DC2800)
4403 +extern struct dvb_frontend* m88dc2800_attach(const struct m88dc2800_config* config,
4404 + struct i2c_adapter* i2c);
4406 +static inline struct dvb_frontend* m88dc2800_attach(const struct m88dc2800_config* config,
4407 + struct i2c_adapter* i2c)
4409 + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
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;
4435 -int netup_ci_init(struct cx23885_tsport *port)
4436 +int netup_ci_init(struct cx23885_tsport *port, bool isDVBSky)
4438 struct netup_ci_state *state;
4439 u8 cimax_init[34] = {
4440 @@ -475,6 +475,11 @@ int netup_ci_init(struct cx23885_tsport *port)
4445 + cimax_init[32] = 0x22;
4446 + cimax_init[33] = 0x00;
4449 port->port_priv = state;
4452 @@ -548,3 +553,19 @@ void netup_ci_exit(struct cx23885_tsport *port)
4453 dvb_ca_en50221_release(&state->ca);
4457 +/* CI irq handler for DVBSky board*/
4458 +int dvbsky_ci_slot_status(struct cx23885_dev *dev)
4460 + struct cx23885_tsport *port = NULL;
4461 + struct netup_ci_state *state = NULL;
4463 + ci_dbg_print("%s:\n", __func__);
4466 + state = port->port_priv;
4467 + schedule_work(&state->work);
4468 + ci_dbg_print("%s: Wakeup CI0\n", __func__);
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);
4484 +extern int dvbsky_ci_slot_status(struct cx23885_dev *dev);
4487 diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c
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,
4497 + [CX23885_BOARD_BST_PS8512] = {
4498 + .name = "Bestunar PS8512",
4499 + .portb = CX23885_MPEG_DVB,
4501 + [CX23885_BOARD_DVBSKY_S950] = {
4502 + .name = "DVBSKY S950",
4503 + .portb = CX23885_MPEG_DVB,
4505 + [CX23885_BOARD_DVBSKY_S952] = {
4506 + .name = "DVBSKY S952",
4507 + .portb = CX23885_MPEG_DVB,
4508 + .portc = CX23885_MPEG_DVB,
4510 + [CX23885_BOARD_DVBSKY_S950_CI] = {
4512 + .name = "DVBSKY S950CI DVB-S2 CI",
4513 + .portb = CX23885_MPEG_DVB,
4515 + [CX23885_BOARD_DVBSKY_C2800E_CI] = {
4517 + .name = "DVBSKY C2800E DVB-C CI",
4518 + .portb = CX23885_MPEG_DVB,
4520 + [CX23885_BOARD_DVBSKY_T9580] = {
4521 + .name = "DVBSKY T9580",
4522 + .portb = CX23885_MPEG_DVB,
4523 + .portc = CX23885_MPEG_DVB,
4525 + [CX23885_BOARD_DVBSKY_T980_CI] = {
4527 + .name = "DVBSKY T980CI DVB-T2/C CI",
4528 + .portb = CX23885_MPEG_DVB,
4530 + [CX23885_BOARD_DVBSKY_T982] = {
4531 + .name = "DVBSKY T982",
4532 + .portb = CX23885_MPEG_DVB,
4533 + .portc = CX23885_MPEG_DVB,
4535 + [CX23885_BOARD_TT_4500_CI] = {
4537 + .name = "TT-budget CT2-4500 CI",
4538 + .portb = CX23885_MPEG_DVB,
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,
4547 + .subvendor = 0x14f1,
4548 + .subdevice = 0x8512,
4549 + .card = CX23885_BOARD_BST_PS8512,
4551 + .subvendor = 0x4254,
4552 + .subdevice = 0x0950,
4553 + .card = CX23885_BOARD_DVBSKY_S950,
4555 + .subvendor = 0x4254,
4556 + .subdevice = 0x0952,
4557 + .card = CX23885_BOARD_DVBSKY_S952,
4559 + .subvendor = 0x4254,
4560 + .subdevice = 0x950C,
4561 + .card = CX23885_BOARD_DVBSKY_S950_CI,
4563 + .subvendor = 0x4254,
4564 + .subdevice = 0x2800,
4565 + .card = CX23885_BOARD_DVBSKY_C2800E_CI,
4567 + .subvendor = 0x4254,
4568 + .subdevice = 0x9580,
4569 + .card = CX23885_BOARD_DVBSKY_T9580,
4571 + .subvendor = 0x4254,
4572 + .subdevice = 0x980C,
4573 + .card = CX23885_BOARD_DVBSKY_T980_CI,
4575 + .subvendor = 0x4254,
4576 + .subdevice = 0x0982,
4577 + .card = CX23885_BOARD_DVBSKY_T982,
4579 + .subvendor = 0x13C2,
4580 + .subdevice = 0x3013,
4581 + .card = CX23885_BOARD_TT_4500_CI,
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);
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);
4595 + cx23885_gpio_set(dev, GPIO_2);
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 */
4602 + cx23885_gpio_enable(dev, GPIO_2, 1);
4603 + cx23885_gpio_enable(dev, GPIO_11, 1);
4605 + cx23885_gpio_clear(dev, GPIO_2);
4606 + cx23885_gpio_clear(dev, GPIO_11);
4608 + cx23885_gpio_set(dev, GPIO_2);
4609 + cx23885_gpio_set(dev, GPIO_11);
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);
4626 + cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/
4631 +static int cx23885_ir_patch(struct i2c_adapter *i2c, u8 reg, u8 mask)
4633 + struct i2c_msg msgs[2];
4634 + u8 tx_buf[2], rx_buf[1];
4635 + /* Write register address */
4637 + msgs[0].addr = 0x4c;
4638 + msgs[0].flags = 0;
4640 + msgs[0].buf = (char *) tx_buf;
4641 + /* Read data from register */
4642 + msgs[1].addr = 0x4c;
4643 + msgs[1].flags = I2C_M_RD;
4645 + msgs[1].buf = (char *) rx_buf;
4647 + i2c_transfer(i2c, msgs, 2);
4650 + tx_buf[1] = rx_buf[0] | mask;
4651 + msgs[0].addr = 0x4c;
4652 + msgs[0].flags = 0;
4654 + msgs[0].buf = (char *) tx_buf;
4656 + return i2c_transfer(i2c, msgs, 1);
4659 int cx23885_ir_init(struct cx23885_dev *dev)
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);
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) {
4680 + v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config,
4681 + ir_rx_pin_cfg_count, ir_rx_pin_cfg);
4683 + cx23885_ir_patch(&(dev->i2c_bus[2].i2c_adap),0x1f,0x80);
4684 + cx23885_ir_patch(&(dev->i2c_bus[2].i2c_adap),0x23,0x80);
4686 case CX23885_BOARD_HAUPPAUGE_HVR1250:
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 */
4710 static int netup_jtag_io(void *device, int tms, int tdi, int read_tdo)
4713 @@ -1639,7 +1813,7 @@ static int netup_jtag_io(void *device, int tms, int tdi, int read_tdo)
4719 void cx23885_ir_pci_int_enable(struct cx23885_dev *dev)
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:
4736 cx23885_irq_add_enable(dev, PCI_MSK_AV_CORE);
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;
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;
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;
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;
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)
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 = {
4801 - .jtag_io = netup_jtag_io,
4803 +// struct altera_config netup_config = {
4805 +// .action = action,
4806 +// .jtag_io = netup_jtag_io,
4809 netup_initialize(dev);
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);
4816 - altera_init(&netup_config, fw);
4818 + // altera_init(&netup_config, fw);
4820 release_firmware(fw);
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);
4829 mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT);
4832 printk(KERN_WARNING "%s: %d buffers handled (should be 1)\n",
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);
4842 + if (cx23885_boards[dev->board].ci_type == 3 &&
4843 + (pci_status & PCI_MSK_GPIO0))
4844 + handled += dvbsky_ci_slot_status(dev);
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);
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);
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
4865 #include "stv6110.h"
4867 #include "cx24116.h"
4868 +#include "dvbsky_m88ds3103.h"
4869 +#include "m88dc2800.h"
4870 #include "cx24117.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,
4877 + .frequency_div = 1146000,
4880 static struct cx24116_config dvbworld_cx24116_config = {
4881 @@ -507,6 +510,93 @@ static struct xc5000_config mygica_x8507_xc5000_config = {
4886 +int bst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
4888 + struct cx23885_tsport *port = fe->dvb->priv;
4889 + struct cx23885_dev *dev = port->dev;
4891 + cx23885_gpio_enable(dev, GPIO_1, 1);
4892 + cx23885_gpio_enable(dev, GPIO_0, 1);
4894 + switch (voltage) {
4895 + case SEC_VOLTAGE_13:
4896 + cx23885_gpio_set(dev, GPIO_1);
4897 + cx23885_gpio_clear(dev, GPIO_0);
4899 + case SEC_VOLTAGE_18:
4900 + cx23885_gpio_set(dev, GPIO_1);
4901 + cx23885_gpio_set(dev, GPIO_0);
4903 + case SEC_VOLTAGE_OFF:
4904 + cx23885_gpio_clear(dev, GPIO_1);
4905 + cx23885_gpio_clear(dev, GPIO_0);
4911 +int dvbsky_set_voltage_sec(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
4913 + struct cx23885_tsport *port = fe->dvb->priv;
4914 + struct cx23885_dev *dev = port->dev;
4916 + cx23885_gpio_enable(dev, GPIO_12, 1);
4917 + cx23885_gpio_enable(dev, GPIO_13, 1);
4919 + switch (voltage) {
4920 + case SEC_VOLTAGE_13:
4921 + cx23885_gpio_set(dev, GPIO_13);
4922 + cx23885_gpio_clear(dev, GPIO_12);
4924 + case SEC_VOLTAGE_18:
4925 + cx23885_gpio_set(dev, GPIO_13);
4926 + cx23885_gpio_set(dev, GPIO_12);
4928 + case SEC_VOLTAGE_OFF:
4929 + cx23885_gpio_clear(dev, GPIO_13);
4930 + cx23885_gpio_clear(dev, GPIO_12);
4936 +/* bestunar single dvb-s2 */
4937 +static struct dvbsky_m88ds3103_config bst_ds3103_config = {
4938 + .demod_address = 0x68,
4942 + .set_voltage = bst_set_voltage,
4944 +/* DVBSKY dual dvb-s2 */
4945 +static struct dvbsky_m88ds3103_config dvbsky_ds3103_config_pri = {
4946 + .demod_address = 0x68,
4950 + .set_voltage = bst_set_voltage,
4952 +static struct dvbsky_m88ds3103_config dvbsky_ds3103_config_sec = {
4953 + .demod_address = 0x68,
4957 + .set_voltage = dvbsky_set_voltage_sec,
4960 +static struct dvbsky_m88ds3103_config dvbsky_ds3103_ci_config = {
4961 + .demod_address = 0x68,
4967 +static struct m88dc2800_config dvbsky_dc2800_config = {
4968 + .demod_address = 0x1c,
4972 static struct stv090x_config prof_8000_stv090x_config = {
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);
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);
4987 + case CX23885_BOARD_DVBSKY_S952:
4988 + switch (port->nr) {
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);
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);
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);
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);
5020 + case CX23885_BOARD_DVBSKY_T9580:
5021 + switch (port->nr) {
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);
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);
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);
5047 +// case CX23885_BOARD_DVBSKY_T982:
5048 +// switch (port->nr) {
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);
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);
5065 case CX23885_BOARD_PROF_8000:
5066 i2c_bus = &dev->i2c_bus[0];
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);
5072 - netup_ci_init(port);
5073 + netup_ci_init(port, false);
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);
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 */
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);
5098 + case CX23885_BOARD_DVBSKY_S950_CI: {
5099 + u8 eeprom[256]; /* 24C02 i2c eeprom */
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);
5110 + netup_ci_init(port, true);
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);
5122 @@ -1495,6 +1709,10 @@ int cx23885_dvb_unregister(struct cx23885_tsport *port)
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);
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:
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:
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;
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;
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;
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
5201 #define CX23885_BOARD_TBS_6980 41
5202 #define CX23885_BOARD_LEADTEK_WINFAST_PXPVR2200 42
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)
5215 #define GPIO_0 0x00000001
5216 #define GPIO_1 0x00000002
5217 #define GPIO_2 0x00000004
5218 @@ -234,7 +245,7 @@ struct cx23885_board {
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) */
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[] = {
5245 .mpeg = CX88_MPEG_DVB,
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,
5254 + .type = CX88_VMUX_DVB,
5257 + .mpeg = CX88_MPEG_DVB,
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,
5267 + .subvendor = 0x14f1,
5268 + .subdevice = 0x8312,
5269 + .card = CX88_BOARD_BST_PS8312,
5273 @@ -3551,6 +3567,12 @@ static void cx88_card_setup(struct cx88_core *core)
5274 cx_write(MO_SRST_IO, 1);
5277 + case CX88_BOARD_BST_PS8312:
5278 + cx_write(MO_GP1_IO, 0x808000);
5280 + cx_write(MO_GP1_IO, 0x808080);
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
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);
5302 +/*CX88_BOARD_BST_PS8312*/
5303 +static int bst_dvbs_set_voltage(struct dvb_frontend *fe,
5304 + fe_sec_voltage_t voltage)
5306 + struct cx8802_dev *dev= fe->dvb->priv;
5307 + struct cx88_core *core = dev->core;
5309 + cx_write(MO_GP1_IO, 0x111111);
5310 + switch (voltage) {
5311 + case SEC_VOLTAGE_13:
5312 + cx_write(MO_GP1_IO, 0x020200);
5314 + case SEC_VOLTAGE_18:
5315 + cx_write(MO_GP1_IO, 0x020202);
5317 + case SEC_VOLTAGE_OFF:
5318 + cx_write(MO_GP1_IO, 0x111100);
5322 + if (core->prev_set_voltage)
5323 + return core->prev_set_voltage(fe, voltage);
5327 +static int bst_dvbs_set_voltage_v2(struct dvb_frontend *fe,
5328 + fe_sec_voltage_t voltage)
5330 + struct cx8802_dev *dev= fe->dvb->priv;
5331 + struct cx88_core *core = dev->core;
5333 + cx_write(MO_GP1_IO, 0x111101);
5334 + switch (voltage) {
5335 + case SEC_VOLTAGE_13:
5336 + cx_write(MO_GP1_IO, 0x020200);
5338 + case SEC_VOLTAGE_18:
5340 + cx_write(MO_GP1_IO, 0x020202);
5342 + case SEC_VOLTAGE_OFF:
5344 + cx_write(MO_GP1_IO, 0x111110);
5348 + if (core->prev_set_voltage)
5349 + return core->prev_set_voltage(fe, voltage);
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 = {
5359 +static struct dvbsky_m88ds3103_config dvbsky_ds3103_config = {
5360 + .demod_address = 0x68,
5361 + .set_ts_params = ds3000_set_ts_param,
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;
5371 + case CX88_BOARD_BST_PS8312:
5372 + fe0->dvb.frontend = dvb_attach(dvbsky_m88ds3103_attach,
5373 + &dvbsky_ds3103_config,
5375 + if (fe0->dvb.frontend != NULL){
5377 + u8 b0[] = { 0x60 };
5379 + struct i2c_msg msg[] = {
5387 + .flags = I2C_M_RD,
5392 + ret = i2c_transfer(&core->i2c_adap, msg, 2);
5393 + printk("PS8312: config = %02x, %02x", b1[0],b1[1]);
5395 + fe0->dvb.frontend->ops.set_voltage = bst_dvbs_set_voltage_v2;
5397 + fe0->dvb.frontend->ops.set_voltage = bst_dvbs_set_voltage;
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);
5410 data = (data << 4) | ((gpio_key & 0xf0) >> 4);
5412 +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0)
5413 rc_keydown(ir->dev, data, 0);
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);
5421 + rc_keydown(ir->dev, RC_TYPE_UNKNOWN, data, 0);
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 */
5430 + addr = (data >> 8) & 0xffff;
5431 + cmd = (data >> 0) & 0x00ff;
5432 + scancode = RC_SCANCODE_NECX(addr, cmd);
5434 + if (0 == (gpio & ir->mask_keyup))
5435 + rc_keydown_notimeout(ir->dev, RC_TYPE_NEC, scancode, 0);
5437 + rc_keyup(ir->dev);
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);
5444 + rc_keyup(ir->dev);
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);
5451 + rc_keyup(ir->dev);
5454 + /* can't distinguish keydown/up :-/ */
5455 + rc_keydown_notimeout(ir->dev, RC_TYPE_UNKNOWN, data, 0);
5456 + rc_keyup(ir->dev);
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 */
5466 + case CX88_BOARD_BST_PS8312:
5467 + ir_codes = RC_MAP_DVBSKY;
5468 + ir->sampling = 0xff00; /* address */
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;
5481 @@ -538,8 +580,12 @@ void cx88_ir_irq(struct cx88_core *core)
5483 ir_raw_event_handle(ir->dev);
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)
5489 +static int get_key_pvr2000(struct IR_i2c *ir, enum rc_type *protocol,
5490 + u32 *scancode, u8 *toggle)
5495 @@ -562,9 +608,14 @@ static int get_key_pvr2000(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
5497 dprintk("IR Key/Flags: (0x%02x/0x%02x)\n",
5498 code & 0xff, flags & 0xff);
5500 +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0)
5501 *ir_key = code & 0xff;
5504 + *protocol = RC_TYPE_UNKNOWN;
5505 + *scancode = code & 0xff;
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
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 \
5529 rc-dntv-live-dvb-t.o \
5530 rc-dntv-live-dvbt-pro.o \
5533 rc-encore-enltv2.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
5539 +++ b/drivers/media/rc/keymaps/rc-dvbsky.c
5541 +/* rc-dvbsky.c - Keytable for Dvbsky Remote Controllers
5543 + * keymap imported from ir-keymaps.c
5546 + * Copyright (c) 2010-2012 by Nibble Max <nibble.max@gmail.com>
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.
5554 +#include <media/rc-map.h>
5555 +#include <linux/module.h>
5557 + * This table contains the complete RC5 code, instead of just the data part
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 },
5595 +static struct rc_map_list rc5_dvbsky_map = {
5597 + .scan = rc5_dvbsky,
5598 + .size = ARRAY_SIZE(rc5_dvbsky),
5599 + .rc_type = RC_TYPE_RC5,
5600 + .name = RC_MAP_DVBSKY,
5604 +static int __init init_rc_map_rc5_dvbsky(void)
5606 + return rc_map_register(&rc5_dvbsky_map);
5609 +static void __exit exit_rc_map_rc5_dvbsky(void)
5611 + rc_map_unregister(&rc5_dvbsky_map);
5614 +module_init(init_rc_map_rc5_dvbsky)
5615 +module_exit(exit_rc_map_rc5_dvbsky)
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
5625 Say Y here to support the Realtek RTL28xxU DVB USB receiver.
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
5633 + Say Y here to support the USB receivers from DVBSky.
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
5643 +dvb-usb-dvbsky-objs := dvbsky.o
5644 +obj-$(CONFIG_DVB_USB_DVBSKY) += dvb-usb-dvbsky.o
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
5653 +++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c
5656 + * Driver for DVBSky receiver
5658 + * Copyright (C) 2013 Max nibble <nibble.max@gmail.com>
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>
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.
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.
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.
5681 +#include "dvb_ca_en50221.h"
5682 +#include "dvb_usb.h"
5683 +#include "dvbsky_m88ds3103.h"
5685 +static int dvbsky_debug;
5686 +module_param(dvbsky_debug, int, 0644);
5687 +MODULE_PARM_DESC(dvbsky_debug, "Activates dvbsky usb debugging (default:0)");
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
5694 +#define dprintk(args...) \
5696 + if (dvbsky_debug) \
5697 + printk(KERN_INFO "dvbsky_usb: " args); \
5700 +DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
5702 +struct dvbsky_state {
5703 + struct mutex stream_mutex;
5704 + u8 ibuf[DVBSKY_BUF_LEN];
5705 + u8 obuf[DVBSKY_BUF_LEN];
5708 + struct dvb_ca_en50221 ci;
5709 + unsigned long next_status_checked_time;
5711 + u8 current_ci_flag;
5715 +static int dvbsky_usb_generic_rw(struct dvb_usb_device *d,
5716 + u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
5719 + struct dvbsky_state *state = d_to_priv(d);
5721 + mutex_lock(&d->usb_mutex);
5723 + memcpy(state->obuf, wbuf, wlen);
5725 + ret = dvb_usbv2_generic_rw_locked(d, state->obuf, wlen,
5726 + state->ibuf, rlen);
5728 + if (!ret && (rlen != 0))
5729 + memcpy(rbuf, state->ibuf, rlen);
5731 + mutex_unlock(&d->usb_mutex);
5735 +static int dvbsky_stream_ctrl(struct dvb_usb_device *d, u8 onoff)
5737 + struct dvbsky_state *state = d_to_priv(d);
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) {
5746 + ret = dvbsky_usb_generic_rw(d, obuf_post, 3, NULL, 0);
5747 + dprintk("%s() -on \n", __func__);
5749 + mutex_unlock(&state->stream_mutex);
5753 +/* CI opertaions */
5754 +static int dvbsky_ci_read_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
5758 + struct i2c_msg msg[] = {
5766 + .flags = I2C_M_RD,
5772 + ret = i2c_transfer(i2c_adap, msg, 2);
5775 + dprintk("%s: error, Reg = 0x%02x, Status = %d\n", __func__, reg, ret);
5781 +static int dvbsky_ci_write_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,
5787 + struct i2c_msg msg = {
5790 + .buf = &buffer[0],
5794 + if(len + 1 > sizeof(buffer)) {
5795 + dprintk("%s: len overflow.\n", __func__);
5800 + memcpy(&buffer[1], buf, len);
5802 + ret = i2c_transfer(i2c_adap, &msg, 1);
5805 + dprintk("%s: error, Reg=[0x%02x], Status=%d\n", __func__, reg, ret);
5811 +static int dvbsky_ci_op_cam(struct dvb_ca_en50221 *ci, int slot,
5812 + u8 flag, u8 read, int addr, u8 data)
5814 + struct dvb_usb_device *d = ci->data;
5815 + struct dvbsky_state *state = d_to_priv(d);
5818 + u8 command[4], respond[2], command_size, respond_size;
5820 + /*dprintk("%s()\n", __func__);*/
5824 + if (state->current_ci_flag != flag) {
5825 + ret = dvbsky_ci_read_i2c(&d->i2c_adap, state->ci_i2c_addr,
5833 + ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr,
5838 + state->current_ci_flag = flag;
5840 + command[1] = (u8)((addr >> 8) & 0xff); /*high part of address*/
5841 + command[2] = (u8)(addr & 0xff); /*low part of address*/
5843 + command[0] = 0x71;
5847 + command[0] = 0x70;
5848 + command[3] = data;
5852 + ret = dvbsky_usb_generic_rw(d, command, command_size, respond, respond_size);
5854 + dev_err(&d->udev->dev, "%s: %s() " \
5855 + "failed=%d\n", KBUILD_MODNAME, __func__, ret);
5857 + return (read) ? respond[1] : 0;
5860 +static int dvbsky_ci_read_attribute_mem(struct dvb_ca_en50221 *ci,
5861 + int slot, int addr)
5863 + return dvbsky_ci_op_cam(ci, slot, 0, DVBSKY_CI_RD, addr, 0);
5866 +static int dvbsky_ci_write_attribute_mem(struct dvb_ca_en50221 *ci,
5867 + int slot, int addr, u8 data)
5869 + return dvbsky_ci_op_cam(ci, slot, 0, 0, addr, data);
5872 +static int dvbsky_ci_read_cam_ctl(struct dvb_ca_en50221 *ci, int slot, u8 addr)
5874 + return dvbsky_ci_op_cam(ci, slot, DVBSKY_CI_CTL, DVBSKY_CI_RD, addr, 0);
5877 +static int dvbsky_ci_write_cam_ctl(struct dvb_ca_en50221 *ci, int slot,
5880 + return dvbsky_ci_op_cam(ci, slot, DVBSKY_CI_CTL, 0, addr, data);
5883 +static int dvbsky_ci_slot_reset(struct dvb_ca_en50221 *ci, int slot)
5885 + struct dvb_usb_device *d = ci->data;
5886 + struct dvbsky_state *state = d_to_priv(d);
5889 + dprintk("%s() slot=%d\n", __func__, slot);
5895 + ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr,
5904 + ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr,
5907 + dprintk("%s() slot=%d complete\n", __func__, slot);
5912 +static int dvbsky_ci_slot_shutdown(struct dvb_ca_en50221 *ci, int slot)
5914 + /* not implemented */
5915 + dprintk("%s()\n", __func__);
5919 +static int dvbsky_ci_slot_ts_enable(struct dvb_ca_en50221 *ci, int slot)
5921 + struct dvb_usb_device *d = ci->data;
5922 + struct dvbsky_state *state = d_to_priv(d);
5926 + dprintk("%s()\n", __func__);
5930 + dvbsky_ci_read_i2c(&d->i2c_adap, state->ci_i2c_addr,
5934 + ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr,
5939 +static int dvbsky_ci_poll_slot_status(struct dvb_ca_en50221 *ci, int slot,
5942 + struct dvb_usb_device *d = ci->data;
5943 + struct dvbsky_state *state = d_to_priv(d);
5946 + /*dprintk("%s()\n", __func__);*/
5948 + /* CAM module INSERT/REMOVE processing. slow operation because of i2c
5950 + if (time_after(jiffies, state->next_status_checked_time)) {
5951 + ret = dvbsky_ci_read_i2c(&d->i2c_adap, state->ci_i2c_addr,
5954 + /*dprintk("%s() status=%x\n", __func__, buf);*/
5956 + state->next_status_checked_time = jiffies
5957 + + msecs_to_jiffies(1000);
5963 + state->ci_status = DVB_CA_EN50221_POLL_CAM_PRESENT |
5964 + DVB_CA_EN50221_POLL_CAM_READY;
5967 + state->ci_status = 0;
5969 + /*dprintk("%s() ret=%x\n", __func__, state->ci_status);*/
5970 + return state->ci_status;
5973 +static int dvbsky_ci_init(struct dvb_usb_device *d)
5975 + struct dvbsky_state *state = d_to_priv(d);
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 */
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 */
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 */
6001 + 0x02, /* destination - module A */
6002 + 0x01, /* power on (use it like store place) */
6004 + 0x00, /* int status read only */
6005 + 0x00, /* Max: Disable the interrupt in USB solution.*/
6006 + 0x05, /* EXTINT=active-high, INT=push-pull */
6008 + 0x04, /* ack active low */
6009 + 0x00, /* LOCK = 0 */
6010 + 0x22, /* serial mode, rising in, rising out, MSB first*/
6011 + 0x00 /* synchronization */
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;
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;
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);
6041 + ret = dvb_ca_en50221_init(&d->adapter[0].dvb_adap, &state->ci, 0, 1);
6044 + state->ci_attached = 1;
6045 + dprintk("%s() complete.\n", __func__);
6049 +static void dvbsky_ci_release(struct dvb_usb_device *d)
6051 + struct dvbsky_state *state = d_to_priv(d);
6054 + if (state->ci_attached)
6055 + dvb_ca_en50221_release(&state->ci);
6060 +static int dvbsky_streaming_ctrl(struct dvb_frontend *fe, int onoff)
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);
6068 +static int dvbsky_gpio_ctrl(struct dvb_usb_device *d, u8 gport, u8 value)
6071 + u8 obuf[64], ibuf[64];
6075 + ret = dvbsky_usb_generic_rw(d, obuf, 3, ibuf, 1);
6077 + dev_err(&d->udev->dev, "%s: %s() " \
6078 + "failed=%d\n", KBUILD_MODNAME, __func__, ret);
6083 +static int dvbsky_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
6086 + struct dvb_usb_device *d = i2c_get_adapdata(adap);
6088 + u8 ibuf[64], obuf[64];
6090 + if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
6094 + printk(KERN_ERR "dvbsky_usb: too many i2c messages[%d] than 2.", num);
6095 + ret = -EOPNOTSUPP;
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;
6105 + if (msg[0].flags & I2C_M_RD) {
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);
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]);*/
6117 + memcpy(msg[0].buf, &ibuf[1], msg[0].len);
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);
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]);*/
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;
6136 + /* write then read */
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);
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]);*/
6148 + memcpy(msg[1].buf, &ibuf[1], msg[1].len);
6151 + mutex_unlock(&d->i2c_mutex);
6152 + return (ret) ? ret : num;
6155 +static u32 dvbsky_i2c_func(struct i2c_adapter *adapter)
6157 + return I2C_FUNC_I2C;
6160 +static struct i2c_algorithm dvbsky_i2c_algo = {
6161 + .master_xfer = dvbsky_i2c_xfer,
6162 + .functionality = dvbsky_i2c_func,
6165 +#if IS_ENABLED(CONFIG_RC_CORE)
6166 +static int dvbsky_rc_query(struct dvb_usb_device *d)
6169 + u32 code = 0xffff, scancode;
6170 + u8 rc5_command, rc5_system;
6171 + u8 obuf[2], ibuf[2], toggle;
6174 + ret = dvbsky_usb_generic_rw(d, obuf, 1, ibuf, 2);
6176 + dev_err(&d->udev->dev, "%s: %s() " \
6177 + "failed=%d\n", KBUILD_MODNAME, __func__, ret);
6179 + code = (ibuf[0] << 8) | ibuf[1];
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);
6192 +static int dvbsky_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
6194 + rc->allowed_protos = RC_BIT_RC5;
6195 + rc->query = dvbsky_rc_query;
6196 + rc->interval = 300;
6200 + #define dvbsky_get_rc_config NULL
6203 +static int dvbsky_sync_ctrl(struct dvb_frontend *fe)
6205 + struct dvb_usb_device *d = fe_to_d(fe);
6206 + return dvbsky_stream_ctrl(d, 1);
6209 +static int dvbsky_usb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
6211 + struct dvb_usb_device *d = fe_to_d(fe);
6214 + if (voltage == SEC_VOLTAGE_OFF)
6218 + return dvbsky_gpio_ctrl(d, 0x80, value);
6221 +static int dvbsky_usb_ci_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
6223 + struct dvb_usb_device *d = fe_to_d(fe);
6226 + if (voltage == SEC_VOLTAGE_OFF)
6230 + return dvbsky_gpio_ctrl(d, 0x00, value);
6233 +static int dvbsky_t680c_attach(struct dvb_usb_adapter *adap)
6235 + struct dvbsky_state *state = adap_to_priv(adap);
6236 + struct dvb_usb_device *d = adap_to_d(adap);
6239 + /*dprintk("%s, build on %s %s()\n", __func__, __DATE__,__TIME__);*/
6241 +// adap->fe[0] = dvb_attach(sit2_attach,
6242 +// &dvbsky_usb_sit2_config,
6244 + if (!adap->fe[0]) {
6245 + printk(KERN_ERR "dvbsky_t680c_attach fail.");
6249 + state->has_ci = 1;
6254 +static int dvbsky_t330_attach(struct dvb_usb_adapter *adap)
6256 + struct dvbsky_state *state = adap_to_priv(adap);
6257 + struct dvb_usb_device *d = adap_to_d(adap);
6260 + /*dprintk("%s, build on %s %s()\n", __func__, __DATE__,__TIME__);*/
6262 +// adap->fe[0] = dvb_attach(sit2_attach,
6263 +// &dvbsky_t330_sit2_config,
6265 + if (!adap->fe[0]) {
6266 + printk(KERN_ERR "dvbsky_t330_attach fail.");
6270 + state->has_ci = 0;
6275 +static int dvbsky_read_mac_addr(struct dvb_usb_adapter *adap, u8 mac[6])
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[] = {
6288 + .flags = I2C_M_RD,
6295 + if (i2c_transfer(&d->i2c_adap, msg, 2) == 2)
6296 + memcpy(mac, ibuf, 6);
6298 + printk(KERN_INFO "dvbsky_usb MAC address=%pM\n", mac);
6303 +static struct dvbsky_m88ds3103_config dvbsky_usb_ds3103_config = {
6304 + .demod_address = 0x68,
6308 + .start_ctrl = dvbsky_sync_ctrl,
6309 + .set_voltage = dvbsky_usb_set_voltage,
6312 +static int dvbsky_s960_attach(struct dvb_usb_adapter *adap)
6314 + struct dvbsky_state *state = adap_to_priv(adap);
6315 + struct dvb_usb_device *d = adap_to_d(adap);
6318 + dprintk("%s()\n", __func__);
6320 + adap->fe[0] = dvb_attach(dvbsky_m88ds3103_attach,
6321 + &dvbsky_usb_ds3103_config,
6323 + if (!adap->fe[0]) {
6324 + printk(KERN_ERR "dvbsky_s960_attach fail.");
6328 + state->has_ci = 0;
6333 +static struct dvbsky_m88ds3103_config dvbsky_usb_ds3103_ci_config = {
6334 + .demod_address = 0x68,
6338 + .start_ctrl = dvbsky_sync_ctrl,
6339 + .set_voltage = dvbsky_usb_ci_set_voltage,
6341 +static int dvbsky_s960c_attach(struct dvb_usb_adapter *adap)
6343 + struct dvbsky_state *state = adap_to_priv(adap);
6344 + struct dvb_usb_device *d = adap_to_d(adap);
6347 + /*dprintk("%s, build on %s %s()\n", __func__, __DATE__,__TIME__);*/
6349 + adap->fe[0] = dvb_attach(dvbsky_m88ds3103_attach,
6350 + &dvbsky_usb_ds3103_ci_config,
6352 + if (!adap->fe[0]) {
6353 + printk(KERN_ERR "dvbsky_s960c_attach fail.");
6357 + state->has_ci = 1;
6362 +static int dvbsky_identify_state(struct dvb_usb_device *d, const char **name)
6365 + printk(KERN_INFO "%s, build on %s %s(),delay=%d\n",
6366 + __func__, __DATE__,__TIME__,d->props->generic_bulk_ctrl_delay);
6368 + dvbsky_gpio_ctrl(d, 0x04, 1);
6370 + dvbsky_gpio_ctrl(d, 0x83, 0);
6371 + dvbsky_gpio_ctrl(d, 0xc0, 1);
6373 + dvbsky_gpio_ctrl(d, 0x83, 1);
6374 + dvbsky_gpio_ctrl(d, 0xc0, 0);
6380 +static int dvbsky_init(struct dvb_usb_device *d)
6382 + struct dvbsky_state *state = d_to_priv(d);
6385 + /* use default interface */
6387 + ret = usb_set_interface(d->udev, 0, 0);
6391 + mutex_init(&state->stream_mutex);
6394 + if (state->has_ci) {
6395 + state->ci_attached = 0;
6396 + ret = dvbsky_ci_init(d);
6403 +static void dvbsky_exit(struct dvb_usb_device *d)
6405 + return dvbsky_ci_release(d);
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),
6415 + .generic_bulk_ctrl_endpoint = 0x01,
6416 + .generic_bulk_ctrl_endpoint_response = 0x81,
6417 + .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
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,
6428 + .num_adapters = 1,
6431 + .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
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),
6442 + .generic_bulk_ctrl_endpoint = 0x01,
6443 + .generic_bulk_ctrl_endpoint_response = 0x81,
6444 + .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
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,
6455 + .num_adapters = 1,
6458 + .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
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),
6469 + .generic_bulk_ctrl_endpoint = 0x01,
6470 + .generic_bulk_ctrl_endpoint_response = 0x81,
6471 + .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
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,
6482 + .num_adapters = 1,
6485 + .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
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),
6496 + .generic_bulk_ctrl_endpoint = 0x01,
6497 + .generic_bulk_ctrl_endpoint_response = 0x81,
6498 + .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
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,
6509 + .num_adapters = 1,
6512 + .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
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) },
6528 +MODULE_DEVICE_TABLE(usb, dvbsky_id_table);
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,
6542 +module_usb_driver(dvbsky_usb_driver);
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"