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