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