1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Linux-DVB Driver for DiBcom's DiB8000 chip (ISDB-T).
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2009 DiBcom (http://www.dibcom.fr/)
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/kernel.h>
11*4882a593Smuzhiyun #include <linux/slab.h>
12*4882a593Smuzhiyun #include <linux/i2c.h>
13*4882a593Smuzhiyun #include <linux/mutex.h>
14*4882a593Smuzhiyun #include <asm/div64.h>
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #include <media/dvb_math.h>
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #include <media/dvb_frontend.h>
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun #include "dib8000.h"
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #define LAYER_ALL -1
23*4882a593Smuzhiyun #define LAYER_A 1
24*4882a593Smuzhiyun #define LAYER_B 2
25*4882a593Smuzhiyun #define LAYER_C 3
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #define MAX_NUMBER_OF_FRONTENDS 6
28*4882a593Smuzhiyun /* #define DIB8000_AGC_FREEZE */
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun static int debug;
31*4882a593Smuzhiyun module_param(debug, int, 0644);
32*4882a593Smuzhiyun MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #define dprintk(fmt, arg...) do { \
35*4882a593Smuzhiyun if (debug) \
36*4882a593Smuzhiyun printk(KERN_DEBUG pr_fmt("%s: " fmt), \
37*4882a593Smuzhiyun __func__, ##arg); \
38*4882a593Smuzhiyun } while (0)
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun struct i2c_device {
41*4882a593Smuzhiyun struct i2c_adapter *adap;
42*4882a593Smuzhiyun u8 addr;
43*4882a593Smuzhiyun u8 *i2c_write_buffer;
44*4882a593Smuzhiyun u8 *i2c_read_buffer;
45*4882a593Smuzhiyun struct mutex *i2c_buffer_lock;
46*4882a593Smuzhiyun };
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun enum param_loop_step {
49*4882a593Smuzhiyun LOOP_TUNE_1,
50*4882a593Smuzhiyun LOOP_TUNE_2
51*4882a593Smuzhiyun };
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun enum dib8000_autosearch_step {
54*4882a593Smuzhiyun AS_START = 0,
55*4882a593Smuzhiyun AS_SEARCHING_FFT,
56*4882a593Smuzhiyun AS_SEARCHING_GUARD,
57*4882a593Smuzhiyun AS_DONE = 100,
58*4882a593Smuzhiyun };
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun enum timeout_mode {
61*4882a593Smuzhiyun SYMBOL_DEPENDENT_OFF = 0,
62*4882a593Smuzhiyun SYMBOL_DEPENDENT_ON,
63*4882a593Smuzhiyun };
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun struct dib8000_state {
66*4882a593Smuzhiyun struct dib8000_config cfg;
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun struct i2c_device i2c;
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun struct dibx000_i2c_master i2c_master;
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun u16 wbd_ref;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun u8 current_band;
75*4882a593Smuzhiyun u32 current_bandwidth;
76*4882a593Smuzhiyun struct dibx000_agc_config *current_agc;
77*4882a593Smuzhiyun u32 timf;
78*4882a593Smuzhiyun u32 timf_default;
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun u8 div_force_off:1;
81*4882a593Smuzhiyun u8 div_state:1;
82*4882a593Smuzhiyun u16 div_sync_wait;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun u8 agc_state;
85*4882a593Smuzhiyun u8 differential_constellation;
86*4882a593Smuzhiyun u8 diversity_onoff;
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun s16 ber_monitored_layer;
89*4882a593Smuzhiyun u16 gpio_dir;
90*4882a593Smuzhiyun u16 gpio_val;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun u16 revision;
93*4882a593Smuzhiyun u8 isdbt_cfg_loaded;
94*4882a593Smuzhiyun enum frontend_tune_state tune_state;
95*4882a593Smuzhiyun s32 status;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS];
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun /* for the I2C transfer */
100*4882a593Smuzhiyun struct i2c_msg msg[2];
101*4882a593Smuzhiyun u8 i2c_write_buffer[4];
102*4882a593Smuzhiyun u8 i2c_read_buffer[2];
103*4882a593Smuzhiyun struct mutex i2c_buffer_lock;
104*4882a593Smuzhiyun u8 input_mode_mpeg;
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun u16 tuner_enable;
107*4882a593Smuzhiyun struct i2c_adapter dib8096p_tuner_adap;
108*4882a593Smuzhiyun u16 current_demod_bw;
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun u16 seg_mask;
111*4882a593Smuzhiyun u16 seg_diff_mask;
112*4882a593Smuzhiyun u16 mode;
113*4882a593Smuzhiyun u8 layer_b_nb_seg;
114*4882a593Smuzhiyun u8 layer_c_nb_seg;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun u8 channel_parameters_set;
117*4882a593Smuzhiyun u16 autosearch_state;
118*4882a593Smuzhiyun u16 found_nfft;
119*4882a593Smuzhiyun u16 found_guard;
120*4882a593Smuzhiyun u8 subchannel;
121*4882a593Smuzhiyun u8 symbol_duration;
122*4882a593Smuzhiyun unsigned long timeout;
123*4882a593Smuzhiyun u8 longest_intlv_layer;
124*4882a593Smuzhiyun u16 output_mode;
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun /* for DVBv5 stats */
127*4882a593Smuzhiyun s64 init_ucb;
128*4882a593Smuzhiyun unsigned long per_jiffies_stats;
129*4882a593Smuzhiyun unsigned long ber_jiffies_stats;
130*4882a593Smuzhiyun unsigned long ber_jiffies_stats_layer[3];
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun #ifdef DIB8000_AGC_FREEZE
133*4882a593Smuzhiyun u16 agc1_max;
134*4882a593Smuzhiyun u16 agc1_min;
135*4882a593Smuzhiyun u16 agc2_max;
136*4882a593Smuzhiyun u16 agc2_min;
137*4882a593Smuzhiyun #endif
138*4882a593Smuzhiyun };
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun enum dib8000_power_mode {
141*4882a593Smuzhiyun DIB8000_POWER_ALL = 0,
142*4882a593Smuzhiyun DIB8000_POWER_INTERFACE_ONLY,
143*4882a593Smuzhiyun };
144*4882a593Smuzhiyun
dib8000_i2c_read16(struct i2c_device * i2c,u16 reg)145*4882a593Smuzhiyun static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun u16 ret;
148*4882a593Smuzhiyun struct i2c_msg msg[2] = {
149*4882a593Smuzhiyun {.addr = i2c->addr >> 1, .flags = 0, .len = 2},
150*4882a593Smuzhiyun {.addr = i2c->addr >> 1, .flags = I2C_M_RD, .len = 2},
151*4882a593Smuzhiyun };
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) {
154*4882a593Smuzhiyun dprintk("could not acquire lock\n");
155*4882a593Smuzhiyun return 0;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun msg[0].buf = i2c->i2c_write_buffer;
159*4882a593Smuzhiyun msg[0].buf[0] = reg >> 8;
160*4882a593Smuzhiyun msg[0].buf[1] = reg & 0xff;
161*4882a593Smuzhiyun msg[1].buf = i2c->i2c_read_buffer;
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun if (i2c_transfer(i2c->adap, msg, 2) != 2)
164*4882a593Smuzhiyun dprintk("i2c read error on %d\n", reg);
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun ret = (msg[1].buf[0] << 8) | msg[1].buf[1];
167*4882a593Smuzhiyun mutex_unlock(i2c->i2c_buffer_lock);
168*4882a593Smuzhiyun return ret;
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun
__dib8000_read_word(struct dib8000_state * state,u16 reg)171*4882a593Smuzhiyun static u16 __dib8000_read_word(struct dib8000_state *state, u16 reg)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun u16 ret;
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun state->i2c_write_buffer[0] = reg >> 8;
176*4882a593Smuzhiyun state->i2c_write_buffer[1] = reg & 0xff;
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
179*4882a593Smuzhiyun state->msg[0].addr = state->i2c.addr >> 1;
180*4882a593Smuzhiyun state->msg[0].flags = 0;
181*4882a593Smuzhiyun state->msg[0].buf = state->i2c_write_buffer;
182*4882a593Smuzhiyun state->msg[0].len = 2;
183*4882a593Smuzhiyun state->msg[1].addr = state->i2c.addr >> 1;
184*4882a593Smuzhiyun state->msg[1].flags = I2C_M_RD;
185*4882a593Smuzhiyun state->msg[1].buf = state->i2c_read_buffer;
186*4882a593Smuzhiyun state->msg[1].len = 2;
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2)
189*4882a593Smuzhiyun dprintk("i2c read error on %d\n", reg);
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun return ret;
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun
dib8000_read_word(struct dib8000_state * state,u16 reg)196*4882a593Smuzhiyun static u16 dib8000_read_word(struct dib8000_state *state, u16 reg)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun u16 ret;
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
201*4882a593Smuzhiyun dprintk("could not acquire lock\n");
202*4882a593Smuzhiyun return 0;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun ret = __dib8000_read_word(state, reg);
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun mutex_unlock(&state->i2c_buffer_lock);
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun return ret;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun
dib8000_read32(struct dib8000_state * state,u16 reg)212*4882a593Smuzhiyun static u32 dib8000_read32(struct dib8000_state *state, u16 reg)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun u16 rw[2];
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
217*4882a593Smuzhiyun dprintk("could not acquire lock\n");
218*4882a593Smuzhiyun return 0;
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun rw[0] = __dib8000_read_word(state, reg + 0);
222*4882a593Smuzhiyun rw[1] = __dib8000_read_word(state, reg + 1);
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun mutex_unlock(&state->i2c_buffer_lock);
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun return ((rw[0] << 16) | (rw[1]));
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
dib8000_i2c_write16(struct i2c_device * i2c,u16 reg,u16 val)229*4882a593Smuzhiyun static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, .len = 4};
232*4882a593Smuzhiyun int ret = 0;
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) {
235*4882a593Smuzhiyun dprintk("could not acquire lock\n");
236*4882a593Smuzhiyun return -EINVAL;
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun msg.buf = i2c->i2c_write_buffer;
240*4882a593Smuzhiyun msg.buf[0] = (reg >> 8) & 0xff;
241*4882a593Smuzhiyun msg.buf[1] = reg & 0xff;
242*4882a593Smuzhiyun msg.buf[2] = (val >> 8) & 0xff;
243*4882a593Smuzhiyun msg.buf[3] = val & 0xff;
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
246*4882a593Smuzhiyun mutex_unlock(i2c->i2c_buffer_lock);
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun return ret;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun
dib8000_write_word(struct dib8000_state * state,u16 reg,u16 val)251*4882a593Smuzhiyun static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun int ret;
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
256*4882a593Smuzhiyun dprintk("could not acquire lock\n");
257*4882a593Smuzhiyun return -EINVAL;
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
261*4882a593Smuzhiyun state->i2c_write_buffer[1] = reg & 0xff;
262*4882a593Smuzhiyun state->i2c_write_buffer[2] = (val >> 8) & 0xff;
263*4882a593Smuzhiyun state->i2c_write_buffer[3] = val & 0xff;
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun memset(&state->msg[0], 0, sizeof(struct i2c_msg));
266*4882a593Smuzhiyun state->msg[0].addr = state->i2c.addr >> 1;
267*4882a593Smuzhiyun state->msg[0].flags = 0;
268*4882a593Smuzhiyun state->msg[0].buf = state->i2c_write_buffer;
269*4882a593Smuzhiyun state->msg[0].len = 4;
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun ret = (i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ?
272*4882a593Smuzhiyun -EREMOTEIO : 0);
273*4882a593Smuzhiyun mutex_unlock(&state->i2c_buffer_lock);
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun return ret;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun static const s16 coeff_2k_sb_1seg_dqpsk[8] = {
279*4882a593Smuzhiyun (769 << 5) | 0x0a, (745 << 5) | 0x03, (595 << 5) | 0x0d, (769 << 5) | 0x0a, (920 << 5) | 0x09, (784 << 5) | 0x02, (519 << 5) | 0x0c,
280*4882a593Smuzhiyun (920 << 5) | 0x09
281*4882a593Smuzhiyun };
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun static const s16 coeff_2k_sb_1seg[8] = {
284*4882a593Smuzhiyun (692 << 5) | 0x0b, (683 << 5) | 0x01, (519 << 5) | 0x09, (692 << 5) | 0x0b, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f
285*4882a593Smuzhiyun };
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun static const s16 coeff_2k_sb_3seg_0dqpsk_1dqpsk[8] = {
288*4882a593Smuzhiyun (832 << 5) | 0x10, (912 << 5) | 0x05, (900 << 5) | 0x12, (832 << 5) | 0x10, (-931 << 5) | 0x0f, (912 << 5) | 0x04, (807 << 5) | 0x11,
289*4882a593Smuzhiyun (-931 << 5) | 0x0f
290*4882a593Smuzhiyun };
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun static const s16 coeff_2k_sb_3seg_0dqpsk[8] = {
293*4882a593Smuzhiyun (622 << 5) | 0x0c, (941 << 5) | 0x04, (796 << 5) | 0x10, (622 << 5) | 0x0c, (982 << 5) | 0x0c, (519 << 5) | 0x02, (572 << 5) | 0x0e,
294*4882a593Smuzhiyun (982 << 5) | 0x0c
295*4882a593Smuzhiyun };
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun static const s16 coeff_2k_sb_3seg_1dqpsk[8] = {
298*4882a593Smuzhiyun (699 << 5) | 0x14, (607 << 5) | 0x04, (944 << 5) | 0x13, (699 << 5) | 0x14, (-720 << 5) | 0x0d, (640 << 5) | 0x03, (866 << 5) | 0x12,
299*4882a593Smuzhiyun (-720 << 5) | 0x0d
300*4882a593Smuzhiyun };
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun static const s16 coeff_2k_sb_3seg[8] = {
303*4882a593Smuzhiyun (664 << 5) | 0x0c, (925 << 5) | 0x03, (937 << 5) | 0x10, (664 << 5) | 0x0c, (-610 << 5) | 0x0a, (697 << 5) | 0x01, (836 << 5) | 0x0e,
304*4882a593Smuzhiyun (-610 << 5) | 0x0a
305*4882a593Smuzhiyun };
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun static const s16 coeff_4k_sb_1seg_dqpsk[8] = {
308*4882a593Smuzhiyun (-955 << 5) | 0x0e, (687 << 5) | 0x04, (818 << 5) | 0x10, (-955 << 5) | 0x0e, (-922 << 5) | 0x0d, (750 << 5) | 0x03, (665 << 5) | 0x0f,
309*4882a593Smuzhiyun (-922 << 5) | 0x0d
310*4882a593Smuzhiyun };
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun static const s16 coeff_4k_sb_1seg[8] = {
313*4882a593Smuzhiyun (638 << 5) | 0x0d, (683 << 5) | 0x02, (638 << 5) | 0x0d, (638 << 5) | 0x0d, (-655 << 5) | 0x0a, (517 << 5) | 0x00, (698 << 5) | 0x0d,
314*4882a593Smuzhiyun (-655 << 5) | 0x0a
315*4882a593Smuzhiyun };
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun static const s16 coeff_4k_sb_3seg_0dqpsk_1dqpsk[8] = {
318*4882a593Smuzhiyun (-707 << 5) | 0x14, (910 << 5) | 0x06, (889 << 5) | 0x16, (-707 << 5) | 0x14, (-958 << 5) | 0x13, (993 << 5) | 0x05, (523 << 5) | 0x14,
319*4882a593Smuzhiyun (-958 << 5) | 0x13
320*4882a593Smuzhiyun };
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun static const s16 coeff_4k_sb_3seg_0dqpsk[8] = {
323*4882a593Smuzhiyun (-723 << 5) | 0x13, (910 << 5) | 0x05, (777 << 5) | 0x14, (-723 << 5) | 0x13, (-568 << 5) | 0x0f, (547 << 5) | 0x03, (696 << 5) | 0x12,
324*4882a593Smuzhiyun (-568 << 5) | 0x0f
325*4882a593Smuzhiyun };
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun static const s16 coeff_4k_sb_3seg_1dqpsk[8] = {
328*4882a593Smuzhiyun (-940 << 5) | 0x15, (607 << 5) | 0x05, (915 << 5) | 0x16, (-940 << 5) | 0x15, (-848 << 5) | 0x13, (683 << 5) | 0x04, (543 << 5) | 0x14,
329*4882a593Smuzhiyun (-848 << 5) | 0x13
330*4882a593Smuzhiyun };
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun static const s16 coeff_4k_sb_3seg[8] = {
333*4882a593Smuzhiyun (612 << 5) | 0x12, (910 << 5) | 0x04, (864 << 5) | 0x14, (612 << 5) | 0x12, (-869 << 5) | 0x13, (683 << 5) | 0x02, (869 << 5) | 0x12,
334*4882a593Smuzhiyun (-869 << 5) | 0x13
335*4882a593Smuzhiyun };
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun static const s16 coeff_8k_sb_1seg_dqpsk[8] = {
338*4882a593Smuzhiyun (-835 << 5) | 0x12, (684 << 5) | 0x05, (735 << 5) | 0x14, (-835 << 5) | 0x12, (-598 << 5) | 0x10, (781 << 5) | 0x04, (739 << 5) | 0x13,
339*4882a593Smuzhiyun (-598 << 5) | 0x10
340*4882a593Smuzhiyun };
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun static const s16 coeff_8k_sb_1seg[8] = {
343*4882a593Smuzhiyun (673 << 5) | 0x0f, (683 << 5) | 0x03, (808 << 5) | 0x12, (673 << 5) | 0x0f, (585 << 5) | 0x0f, (512 << 5) | 0x01, (780 << 5) | 0x0f,
344*4882a593Smuzhiyun (585 << 5) | 0x0f
345*4882a593Smuzhiyun };
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun static const s16 coeff_8k_sb_3seg_0dqpsk_1dqpsk[8] = {
348*4882a593Smuzhiyun (863 << 5) | 0x17, (930 << 5) | 0x07, (878 << 5) | 0x19, (863 << 5) | 0x17, (0 << 5) | 0x14, (521 << 5) | 0x05, (980 << 5) | 0x18,
349*4882a593Smuzhiyun (0 << 5) | 0x14
350*4882a593Smuzhiyun };
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun static const s16 coeff_8k_sb_3seg_0dqpsk[8] = {
353*4882a593Smuzhiyun (-924 << 5) | 0x17, (910 << 5) | 0x06, (774 << 5) | 0x17, (-924 << 5) | 0x17, (-877 << 5) | 0x15, (565 << 5) | 0x04, (553 << 5) | 0x15,
354*4882a593Smuzhiyun (-877 << 5) | 0x15
355*4882a593Smuzhiyun };
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun static const s16 coeff_8k_sb_3seg_1dqpsk[8] = {
358*4882a593Smuzhiyun (-921 << 5) | 0x19, (607 << 5) | 0x06, (881 << 5) | 0x19, (-921 << 5) | 0x19, (-921 << 5) | 0x14, (713 << 5) | 0x05, (1018 << 5) | 0x18,
359*4882a593Smuzhiyun (-921 << 5) | 0x14
360*4882a593Smuzhiyun };
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun static const s16 coeff_8k_sb_3seg[8] = {
363*4882a593Smuzhiyun (514 << 5) | 0x14, (910 << 5) | 0x05, (861 << 5) | 0x17, (514 << 5) | 0x14, (690 << 5) | 0x14, (683 << 5) | 0x03, (662 << 5) | 0x15,
364*4882a593Smuzhiyun (690 << 5) | 0x14
365*4882a593Smuzhiyun };
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun static const s16 ana_fe_coeff_3seg[24] = {
368*4882a593Smuzhiyun 81, 80, 78, 74, 68, 61, 54, 45, 37, 28, 19, 11, 4, 1022, 1017, 1013, 1010, 1008, 1008, 1008, 1008, 1010, 1014, 1017
369*4882a593Smuzhiyun };
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun static const s16 ana_fe_coeff_1seg[24] = {
372*4882a593Smuzhiyun 249, 226, 164, 82, 5, 981, 970, 988, 1018, 20, 31, 26, 8, 1012, 1000, 1018, 1012, 8, 15, 14, 9, 3, 1017, 1003
373*4882a593Smuzhiyun };
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun static const s16 ana_fe_coeff_13seg[24] = {
376*4882a593Smuzhiyun 396, 305, 105, -51, -77, -12, 41, 31, -11, -30, -11, 14, 15, -2, -13, -7, 5, 8, 1, -6, -7, -3, 0, 1
377*4882a593Smuzhiyun };
378*4882a593Smuzhiyun
fft_to_mode(struct dib8000_state * state)379*4882a593Smuzhiyun static u16 fft_to_mode(struct dib8000_state *state)
380*4882a593Smuzhiyun {
381*4882a593Smuzhiyun u16 mode;
382*4882a593Smuzhiyun switch (state->fe[0]->dtv_property_cache.transmission_mode) {
383*4882a593Smuzhiyun case TRANSMISSION_MODE_2K:
384*4882a593Smuzhiyun mode = 1;
385*4882a593Smuzhiyun break;
386*4882a593Smuzhiyun case TRANSMISSION_MODE_4K:
387*4882a593Smuzhiyun mode = 2;
388*4882a593Smuzhiyun break;
389*4882a593Smuzhiyun default:
390*4882a593Smuzhiyun case TRANSMISSION_MODE_AUTO:
391*4882a593Smuzhiyun case TRANSMISSION_MODE_8K:
392*4882a593Smuzhiyun mode = 3;
393*4882a593Smuzhiyun break;
394*4882a593Smuzhiyun }
395*4882a593Smuzhiyun return mode;
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun
dib8000_set_acquisition_mode(struct dib8000_state * state)398*4882a593Smuzhiyun static void dib8000_set_acquisition_mode(struct dib8000_state *state)
399*4882a593Smuzhiyun {
400*4882a593Smuzhiyun u16 nud = dib8000_read_word(state, 298);
401*4882a593Smuzhiyun nud |= (1 << 3) | (1 << 0);
402*4882a593Smuzhiyun dprintk("acquisition mode activated\n");
403*4882a593Smuzhiyun dib8000_write_word(state, 298, nud);
404*4882a593Smuzhiyun }
dib8000_set_output_mode(struct dvb_frontend * fe,int mode)405*4882a593Smuzhiyun static int dib8000_set_output_mode(struct dvb_frontend *fe, int mode)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
408*4882a593Smuzhiyun u16 outreg, fifo_threshold, smo_mode, sram = 0x0205; /* by default SDRAM deintlv is enabled */
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun state->output_mode = mode;
411*4882a593Smuzhiyun outreg = 0;
412*4882a593Smuzhiyun fifo_threshold = 1792;
413*4882a593Smuzhiyun smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1);
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun dprintk("-I- Setting output mode for demod %p to %d\n",
416*4882a593Smuzhiyun &state->fe[0], mode);
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun switch (mode) {
419*4882a593Smuzhiyun case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock
420*4882a593Smuzhiyun outreg = (1 << 10); /* 0x0400 */
421*4882a593Smuzhiyun break;
422*4882a593Smuzhiyun case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock
423*4882a593Smuzhiyun outreg = (1 << 10) | (1 << 6); /* 0x0440 */
424*4882a593Smuzhiyun break;
425*4882a593Smuzhiyun case OUTMODE_MPEG2_SERIAL: // STBs with serial input
426*4882a593Smuzhiyun outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */
427*4882a593Smuzhiyun break;
428*4882a593Smuzhiyun case OUTMODE_DIVERSITY:
429*4882a593Smuzhiyun if (state->cfg.hostbus_diversity) {
430*4882a593Smuzhiyun outreg = (1 << 10) | (4 << 6); /* 0x0500 */
431*4882a593Smuzhiyun sram &= 0xfdff;
432*4882a593Smuzhiyun } else
433*4882a593Smuzhiyun sram |= 0x0c00;
434*4882a593Smuzhiyun break;
435*4882a593Smuzhiyun case OUTMODE_MPEG2_FIFO: // e.g. USB feeding
436*4882a593Smuzhiyun smo_mode |= (3 << 1);
437*4882a593Smuzhiyun fifo_threshold = 512;
438*4882a593Smuzhiyun outreg = (1 << 10) | (5 << 6);
439*4882a593Smuzhiyun break;
440*4882a593Smuzhiyun case OUTMODE_HIGH_Z: // disable
441*4882a593Smuzhiyun outreg = 0;
442*4882a593Smuzhiyun break;
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun case OUTMODE_ANALOG_ADC:
445*4882a593Smuzhiyun outreg = (1 << 10) | (3 << 6);
446*4882a593Smuzhiyun dib8000_set_acquisition_mode(state);
447*4882a593Smuzhiyun break;
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun default:
450*4882a593Smuzhiyun dprintk("Unhandled output_mode passed to be set for demod %p\n",
451*4882a593Smuzhiyun &state->fe[0]);
452*4882a593Smuzhiyun return -EINVAL;
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun if (state->cfg.output_mpeg2_in_188_bytes)
456*4882a593Smuzhiyun smo_mode |= (1 << 5);
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun dib8000_write_word(state, 299, smo_mode);
459*4882a593Smuzhiyun dib8000_write_word(state, 300, fifo_threshold); /* synchronous fread */
460*4882a593Smuzhiyun dib8000_write_word(state, 1286, outreg);
461*4882a593Smuzhiyun dib8000_write_word(state, 1291, sram);
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun return 0;
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun
dib8000_set_diversity_in(struct dvb_frontend * fe,int onoff)466*4882a593Smuzhiyun static int dib8000_set_diversity_in(struct dvb_frontend *fe, int onoff)
467*4882a593Smuzhiyun {
468*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
469*4882a593Smuzhiyun u16 tmp, sync_wait = dib8000_read_word(state, 273) & 0xfff0;
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun dprintk("set diversity input to %i\n", onoff);
472*4882a593Smuzhiyun if (!state->differential_constellation) {
473*4882a593Smuzhiyun dib8000_write_word(state, 272, 1 << 9); //dvsy_off_lmod4 = 1
474*4882a593Smuzhiyun dib8000_write_word(state, 273, sync_wait | (1 << 2) | 2); // sync_enable = 1; comb_mode = 2
475*4882a593Smuzhiyun } else {
476*4882a593Smuzhiyun dib8000_write_word(state, 272, 0); //dvsy_off_lmod4 = 0
477*4882a593Smuzhiyun dib8000_write_word(state, 273, sync_wait); // sync_enable = 0; comb_mode = 0
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun state->diversity_onoff = onoff;
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun switch (onoff) {
482*4882a593Smuzhiyun case 0: /* only use the internal way - not the diversity input */
483*4882a593Smuzhiyun dib8000_write_word(state, 270, 1);
484*4882a593Smuzhiyun dib8000_write_word(state, 271, 0);
485*4882a593Smuzhiyun break;
486*4882a593Smuzhiyun case 1: /* both ways */
487*4882a593Smuzhiyun dib8000_write_word(state, 270, 6);
488*4882a593Smuzhiyun dib8000_write_word(state, 271, 6);
489*4882a593Smuzhiyun break;
490*4882a593Smuzhiyun case 2: /* only the diversity input */
491*4882a593Smuzhiyun dib8000_write_word(state, 270, 0);
492*4882a593Smuzhiyun dib8000_write_word(state, 271, 1);
493*4882a593Smuzhiyun break;
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun if (state->revision == 0x8002) {
497*4882a593Smuzhiyun tmp = dib8000_read_word(state, 903);
498*4882a593Smuzhiyun dib8000_write_word(state, 903, tmp & ~(1 << 3));
499*4882a593Smuzhiyun msleep(30);
500*4882a593Smuzhiyun dib8000_write_word(state, 903, tmp | (1 << 3));
501*4882a593Smuzhiyun }
502*4882a593Smuzhiyun return 0;
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun
dib8000_set_power_mode(struct dib8000_state * state,enum dib8000_power_mode mode)505*4882a593Smuzhiyun static void dib8000_set_power_mode(struct dib8000_state *state, enum dib8000_power_mode mode)
506*4882a593Smuzhiyun {
507*4882a593Smuzhiyun /* by default everything is going to be powered off */
508*4882a593Smuzhiyun u16 reg_774 = 0x3fff, reg_775 = 0xffff, reg_776 = 0xffff,
509*4882a593Smuzhiyun reg_900 = (dib8000_read_word(state, 900) & 0xfffc) | 0x3,
510*4882a593Smuzhiyun reg_1280;
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun if (state->revision != 0x8090)
513*4882a593Smuzhiyun reg_1280 = (dib8000_read_word(state, 1280) & 0x00ff) | 0xff00;
514*4882a593Smuzhiyun else
515*4882a593Smuzhiyun reg_1280 = (dib8000_read_word(state, 1280) & 0x707f) | 0x8f80;
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun /* now, depending on the requested mode, we power on */
518*4882a593Smuzhiyun switch (mode) {
519*4882a593Smuzhiyun /* power up everything in the demod */
520*4882a593Smuzhiyun case DIB8000_POWER_ALL:
521*4882a593Smuzhiyun reg_774 = 0x0000;
522*4882a593Smuzhiyun reg_775 = 0x0000;
523*4882a593Smuzhiyun reg_776 = 0x0000;
524*4882a593Smuzhiyun reg_900 &= 0xfffc;
525*4882a593Smuzhiyun if (state->revision != 0x8090)
526*4882a593Smuzhiyun reg_1280 &= 0x00ff;
527*4882a593Smuzhiyun else
528*4882a593Smuzhiyun reg_1280 &= 0x707f;
529*4882a593Smuzhiyun break;
530*4882a593Smuzhiyun case DIB8000_POWER_INTERFACE_ONLY:
531*4882a593Smuzhiyun if (state->revision != 0x8090)
532*4882a593Smuzhiyun reg_1280 &= 0x00ff;
533*4882a593Smuzhiyun else
534*4882a593Smuzhiyun reg_1280 &= 0xfa7b;
535*4882a593Smuzhiyun break;
536*4882a593Smuzhiyun }
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun dprintk("powermode : 774 : %x ; 775 : %x; 776 : %x ; 900 : %x; 1280 : %x\n", reg_774, reg_775, reg_776, reg_900, reg_1280);
539*4882a593Smuzhiyun dib8000_write_word(state, 774, reg_774);
540*4882a593Smuzhiyun dib8000_write_word(state, 775, reg_775);
541*4882a593Smuzhiyun dib8000_write_word(state, 776, reg_776);
542*4882a593Smuzhiyun dib8000_write_word(state, 900, reg_900);
543*4882a593Smuzhiyun dib8000_write_word(state, 1280, reg_1280);
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun
dib8000_set_adc_state(struct dib8000_state * state,enum dibx000_adc_states no)546*4882a593Smuzhiyun static int dib8000_set_adc_state(struct dib8000_state *state, enum dibx000_adc_states no)
547*4882a593Smuzhiyun {
548*4882a593Smuzhiyun int ret = 0;
549*4882a593Smuzhiyun u16 reg, reg_907 = dib8000_read_word(state, 907);
550*4882a593Smuzhiyun u16 reg_908 = dib8000_read_word(state, 908);
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun switch (no) {
553*4882a593Smuzhiyun case DIBX000_SLOW_ADC_ON:
554*4882a593Smuzhiyun if (state->revision != 0x8090) {
555*4882a593Smuzhiyun reg_908 |= (1 << 1) | (1 << 0);
556*4882a593Smuzhiyun ret |= dib8000_write_word(state, 908, reg_908);
557*4882a593Smuzhiyun reg_908 &= ~(1 << 1);
558*4882a593Smuzhiyun } else {
559*4882a593Smuzhiyun reg = dib8000_read_word(state, 1925);
560*4882a593Smuzhiyun /* en_slowAdc = 1 & reset_sladc = 1 */
561*4882a593Smuzhiyun dib8000_write_word(state, 1925, reg |
562*4882a593Smuzhiyun (1<<4) | (1<<2));
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun /* read access to make it works... strange ... */
565*4882a593Smuzhiyun reg = dib8000_read_word(state, 1925);
566*4882a593Smuzhiyun msleep(20);
567*4882a593Smuzhiyun /* en_slowAdc = 1 & reset_sladc = 0 */
568*4882a593Smuzhiyun dib8000_write_word(state, 1925, reg & ~(1<<4));
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun reg = dib8000_read_word(state, 921) & ~((0x3 << 14)
571*4882a593Smuzhiyun | (0x3 << 12));
572*4882a593Smuzhiyun /* ref = Vin1 => Vbg ; sel = Vin0 or Vin3 ;
573*4882a593Smuzhiyun (Vin2 = Vcm) */
574*4882a593Smuzhiyun dib8000_write_word(state, 921, reg | (1 << 14)
575*4882a593Smuzhiyun | (3 << 12));
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun break;
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun case DIBX000_SLOW_ADC_OFF:
580*4882a593Smuzhiyun if (state->revision == 0x8090) {
581*4882a593Smuzhiyun reg = dib8000_read_word(state, 1925);
582*4882a593Smuzhiyun /* reset_sladc = 1 en_slowAdc = 0 */
583*4882a593Smuzhiyun dib8000_write_word(state, 1925,
584*4882a593Smuzhiyun (reg & ~(1<<2)) | (1<<4));
585*4882a593Smuzhiyun }
586*4882a593Smuzhiyun reg_908 |= (1 << 1) | (1 << 0);
587*4882a593Smuzhiyun break;
588*4882a593Smuzhiyun
589*4882a593Smuzhiyun case DIBX000_ADC_ON:
590*4882a593Smuzhiyun reg_907 &= 0x0fff;
591*4882a593Smuzhiyun reg_908 &= 0x0003;
592*4882a593Smuzhiyun break;
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun case DIBX000_ADC_OFF: // leave the VBG voltage on
595*4882a593Smuzhiyun reg_907 = (1 << 13) | (1 << 12);
596*4882a593Smuzhiyun reg_908 = (1 << 6) | (1 << 5) | (1 << 4) | (1 << 3) | (1 << 1);
597*4882a593Smuzhiyun break;
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun case DIBX000_VBG_ENABLE:
600*4882a593Smuzhiyun reg_907 &= ~(1 << 15);
601*4882a593Smuzhiyun break;
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun case DIBX000_VBG_DISABLE:
604*4882a593Smuzhiyun reg_907 |= (1 << 15);
605*4882a593Smuzhiyun break;
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun default:
608*4882a593Smuzhiyun break;
609*4882a593Smuzhiyun }
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun ret |= dib8000_write_word(state, 907, reg_907);
612*4882a593Smuzhiyun ret |= dib8000_write_word(state, 908, reg_908);
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun return ret;
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun
dib8000_set_bandwidth(struct dvb_frontend * fe,u32 bw)617*4882a593Smuzhiyun static int dib8000_set_bandwidth(struct dvb_frontend *fe, u32 bw)
618*4882a593Smuzhiyun {
619*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
620*4882a593Smuzhiyun u32 timf;
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun if (bw == 0)
623*4882a593Smuzhiyun bw = 6000;
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun if (state->timf == 0) {
626*4882a593Smuzhiyun dprintk("using default timf\n");
627*4882a593Smuzhiyun timf = state->timf_default;
628*4882a593Smuzhiyun } else {
629*4882a593Smuzhiyun dprintk("using updated timf\n");
630*4882a593Smuzhiyun timf = state->timf;
631*4882a593Smuzhiyun }
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun dib8000_write_word(state, 29, (u16) ((timf >> 16) & 0xffff));
634*4882a593Smuzhiyun dib8000_write_word(state, 30, (u16) ((timf) & 0xffff));
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun return 0;
637*4882a593Smuzhiyun }
638*4882a593Smuzhiyun
dib8000_sad_calib(struct dib8000_state * state)639*4882a593Smuzhiyun static int dib8000_sad_calib(struct dib8000_state *state)
640*4882a593Smuzhiyun {
641*4882a593Smuzhiyun u8 sad_sel = 3;
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun if (state->revision == 0x8090) {
644*4882a593Smuzhiyun dib8000_write_word(state, 922, (sad_sel << 2));
645*4882a593Smuzhiyun dib8000_write_word(state, 923, 2048);
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun dib8000_write_word(state, 922, (sad_sel << 2) | 0x1);
648*4882a593Smuzhiyun dib8000_write_word(state, 922, (sad_sel << 2));
649*4882a593Smuzhiyun } else {
650*4882a593Smuzhiyun /* internal */
651*4882a593Smuzhiyun dib8000_write_word(state, 923, (0 << 1) | (0 << 0));
652*4882a593Smuzhiyun dib8000_write_word(state, 924, 776);
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun /* do the calibration */
655*4882a593Smuzhiyun dib8000_write_word(state, 923, (1 << 0));
656*4882a593Smuzhiyun dib8000_write_word(state, 923, (0 << 0));
657*4882a593Smuzhiyun }
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun msleep(1);
660*4882a593Smuzhiyun return 0;
661*4882a593Smuzhiyun }
662*4882a593Smuzhiyun
dib8000_set_wbd_ref(struct dvb_frontend * fe,u16 value)663*4882a593Smuzhiyun static int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
664*4882a593Smuzhiyun {
665*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
666*4882a593Smuzhiyun if (value > 4095)
667*4882a593Smuzhiyun value = 4095;
668*4882a593Smuzhiyun state->wbd_ref = value;
669*4882a593Smuzhiyun return dib8000_write_word(state, 106, value);
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun
dib8000_reset_pll_common(struct dib8000_state * state,const struct dibx000_bandwidth_config * bw)672*4882a593Smuzhiyun static void dib8000_reset_pll_common(struct dib8000_state *state, const struct dibx000_bandwidth_config *bw)
673*4882a593Smuzhiyun {
674*4882a593Smuzhiyun dprintk("ifreq: %d %x, inversion: %d\n", bw->ifreq, bw->ifreq, bw->ifreq >> 25);
675*4882a593Smuzhiyun if (state->revision != 0x8090) {
676*4882a593Smuzhiyun dib8000_write_word(state, 23,
677*4882a593Smuzhiyun (u16) (((bw->internal * 1000) >> 16) & 0xffff));
678*4882a593Smuzhiyun dib8000_write_word(state, 24,
679*4882a593Smuzhiyun (u16) ((bw->internal * 1000) & 0xffff));
680*4882a593Smuzhiyun } else {
681*4882a593Smuzhiyun dib8000_write_word(state, 23, (u16) (((bw->internal / 2 * 1000) >> 16) & 0xffff));
682*4882a593Smuzhiyun dib8000_write_word(state, 24,
683*4882a593Smuzhiyun (u16) ((bw->internal / 2 * 1000) & 0xffff));
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun dib8000_write_word(state, 27, (u16) ((bw->ifreq >> 16) & 0x01ff));
686*4882a593Smuzhiyun dib8000_write_word(state, 28, (u16) (bw->ifreq & 0xffff));
687*4882a593Smuzhiyun dib8000_write_word(state, 26, (u16) ((bw->ifreq >> 25) & 0x0003));
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun if (state->revision != 0x8090)
690*4882a593Smuzhiyun dib8000_write_word(state, 922, bw->sad_cfg);
691*4882a593Smuzhiyun }
692*4882a593Smuzhiyun
dib8000_reset_pll(struct dib8000_state * state)693*4882a593Smuzhiyun static void dib8000_reset_pll(struct dib8000_state *state)
694*4882a593Smuzhiyun {
695*4882a593Smuzhiyun const struct dibx000_bandwidth_config *pll = state->cfg.pll;
696*4882a593Smuzhiyun u16 clk_cfg1, reg;
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun if (state->revision != 0x8090) {
699*4882a593Smuzhiyun dib8000_write_word(state, 901,
700*4882a593Smuzhiyun (pll->pll_prediv << 8) | (pll->pll_ratio << 0));
701*4882a593Smuzhiyun
702*4882a593Smuzhiyun clk_cfg1 = (1 << 10) | (0 << 9) | (pll->IO_CLK_en_core << 8) |
703*4882a593Smuzhiyun (pll->bypclk_div << 5) | (pll->enable_refdiv << 4) |
704*4882a593Smuzhiyun (1 << 3) | (pll->pll_range << 1) |
705*4882a593Smuzhiyun (pll->pll_reset << 0);
706*4882a593Smuzhiyun
707*4882a593Smuzhiyun dib8000_write_word(state, 902, clk_cfg1);
708*4882a593Smuzhiyun clk_cfg1 = (clk_cfg1 & 0xfff7) | (pll->pll_bypass << 3);
709*4882a593Smuzhiyun dib8000_write_word(state, 902, clk_cfg1);
710*4882a593Smuzhiyun
711*4882a593Smuzhiyun dprintk("clk_cfg1: 0x%04x\n", clk_cfg1);
712*4882a593Smuzhiyun
713*4882a593Smuzhiyun /* smpl_cfg: P_refclksel=2, P_ensmplsel=1 nodivsmpl=1 */
714*4882a593Smuzhiyun if (state->cfg.pll->ADClkSrc == 0)
715*4882a593Smuzhiyun dib8000_write_word(state, 904,
716*4882a593Smuzhiyun (0 << 15) | (0 << 12) | (0 << 10) |
717*4882a593Smuzhiyun (pll->modulo << 8) |
718*4882a593Smuzhiyun (pll->ADClkSrc << 7) | (0 << 1));
719*4882a593Smuzhiyun else if (state->cfg.refclksel != 0)
720*4882a593Smuzhiyun dib8000_write_word(state, 904, (0 << 15) | (1 << 12) |
721*4882a593Smuzhiyun ((state->cfg.refclksel & 0x3) << 10) |
722*4882a593Smuzhiyun (pll->modulo << 8) |
723*4882a593Smuzhiyun (pll->ADClkSrc << 7) | (0 << 1));
724*4882a593Smuzhiyun else
725*4882a593Smuzhiyun dib8000_write_word(state, 904, (0 << 15) | (1 << 12) |
726*4882a593Smuzhiyun (3 << 10) | (pll->modulo << 8) |
727*4882a593Smuzhiyun (pll->ADClkSrc << 7) | (0 << 1));
728*4882a593Smuzhiyun } else {
729*4882a593Smuzhiyun dib8000_write_word(state, 1856, (!pll->pll_reset<<13) |
730*4882a593Smuzhiyun (pll->pll_range<<12) | (pll->pll_ratio<<6) |
731*4882a593Smuzhiyun (pll->pll_prediv));
732*4882a593Smuzhiyun
733*4882a593Smuzhiyun reg = dib8000_read_word(state, 1857);
734*4882a593Smuzhiyun dib8000_write_word(state, 1857, reg|(!pll->pll_bypass<<15));
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun reg = dib8000_read_word(state, 1858); /* Force clk out pll /2 */
737*4882a593Smuzhiyun dib8000_write_word(state, 1858, reg | 1);
738*4882a593Smuzhiyun
739*4882a593Smuzhiyun dib8000_write_word(state, 904, (pll->modulo << 8));
740*4882a593Smuzhiyun }
741*4882a593Smuzhiyun
742*4882a593Smuzhiyun dib8000_reset_pll_common(state, pll);
743*4882a593Smuzhiyun }
744*4882a593Smuzhiyun
dib8000_update_pll(struct dvb_frontend * fe,struct dibx000_bandwidth_config * pll,u32 bw,u8 ratio)745*4882a593Smuzhiyun static int dib8000_update_pll(struct dvb_frontend *fe,
746*4882a593Smuzhiyun struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio)
747*4882a593Smuzhiyun {
748*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
749*4882a593Smuzhiyun u16 reg_1857, reg_1856 = dib8000_read_word(state, 1856);
750*4882a593Smuzhiyun u8 loopdiv, prediv, oldprediv = state->cfg.pll->pll_prediv ;
751*4882a593Smuzhiyun u32 internal, xtal;
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun /* get back old values */
754*4882a593Smuzhiyun prediv = reg_1856 & 0x3f;
755*4882a593Smuzhiyun loopdiv = (reg_1856 >> 6) & 0x3f;
756*4882a593Smuzhiyun
757*4882a593Smuzhiyun if ((pll == NULL) || (pll->pll_prediv == prediv &&
758*4882a593Smuzhiyun pll->pll_ratio == loopdiv))
759*4882a593Smuzhiyun return -EINVAL;
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun dprintk("Updating pll (prediv: old = %d new = %d ; loopdiv : old = %d new = %d)\n", prediv, pll->pll_prediv, loopdiv, pll->pll_ratio);
762*4882a593Smuzhiyun if (state->revision == 0x8090) {
763*4882a593Smuzhiyun reg_1856 &= 0xf000;
764*4882a593Smuzhiyun reg_1857 = dib8000_read_word(state, 1857);
765*4882a593Smuzhiyun /* disable PLL */
766*4882a593Smuzhiyun dib8000_write_word(state, 1857, reg_1857 & ~(1 << 15));
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun dib8000_write_word(state, 1856, reg_1856 |
769*4882a593Smuzhiyun ((pll->pll_ratio & 0x3f) << 6) |
770*4882a593Smuzhiyun (pll->pll_prediv & 0x3f));
771*4882a593Smuzhiyun
772*4882a593Smuzhiyun /* write new system clk into P_sec_len */
773*4882a593Smuzhiyun internal = dib8000_read32(state, 23) / 1000;
774*4882a593Smuzhiyun dprintk("Old Internal = %d\n", internal);
775*4882a593Smuzhiyun xtal = 2 * (internal / loopdiv) * prediv;
776*4882a593Smuzhiyun internal = 1000 * (xtal/pll->pll_prediv) * pll->pll_ratio;
777*4882a593Smuzhiyun dprintk("Xtal = %d , New Fmem = %d New Fdemod = %d, New Fsampling = %d\n", xtal, internal/1000, internal/2000, internal/8000);
778*4882a593Smuzhiyun dprintk("New Internal = %d\n", internal);
779*4882a593Smuzhiyun
780*4882a593Smuzhiyun dib8000_write_word(state, 23,
781*4882a593Smuzhiyun (u16) (((internal / 2) >> 16) & 0xffff));
782*4882a593Smuzhiyun dib8000_write_word(state, 24, (u16) ((internal / 2) & 0xffff));
783*4882a593Smuzhiyun /* enable PLL */
784*4882a593Smuzhiyun dib8000_write_word(state, 1857, reg_1857 | (1 << 15));
785*4882a593Smuzhiyun
786*4882a593Smuzhiyun while (((dib8000_read_word(state, 1856)>>15)&0x1) != 1)
787*4882a593Smuzhiyun dprintk("Waiting for PLL to lock\n");
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun /* verify */
790*4882a593Smuzhiyun reg_1856 = dib8000_read_word(state, 1856);
791*4882a593Smuzhiyun dprintk("PLL Updated with prediv = %d and loopdiv = %d\n",
792*4882a593Smuzhiyun reg_1856&0x3f, (reg_1856>>6)&0x3f);
793*4882a593Smuzhiyun } else {
794*4882a593Smuzhiyun if (bw != state->current_demod_bw) {
795*4882a593Smuzhiyun /** Bandwidth change => force PLL update **/
796*4882a593Smuzhiyun dprintk("PLL: Bandwidth Change %d MHz -> %d MHz (prediv: %d->%d)\n", state->current_demod_bw / 1000, bw / 1000, oldprediv, state->cfg.pll->pll_prediv);
797*4882a593Smuzhiyun
798*4882a593Smuzhiyun if (state->cfg.pll->pll_prediv != oldprediv) {
799*4882a593Smuzhiyun /** Full PLL change only if prediv is changed **/
800*4882a593Smuzhiyun
801*4882a593Smuzhiyun /** full update => bypass and reconfigure **/
802*4882a593Smuzhiyun dprintk("PLL: New Setting for %d MHz Bandwidth (prediv: %d, ratio: %d)\n", bw/1000, state->cfg.pll->pll_prediv, state->cfg.pll->pll_ratio);
803*4882a593Smuzhiyun dib8000_write_word(state, 902, dib8000_read_word(state, 902) | (1<<3)); /* bypass PLL */
804*4882a593Smuzhiyun dib8000_reset_pll(state);
805*4882a593Smuzhiyun dib8000_write_word(state, 898, 0x0004); /* sad */
806*4882a593Smuzhiyun } else
807*4882a593Smuzhiyun ratio = state->cfg.pll->pll_ratio;
808*4882a593Smuzhiyun
809*4882a593Smuzhiyun state->current_demod_bw = bw;
810*4882a593Smuzhiyun }
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun if (ratio != 0) {
813*4882a593Smuzhiyun /** ratio update => only change ratio **/
814*4882a593Smuzhiyun dprintk("PLL: Update ratio (prediv: %d, ratio: %d)\n", state->cfg.pll->pll_prediv, ratio);
815*4882a593Smuzhiyun dib8000_write_word(state, 901, (state->cfg.pll->pll_prediv << 8) | (ratio << 0)); /* only the PLL ratio is updated. */
816*4882a593Smuzhiyun }
817*4882a593Smuzhiyun }
818*4882a593Smuzhiyun
819*4882a593Smuzhiyun return 0;
820*4882a593Smuzhiyun }
821*4882a593Smuzhiyun
dib8000_reset_gpio(struct dib8000_state * st)822*4882a593Smuzhiyun static int dib8000_reset_gpio(struct dib8000_state *st)
823*4882a593Smuzhiyun {
824*4882a593Smuzhiyun /* reset the GPIOs */
825*4882a593Smuzhiyun dib8000_write_word(st, 1029, st->cfg.gpio_dir);
826*4882a593Smuzhiyun dib8000_write_word(st, 1030, st->cfg.gpio_val);
827*4882a593Smuzhiyun
828*4882a593Smuzhiyun /* TODO 782 is P_gpio_od */
829*4882a593Smuzhiyun
830*4882a593Smuzhiyun dib8000_write_word(st, 1032, st->cfg.gpio_pwm_pos);
831*4882a593Smuzhiyun
832*4882a593Smuzhiyun dib8000_write_word(st, 1037, st->cfg.pwm_freq_div);
833*4882a593Smuzhiyun return 0;
834*4882a593Smuzhiyun }
835*4882a593Smuzhiyun
dib8000_cfg_gpio(struct dib8000_state * st,u8 num,u8 dir,u8 val)836*4882a593Smuzhiyun static int dib8000_cfg_gpio(struct dib8000_state *st, u8 num, u8 dir, u8 val)
837*4882a593Smuzhiyun {
838*4882a593Smuzhiyun st->cfg.gpio_dir = dib8000_read_word(st, 1029);
839*4882a593Smuzhiyun st->cfg.gpio_dir &= ~(1 << num); /* reset the direction bit */
840*4882a593Smuzhiyun st->cfg.gpio_dir |= (dir & 0x1) << num; /* set the new direction */
841*4882a593Smuzhiyun dib8000_write_word(st, 1029, st->cfg.gpio_dir);
842*4882a593Smuzhiyun
843*4882a593Smuzhiyun st->cfg.gpio_val = dib8000_read_word(st, 1030);
844*4882a593Smuzhiyun st->cfg.gpio_val &= ~(1 << num); /* reset the direction bit */
845*4882a593Smuzhiyun st->cfg.gpio_val |= (val & 0x01) << num; /* set the new value */
846*4882a593Smuzhiyun dib8000_write_word(st, 1030, st->cfg.gpio_val);
847*4882a593Smuzhiyun
848*4882a593Smuzhiyun dprintk("gpio dir: %x: gpio val: %x\n", st->cfg.gpio_dir, st->cfg.gpio_val);
849*4882a593Smuzhiyun
850*4882a593Smuzhiyun return 0;
851*4882a593Smuzhiyun }
852*4882a593Smuzhiyun
dib8000_set_gpio(struct dvb_frontend * fe,u8 num,u8 dir,u8 val)853*4882a593Smuzhiyun static int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
854*4882a593Smuzhiyun {
855*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
856*4882a593Smuzhiyun return dib8000_cfg_gpio(state, num, dir, val);
857*4882a593Smuzhiyun }
858*4882a593Smuzhiyun
859*4882a593Smuzhiyun static const u16 dib8000_defaults[] = {
860*4882a593Smuzhiyun /* auto search configuration - lock0 by default waiting
861*4882a593Smuzhiyun * for cpil_lock; lock1 cpil_lock; lock2 tmcc_sync_lock */
862*4882a593Smuzhiyun 3, 7,
863*4882a593Smuzhiyun 0x0004,
864*4882a593Smuzhiyun 0x0400,
865*4882a593Smuzhiyun 0x0814,
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun 12, 11,
868*4882a593Smuzhiyun 0x001b,
869*4882a593Smuzhiyun 0x7740,
870*4882a593Smuzhiyun 0x005b,
871*4882a593Smuzhiyun 0x8d80,
872*4882a593Smuzhiyun 0x01c9,
873*4882a593Smuzhiyun 0xc380,
874*4882a593Smuzhiyun 0x0000,
875*4882a593Smuzhiyun 0x0080,
876*4882a593Smuzhiyun 0x0000,
877*4882a593Smuzhiyun 0x0090,
878*4882a593Smuzhiyun 0x0001,
879*4882a593Smuzhiyun 0xd4c0,
880*4882a593Smuzhiyun
881*4882a593Smuzhiyun /*1, 32,
882*4882a593Smuzhiyun 0x6680 // P_corm_thres Lock algorithms configuration */
883*4882a593Smuzhiyun
884*4882a593Smuzhiyun 11, 80, /* set ADC level to -16 */
885*4882a593Smuzhiyun (1 << 13) - 825 - 117,
886*4882a593Smuzhiyun (1 << 13) - 837 - 117,
887*4882a593Smuzhiyun (1 << 13) - 811 - 117,
888*4882a593Smuzhiyun (1 << 13) - 766 - 117,
889*4882a593Smuzhiyun (1 << 13) - 737 - 117,
890*4882a593Smuzhiyun (1 << 13) - 693 - 117,
891*4882a593Smuzhiyun (1 << 13) - 648 - 117,
892*4882a593Smuzhiyun (1 << 13) - 619 - 117,
893*4882a593Smuzhiyun (1 << 13) - 575 - 117,
894*4882a593Smuzhiyun (1 << 13) - 531 - 117,
895*4882a593Smuzhiyun (1 << 13) - 501 - 117,
896*4882a593Smuzhiyun
897*4882a593Smuzhiyun 4, 108,
898*4882a593Smuzhiyun 0,
899*4882a593Smuzhiyun 0,
900*4882a593Smuzhiyun 0,
901*4882a593Smuzhiyun 0,
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun 1, 175,
904*4882a593Smuzhiyun 0x0410,
905*4882a593Smuzhiyun 1, 179,
906*4882a593Smuzhiyun 8192, // P_fft_nb_to_cut
907*4882a593Smuzhiyun
908*4882a593Smuzhiyun 6, 181,
909*4882a593Smuzhiyun 0x2800, // P_coff_corthres_ ( 2k 4k 8k ) 0x2800
910*4882a593Smuzhiyun 0x2800,
911*4882a593Smuzhiyun 0x2800,
912*4882a593Smuzhiyun 0x2800, // P_coff_cpilthres_ ( 2k 4k 8k ) 0x2800
913*4882a593Smuzhiyun 0x2800,
914*4882a593Smuzhiyun 0x2800,
915*4882a593Smuzhiyun
916*4882a593Smuzhiyun 2, 193,
917*4882a593Smuzhiyun 0x0666, // P_pha3_thres
918*4882a593Smuzhiyun 0x0000, // P_cti_use_cpe, P_cti_use_prog
919*4882a593Smuzhiyun
920*4882a593Smuzhiyun 2, 205,
921*4882a593Smuzhiyun 0x200f, // P_cspu_regul, P_cspu_win_cut
922*4882a593Smuzhiyun 0x000f, // P_des_shift_work
923*4882a593Smuzhiyun
924*4882a593Smuzhiyun 5, 215,
925*4882a593Smuzhiyun 0x023d, // P_adp_regul_cnt
926*4882a593Smuzhiyun 0x00a4, // P_adp_noise_cnt
927*4882a593Smuzhiyun 0x00a4, // P_adp_regul_ext
928*4882a593Smuzhiyun 0x7ff0, // P_adp_noise_ext
929*4882a593Smuzhiyun 0x3ccc, // P_adp_fil
930*4882a593Smuzhiyun
931*4882a593Smuzhiyun 1, 230,
932*4882a593Smuzhiyun 0x0000, // P_2d_byp_ti_num
933*4882a593Smuzhiyun
934*4882a593Smuzhiyun 1, 263,
935*4882a593Smuzhiyun 0x800, //P_equal_thres_wgn
936*4882a593Smuzhiyun
937*4882a593Smuzhiyun 1, 268,
938*4882a593Smuzhiyun (2 << 9) | 39, // P_equal_ctrl_synchro, P_equal_speedmode
939*4882a593Smuzhiyun
940*4882a593Smuzhiyun 1, 270,
941*4882a593Smuzhiyun 0x0001, // P_div_lock0_wait
942*4882a593Smuzhiyun 1, 285,
943*4882a593Smuzhiyun 0x0020, //p_fec_
944*4882a593Smuzhiyun 1, 299,
945*4882a593Smuzhiyun 0x0062, /* P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard */
946*4882a593Smuzhiyun
947*4882a593Smuzhiyun 1, 338,
948*4882a593Smuzhiyun (1 << 12) | // P_ctrl_corm_thres4pre_freq_inh=1
949*4882a593Smuzhiyun (1 << 10) |
950*4882a593Smuzhiyun (0 << 9) | /* P_ctrl_pre_freq_inh=0 */
951*4882a593Smuzhiyun (3 << 5) | /* P_ctrl_pre_freq_step=3 */
952*4882a593Smuzhiyun (1 << 0), /* P_pre_freq_win_len=1 */
953*4882a593Smuzhiyun
954*4882a593Smuzhiyun 0,
955*4882a593Smuzhiyun };
956*4882a593Smuzhiyun
dib8000_identify(struct i2c_device * client)957*4882a593Smuzhiyun static u16 dib8000_identify(struct i2c_device *client)
958*4882a593Smuzhiyun {
959*4882a593Smuzhiyun u16 value;
960*4882a593Smuzhiyun
961*4882a593Smuzhiyun //because of glitches sometimes
962*4882a593Smuzhiyun value = dib8000_i2c_read16(client, 896);
963*4882a593Smuzhiyun
964*4882a593Smuzhiyun if ((value = dib8000_i2c_read16(client, 896)) != 0x01b3) {
965*4882a593Smuzhiyun dprintk("wrong Vendor ID (read=0x%x)\n", value);
966*4882a593Smuzhiyun return 0;
967*4882a593Smuzhiyun }
968*4882a593Smuzhiyun
969*4882a593Smuzhiyun value = dib8000_i2c_read16(client, 897);
970*4882a593Smuzhiyun if (value != 0x8000 && value != 0x8001 &&
971*4882a593Smuzhiyun value != 0x8002 && value != 0x8090) {
972*4882a593Smuzhiyun dprintk("wrong Device ID (%x)\n", value);
973*4882a593Smuzhiyun return 0;
974*4882a593Smuzhiyun }
975*4882a593Smuzhiyun
976*4882a593Smuzhiyun switch (value) {
977*4882a593Smuzhiyun case 0x8000:
978*4882a593Smuzhiyun dprintk("found DiB8000A\n");
979*4882a593Smuzhiyun break;
980*4882a593Smuzhiyun case 0x8001:
981*4882a593Smuzhiyun dprintk("found DiB8000B\n");
982*4882a593Smuzhiyun break;
983*4882a593Smuzhiyun case 0x8002:
984*4882a593Smuzhiyun dprintk("found DiB8000C\n");
985*4882a593Smuzhiyun break;
986*4882a593Smuzhiyun case 0x8090:
987*4882a593Smuzhiyun dprintk("found DiB8096P\n");
988*4882a593Smuzhiyun break;
989*4882a593Smuzhiyun }
990*4882a593Smuzhiyun return value;
991*4882a593Smuzhiyun }
992*4882a593Smuzhiyun
993*4882a593Smuzhiyun static int dib8000_read_unc_blocks(struct dvb_frontend *fe, u32 *unc);
994*4882a593Smuzhiyun
dib8000_reset_stats(struct dvb_frontend * fe)995*4882a593Smuzhiyun static void dib8000_reset_stats(struct dvb_frontend *fe)
996*4882a593Smuzhiyun {
997*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
998*4882a593Smuzhiyun struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
999*4882a593Smuzhiyun u32 ucb;
1000*4882a593Smuzhiyun
1001*4882a593Smuzhiyun memset(&c->strength, 0, sizeof(c->strength));
1002*4882a593Smuzhiyun memset(&c->cnr, 0, sizeof(c->cnr));
1003*4882a593Smuzhiyun memset(&c->post_bit_error, 0, sizeof(c->post_bit_error));
1004*4882a593Smuzhiyun memset(&c->post_bit_count, 0, sizeof(c->post_bit_count));
1005*4882a593Smuzhiyun memset(&c->block_error, 0, sizeof(c->block_error));
1006*4882a593Smuzhiyun
1007*4882a593Smuzhiyun c->strength.len = 1;
1008*4882a593Smuzhiyun c->cnr.len = 1;
1009*4882a593Smuzhiyun c->block_error.len = 1;
1010*4882a593Smuzhiyun c->block_count.len = 1;
1011*4882a593Smuzhiyun c->post_bit_error.len = 1;
1012*4882a593Smuzhiyun c->post_bit_count.len = 1;
1013*4882a593Smuzhiyun
1014*4882a593Smuzhiyun c->strength.stat[0].scale = FE_SCALE_DECIBEL;
1015*4882a593Smuzhiyun c->strength.stat[0].uvalue = 0;
1016*4882a593Smuzhiyun
1017*4882a593Smuzhiyun c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1018*4882a593Smuzhiyun c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1019*4882a593Smuzhiyun c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1020*4882a593Smuzhiyun c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1021*4882a593Smuzhiyun c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1022*4882a593Smuzhiyun
1023*4882a593Smuzhiyun dib8000_read_unc_blocks(fe, &ucb);
1024*4882a593Smuzhiyun
1025*4882a593Smuzhiyun state->init_ucb = -ucb;
1026*4882a593Smuzhiyun state->ber_jiffies_stats = 0;
1027*4882a593Smuzhiyun state->per_jiffies_stats = 0;
1028*4882a593Smuzhiyun memset(&state->ber_jiffies_stats_layer, 0,
1029*4882a593Smuzhiyun sizeof(state->ber_jiffies_stats_layer));
1030*4882a593Smuzhiyun }
1031*4882a593Smuzhiyun
dib8000_reset(struct dvb_frontend * fe)1032*4882a593Smuzhiyun static int dib8000_reset(struct dvb_frontend *fe)
1033*4882a593Smuzhiyun {
1034*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
1035*4882a593Smuzhiyun
1036*4882a593Smuzhiyun if ((state->revision = dib8000_identify(&state->i2c)) == 0)
1037*4882a593Smuzhiyun return -EINVAL;
1038*4882a593Smuzhiyun
1039*4882a593Smuzhiyun /* sram lead in, rdy */
1040*4882a593Smuzhiyun if (state->revision != 0x8090)
1041*4882a593Smuzhiyun dib8000_write_word(state, 1287, 0x0003);
1042*4882a593Smuzhiyun
1043*4882a593Smuzhiyun if (state->revision == 0x8000)
1044*4882a593Smuzhiyun dprintk("error : dib8000 MA not supported\n");
1045*4882a593Smuzhiyun
1046*4882a593Smuzhiyun dibx000_reset_i2c_master(&state->i2c_master);
1047*4882a593Smuzhiyun
1048*4882a593Smuzhiyun dib8000_set_power_mode(state, DIB8000_POWER_ALL);
1049*4882a593Smuzhiyun
1050*4882a593Smuzhiyun /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */
1051*4882a593Smuzhiyun dib8000_set_adc_state(state, DIBX000_ADC_OFF);
1052*4882a593Smuzhiyun
1053*4882a593Smuzhiyun /* restart all parts */
1054*4882a593Smuzhiyun dib8000_write_word(state, 770, 0xffff);
1055*4882a593Smuzhiyun dib8000_write_word(state, 771, 0xffff);
1056*4882a593Smuzhiyun dib8000_write_word(state, 772, 0xfffc);
1057*4882a593Smuzhiyun dib8000_write_word(state, 898, 0x000c); /* restart sad */
1058*4882a593Smuzhiyun if (state->revision == 0x8090)
1059*4882a593Smuzhiyun dib8000_write_word(state, 1280, 0x0045);
1060*4882a593Smuzhiyun else
1061*4882a593Smuzhiyun dib8000_write_word(state, 1280, 0x004d);
1062*4882a593Smuzhiyun dib8000_write_word(state, 1281, 0x000c);
1063*4882a593Smuzhiyun
1064*4882a593Smuzhiyun dib8000_write_word(state, 770, 0x0000);
1065*4882a593Smuzhiyun dib8000_write_word(state, 771, 0x0000);
1066*4882a593Smuzhiyun dib8000_write_word(state, 772, 0x0000);
1067*4882a593Smuzhiyun dib8000_write_word(state, 898, 0x0004); // sad
1068*4882a593Smuzhiyun dib8000_write_word(state, 1280, 0x0000);
1069*4882a593Smuzhiyun dib8000_write_word(state, 1281, 0x0000);
1070*4882a593Smuzhiyun
1071*4882a593Smuzhiyun /* drives */
1072*4882a593Smuzhiyun if (state->revision != 0x8090) {
1073*4882a593Smuzhiyun if (state->cfg.drives)
1074*4882a593Smuzhiyun dib8000_write_word(state, 906, state->cfg.drives);
1075*4882a593Smuzhiyun else {
1076*4882a593Smuzhiyun dprintk("using standard PAD-drive-settings, please adjust settings in config-struct to be optimal.\n");
1077*4882a593Smuzhiyun /* min drive SDRAM - not optimal - adjust */
1078*4882a593Smuzhiyun dib8000_write_word(state, 906, 0x2d98);
1079*4882a593Smuzhiyun }
1080*4882a593Smuzhiyun }
1081*4882a593Smuzhiyun
1082*4882a593Smuzhiyun dib8000_reset_pll(state);
1083*4882a593Smuzhiyun if (state->revision != 0x8090)
1084*4882a593Smuzhiyun dib8000_write_word(state, 898, 0x0004);
1085*4882a593Smuzhiyun
1086*4882a593Smuzhiyun if (dib8000_reset_gpio(state) != 0)
1087*4882a593Smuzhiyun dprintk("GPIO reset was not successful.\n");
1088*4882a593Smuzhiyun
1089*4882a593Smuzhiyun if ((state->revision != 0x8090) &&
1090*4882a593Smuzhiyun (dib8000_set_output_mode(fe, OUTMODE_HIGH_Z) != 0))
1091*4882a593Smuzhiyun dprintk("OUTPUT_MODE could not be reset.\n");
1092*4882a593Smuzhiyun
1093*4882a593Smuzhiyun state->current_agc = NULL;
1094*4882a593Smuzhiyun
1095*4882a593Smuzhiyun // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ...
1096*4882a593Smuzhiyun /* P_iqc_ca2 = 0; P_iqc_impnc_on = 0; P_iqc_mode = 0; */
1097*4882a593Smuzhiyun if (state->cfg.pll->ifreq == 0)
1098*4882a593Smuzhiyun dib8000_write_word(state, 40, 0x0755); /* P_iqc_corr_inh = 0 enable IQcorr block */
1099*4882a593Smuzhiyun else
1100*4882a593Smuzhiyun dib8000_write_word(state, 40, 0x1f55); /* P_iqc_corr_inh = 1 disable IQcorr block */
1101*4882a593Smuzhiyun
1102*4882a593Smuzhiyun {
1103*4882a593Smuzhiyun u16 l = 0, r;
1104*4882a593Smuzhiyun const u16 *n;
1105*4882a593Smuzhiyun n = dib8000_defaults;
1106*4882a593Smuzhiyun l = *n++;
1107*4882a593Smuzhiyun while (l) {
1108*4882a593Smuzhiyun r = *n++;
1109*4882a593Smuzhiyun do {
1110*4882a593Smuzhiyun dib8000_write_word(state, r, *n++);
1111*4882a593Smuzhiyun r++;
1112*4882a593Smuzhiyun } while (--l);
1113*4882a593Smuzhiyun l = *n++;
1114*4882a593Smuzhiyun }
1115*4882a593Smuzhiyun }
1116*4882a593Smuzhiyun
1117*4882a593Smuzhiyun state->isdbt_cfg_loaded = 0;
1118*4882a593Smuzhiyun
1119*4882a593Smuzhiyun //div_cfg override for special configs
1120*4882a593Smuzhiyun if ((state->revision != 8090) && (state->cfg.div_cfg != 0))
1121*4882a593Smuzhiyun dib8000_write_word(state, 903, state->cfg.div_cfg);
1122*4882a593Smuzhiyun
1123*4882a593Smuzhiyun /* unforce divstr regardless whether i2c enumeration was done or not */
1124*4882a593Smuzhiyun dib8000_write_word(state, 1285, dib8000_read_word(state, 1285) & ~(1 << 1));
1125*4882a593Smuzhiyun
1126*4882a593Smuzhiyun dib8000_set_bandwidth(fe, 6000);
1127*4882a593Smuzhiyun
1128*4882a593Smuzhiyun dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON);
1129*4882a593Smuzhiyun dib8000_sad_calib(state);
1130*4882a593Smuzhiyun if (state->revision != 0x8090)
1131*4882a593Smuzhiyun dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
1132*4882a593Smuzhiyun
1133*4882a593Smuzhiyun /* ber_rs_len = 3 */
1134*4882a593Smuzhiyun dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5));
1135*4882a593Smuzhiyun
1136*4882a593Smuzhiyun dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY);
1137*4882a593Smuzhiyun
1138*4882a593Smuzhiyun dib8000_reset_stats(fe);
1139*4882a593Smuzhiyun
1140*4882a593Smuzhiyun return 0;
1141*4882a593Smuzhiyun }
1142*4882a593Smuzhiyun
dib8000_restart_agc(struct dib8000_state * state)1143*4882a593Smuzhiyun static void dib8000_restart_agc(struct dib8000_state *state)
1144*4882a593Smuzhiyun {
1145*4882a593Smuzhiyun // P_restart_iqc & P_restart_agc
1146*4882a593Smuzhiyun dib8000_write_word(state, 770, 0x0a00);
1147*4882a593Smuzhiyun dib8000_write_word(state, 770, 0x0000);
1148*4882a593Smuzhiyun }
1149*4882a593Smuzhiyun
dib8000_update_lna(struct dib8000_state * state)1150*4882a593Smuzhiyun static int dib8000_update_lna(struct dib8000_state *state)
1151*4882a593Smuzhiyun {
1152*4882a593Smuzhiyun u16 dyn_gain;
1153*4882a593Smuzhiyun
1154*4882a593Smuzhiyun if (state->cfg.update_lna) {
1155*4882a593Smuzhiyun // read dyn_gain here (because it is demod-dependent and not tuner)
1156*4882a593Smuzhiyun dyn_gain = dib8000_read_word(state, 390);
1157*4882a593Smuzhiyun
1158*4882a593Smuzhiyun if (state->cfg.update_lna(state->fe[0], dyn_gain)) {
1159*4882a593Smuzhiyun dib8000_restart_agc(state);
1160*4882a593Smuzhiyun return 1;
1161*4882a593Smuzhiyun }
1162*4882a593Smuzhiyun }
1163*4882a593Smuzhiyun return 0;
1164*4882a593Smuzhiyun }
1165*4882a593Smuzhiyun
dib8000_set_agc_config(struct dib8000_state * state,u8 band)1166*4882a593Smuzhiyun static int dib8000_set_agc_config(struct dib8000_state *state, u8 band)
1167*4882a593Smuzhiyun {
1168*4882a593Smuzhiyun struct dibx000_agc_config *agc = NULL;
1169*4882a593Smuzhiyun int i;
1170*4882a593Smuzhiyun u16 reg;
1171*4882a593Smuzhiyun
1172*4882a593Smuzhiyun if (state->current_band == band && state->current_agc != NULL)
1173*4882a593Smuzhiyun return 0;
1174*4882a593Smuzhiyun state->current_band = band;
1175*4882a593Smuzhiyun
1176*4882a593Smuzhiyun for (i = 0; i < state->cfg.agc_config_count; i++)
1177*4882a593Smuzhiyun if (state->cfg.agc[i].band_caps & band) {
1178*4882a593Smuzhiyun agc = &state->cfg.agc[i];
1179*4882a593Smuzhiyun break;
1180*4882a593Smuzhiyun }
1181*4882a593Smuzhiyun
1182*4882a593Smuzhiyun if (agc == NULL) {
1183*4882a593Smuzhiyun dprintk("no valid AGC configuration found for band 0x%02x\n", band);
1184*4882a593Smuzhiyun return -EINVAL;
1185*4882a593Smuzhiyun }
1186*4882a593Smuzhiyun
1187*4882a593Smuzhiyun state->current_agc = agc;
1188*4882a593Smuzhiyun
1189*4882a593Smuzhiyun /* AGC */
1190*4882a593Smuzhiyun dib8000_write_word(state, 76, agc->setup);
1191*4882a593Smuzhiyun dib8000_write_word(state, 77, agc->inv_gain);
1192*4882a593Smuzhiyun dib8000_write_word(state, 78, agc->time_stabiliz);
1193*4882a593Smuzhiyun dib8000_write_word(state, 101, (agc->alpha_level << 12) | agc->thlock);
1194*4882a593Smuzhiyun
1195*4882a593Smuzhiyun // Demod AGC loop configuration
1196*4882a593Smuzhiyun dib8000_write_word(state, 102, (agc->alpha_mant << 5) | agc->alpha_exp);
1197*4882a593Smuzhiyun dib8000_write_word(state, 103, (agc->beta_mant << 6) | agc->beta_exp);
1198*4882a593Smuzhiyun
1199*4882a593Smuzhiyun dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d\n",
1200*4882a593Smuzhiyun state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
1201*4882a593Smuzhiyun
1202*4882a593Smuzhiyun /* AGC continued */
1203*4882a593Smuzhiyun if (state->wbd_ref != 0)
1204*4882a593Smuzhiyun dib8000_write_word(state, 106, state->wbd_ref);
1205*4882a593Smuzhiyun else // use default
1206*4882a593Smuzhiyun dib8000_write_word(state, 106, agc->wbd_ref);
1207*4882a593Smuzhiyun
1208*4882a593Smuzhiyun if (state->revision == 0x8090) {
1209*4882a593Smuzhiyun reg = dib8000_read_word(state, 922) & (0x3 << 2);
1210*4882a593Smuzhiyun dib8000_write_word(state, 922, reg | (agc->wbd_sel << 2));
1211*4882a593Smuzhiyun }
1212*4882a593Smuzhiyun
1213*4882a593Smuzhiyun dib8000_write_word(state, 107, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8));
1214*4882a593Smuzhiyun dib8000_write_word(state, 108, agc->agc1_max);
1215*4882a593Smuzhiyun dib8000_write_word(state, 109, agc->agc1_min);
1216*4882a593Smuzhiyun dib8000_write_word(state, 110, agc->agc2_max);
1217*4882a593Smuzhiyun dib8000_write_word(state, 111, agc->agc2_min);
1218*4882a593Smuzhiyun dib8000_write_word(state, 112, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
1219*4882a593Smuzhiyun dib8000_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
1220*4882a593Smuzhiyun dib8000_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
1221*4882a593Smuzhiyun dib8000_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
1222*4882a593Smuzhiyun
1223*4882a593Smuzhiyun dib8000_write_word(state, 75, agc->agc1_pt3);
1224*4882a593Smuzhiyun if (state->revision != 0x8090)
1225*4882a593Smuzhiyun dib8000_write_word(state, 923,
1226*4882a593Smuzhiyun (dib8000_read_word(state, 923) & 0xffe3) |
1227*4882a593Smuzhiyun (agc->wbd_inv << 4) | (agc->wbd_sel << 2));
1228*4882a593Smuzhiyun
1229*4882a593Smuzhiyun return 0;
1230*4882a593Smuzhiyun }
1231*4882a593Smuzhiyun
dib8000_pwm_agc_reset(struct dvb_frontend * fe)1232*4882a593Smuzhiyun static void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
1233*4882a593Smuzhiyun {
1234*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
1235*4882a593Smuzhiyun dib8000_set_adc_state(state, DIBX000_ADC_ON);
1236*4882a593Smuzhiyun dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000)));
1237*4882a593Smuzhiyun }
1238*4882a593Smuzhiyun
dib8000_agc_soft_split(struct dib8000_state * state)1239*4882a593Smuzhiyun static int dib8000_agc_soft_split(struct dib8000_state *state)
1240*4882a593Smuzhiyun {
1241*4882a593Smuzhiyun u16 agc, split_offset;
1242*4882a593Smuzhiyun
1243*4882a593Smuzhiyun if (!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0)
1244*4882a593Smuzhiyun return 0;
1245*4882a593Smuzhiyun
1246*4882a593Smuzhiyun // n_agc_global
1247*4882a593Smuzhiyun agc = dib8000_read_word(state, 390);
1248*4882a593Smuzhiyun
1249*4882a593Smuzhiyun if (agc > state->current_agc->split.min_thres)
1250*4882a593Smuzhiyun split_offset = state->current_agc->split.min;
1251*4882a593Smuzhiyun else if (agc < state->current_agc->split.max_thres)
1252*4882a593Smuzhiyun split_offset = state->current_agc->split.max;
1253*4882a593Smuzhiyun else
1254*4882a593Smuzhiyun split_offset = state->current_agc->split.max *
1255*4882a593Smuzhiyun (agc - state->current_agc->split.min_thres) /
1256*4882a593Smuzhiyun (state->current_agc->split.max_thres - state->current_agc->split.min_thres);
1257*4882a593Smuzhiyun
1258*4882a593Smuzhiyun dprintk("AGC split_offset: %d\n", split_offset);
1259*4882a593Smuzhiyun
1260*4882a593Smuzhiyun // P_agc_force_split and P_agc_split_offset
1261*4882a593Smuzhiyun dib8000_write_word(state, 107, (dib8000_read_word(state, 107) & 0xff00) | split_offset);
1262*4882a593Smuzhiyun return 5000;
1263*4882a593Smuzhiyun }
1264*4882a593Smuzhiyun
dib8000_agc_startup(struct dvb_frontend * fe)1265*4882a593Smuzhiyun static int dib8000_agc_startup(struct dvb_frontend *fe)
1266*4882a593Smuzhiyun {
1267*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
1268*4882a593Smuzhiyun enum frontend_tune_state *tune_state = &state->tune_state;
1269*4882a593Smuzhiyun int ret = 0;
1270*4882a593Smuzhiyun u16 reg;
1271*4882a593Smuzhiyun u32 upd_demod_gain_period = 0x8000;
1272*4882a593Smuzhiyun
1273*4882a593Smuzhiyun switch (*tune_state) {
1274*4882a593Smuzhiyun case CT_AGC_START:
1275*4882a593Smuzhiyun // set power-up level: interf+analog+AGC
1276*4882a593Smuzhiyun
1277*4882a593Smuzhiyun if (state->revision != 0x8090)
1278*4882a593Smuzhiyun dib8000_set_adc_state(state, DIBX000_ADC_ON);
1279*4882a593Smuzhiyun else {
1280*4882a593Smuzhiyun dib8000_set_power_mode(state, DIB8000_POWER_ALL);
1281*4882a593Smuzhiyun
1282*4882a593Smuzhiyun reg = dib8000_read_word(state, 1947)&0xff00;
1283*4882a593Smuzhiyun dib8000_write_word(state, 1946,
1284*4882a593Smuzhiyun upd_demod_gain_period & 0xFFFF);
1285*4882a593Smuzhiyun /* bit 14 = enDemodGain */
1286*4882a593Smuzhiyun dib8000_write_word(state, 1947, reg | (1<<14) |
1287*4882a593Smuzhiyun ((upd_demod_gain_period >> 16) & 0xFF));
1288*4882a593Smuzhiyun
1289*4882a593Smuzhiyun /* enable adc i & q */
1290*4882a593Smuzhiyun reg = dib8000_read_word(state, 1920);
1291*4882a593Smuzhiyun dib8000_write_word(state, 1920, (reg | 0x3) &
1292*4882a593Smuzhiyun (~(1 << 7)));
1293*4882a593Smuzhiyun }
1294*4882a593Smuzhiyun
1295*4882a593Smuzhiyun if (dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000))) != 0) {
1296*4882a593Smuzhiyun *tune_state = CT_AGC_STOP;
1297*4882a593Smuzhiyun state->status = FE_STATUS_TUNE_FAILED;
1298*4882a593Smuzhiyun break;
1299*4882a593Smuzhiyun }
1300*4882a593Smuzhiyun
1301*4882a593Smuzhiyun ret = 70;
1302*4882a593Smuzhiyun *tune_state = CT_AGC_STEP_0;
1303*4882a593Smuzhiyun break;
1304*4882a593Smuzhiyun
1305*4882a593Smuzhiyun case CT_AGC_STEP_0:
1306*4882a593Smuzhiyun //AGC initialization
1307*4882a593Smuzhiyun if (state->cfg.agc_control)
1308*4882a593Smuzhiyun state->cfg.agc_control(fe, 1);
1309*4882a593Smuzhiyun
1310*4882a593Smuzhiyun dib8000_restart_agc(state);
1311*4882a593Smuzhiyun
1312*4882a593Smuzhiyun // wait AGC rough lock time
1313*4882a593Smuzhiyun ret = 50;
1314*4882a593Smuzhiyun *tune_state = CT_AGC_STEP_1;
1315*4882a593Smuzhiyun break;
1316*4882a593Smuzhiyun
1317*4882a593Smuzhiyun case CT_AGC_STEP_1:
1318*4882a593Smuzhiyun // wait AGC accurate lock time
1319*4882a593Smuzhiyun ret = 70;
1320*4882a593Smuzhiyun
1321*4882a593Smuzhiyun if (dib8000_update_lna(state))
1322*4882a593Smuzhiyun // wait only AGC rough lock time
1323*4882a593Smuzhiyun ret = 50;
1324*4882a593Smuzhiyun else
1325*4882a593Smuzhiyun *tune_state = CT_AGC_STEP_2;
1326*4882a593Smuzhiyun break;
1327*4882a593Smuzhiyun
1328*4882a593Smuzhiyun case CT_AGC_STEP_2:
1329*4882a593Smuzhiyun dib8000_agc_soft_split(state);
1330*4882a593Smuzhiyun
1331*4882a593Smuzhiyun if (state->cfg.agc_control)
1332*4882a593Smuzhiyun state->cfg.agc_control(fe, 0);
1333*4882a593Smuzhiyun
1334*4882a593Smuzhiyun *tune_state = CT_AGC_STOP;
1335*4882a593Smuzhiyun break;
1336*4882a593Smuzhiyun default:
1337*4882a593Smuzhiyun ret = dib8000_agc_soft_split(state);
1338*4882a593Smuzhiyun break;
1339*4882a593Smuzhiyun }
1340*4882a593Smuzhiyun return ret;
1341*4882a593Smuzhiyun
1342*4882a593Smuzhiyun }
1343*4882a593Smuzhiyun
dib8096p_host_bus_drive(struct dib8000_state * state,u8 drive)1344*4882a593Smuzhiyun static void dib8096p_host_bus_drive(struct dib8000_state *state, u8 drive)
1345*4882a593Smuzhiyun {
1346*4882a593Smuzhiyun u16 reg;
1347*4882a593Smuzhiyun
1348*4882a593Smuzhiyun drive &= 0x7;
1349*4882a593Smuzhiyun
1350*4882a593Smuzhiyun /* drive host bus 2, 3, 4 */
1351*4882a593Smuzhiyun reg = dib8000_read_word(state, 1798) &
1352*4882a593Smuzhiyun ~(0x7 | (0x7 << 6) | (0x7 << 12));
1353*4882a593Smuzhiyun reg |= (drive<<12) | (drive<<6) | drive;
1354*4882a593Smuzhiyun dib8000_write_word(state, 1798, reg);
1355*4882a593Smuzhiyun
1356*4882a593Smuzhiyun /* drive host bus 5,6 */
1357*4882a593Smuzhiyun reg = dib8000_read_word(state, 1799) & ~((0x7 << 2) | (0x7 << 8));
1358*4882a593Smuzhiyun reg |= (drive<<8) | (drive<<2);
1359*4882a593Smuzhiyun dib8000_write_word(state, 1799, reg);
1360*4882a593Smuzhiyun
1361*4882a593Smuzhiyun /* drive host bus 7, 8, 9 */
1362*4882a593Smuzhiyun reg = dib8000_read_word(state, 1800) &
1363*4882a593Smuzhiyun ~(0x7 | (0x7 << 6) | (0x7 << 12));
1364*4882a593Smuzhiyun reg |= (drive<<12) | (drive<<6) | drive;
1365*4882a593Smuzhiyun dib8000_write_word(state, 1800, reg);
1366*4882a593Smuzhiyun
1367*4882a593Smuzhiyun /* drive host bus 10, 11 */
1368*4882a593Smuzhiyun reg = dib8000_read_word(state, 1801) & ~((0x7 << 2) | (0x7 << 8));
1369*4882a593Smuzhiyun reg |= (drive<<8) | (drive<<2);
1370*4882a593Smuzhiyun dib8000_write_word(state, 1801, reg);
1371*4882a593Smuzhiyun
1372*4882a593Smuzhiyun /* drive host bus 12, 13, 14 */
1373*4882a593Smuzhiyun reg = dib8000_read_word(state, 1802) &
1374*4882a593Smuzhiyun ~(0x7 | (0x7 << 6) | (0x7 << 12));
1375*4882a593Smuzhiyun reg |= (drive<<12) | (drive<<6) | drive;
1376*4882a593Smuzhiyun dib8000_write_word(state, 1802, reg);
1377*4882a593Smuzhiyun }
1378*4882a593Smuzhiyun
dib8096p_calcSyncFreq(u32 P_Kin,u32 P_Kout,u32 insertExtSynchro,u32 syncSize)1379*4882a593Smuzhiyun static u32 dib8096p_calcSyncFreq(u32 P_Kin, u32 P_Kout,
1380*4882a593Smuzhiyun u32 insertExtSynchro, u32 syncSize)
1381*4882a593Smuzhiyun {
1382*4882a593Smuzhiyun u32 quantif = 3;
1383*4882a593Smuzhiyun u32 nom = (insertExtSynchro * P_Kin+syncSize);
1384*4882a593Smuzhiyun u32 denom = P_Kout;
1385*4882a593Smuzhiyun u32 syncFreq = ((nom << quantif) / denom);
1386*4882a593Smuzhiyun
1387*4882a593Smuzhiyun if ((syncFreq & ((1 << quantif) - 1)) != 0)
1388*4882a593Smuzhiyun syncFreq = (syncFreq >> quantif) + 1;
1389*4882a593Smuzhiyun else
1390*4882a593Smuzhiyun syncFreq = (syncFreq >> quantif);
1391*4882a593Smuzhiyun
1392*4882a593Smuzhiyun if (syncFreq != 0)
1393*4882a593Smuzhiyun syncFreq = syncFreq - 1;
1394*4882a593Smuzhiyun
1395*4882a593Smuzhiyun return syncFreq;
1396*4882a593Smuzhiyun }
1397*4882a593Smuzhiyun
dib8096p_cfg_DibTx(struct dib8000_state * state,u32 P_Kin,u32 P_Kout,u32 insertExtSynchro,u32 synchroMode,u32 syncWord,u32 syncSize)1398*4882a593Smuzhiyun static void dib8096p_cfg_DibTx(struct dib8000_state *state, u32 P_Kin,
1399*4882a593Smuzhiyun u32 P_Kout, u32 insertExtSynchro, u32 synchroMode,
1400*4882a593Smuzhiyun u32 syncWord, u32 syncSize)
1401*4882a593Smuzhiyun {
1402*4882a593Smuzhiyun dprintk("Configure DibStream Tx\n");
1403*4882a593Smuzhiyun
1404*4882a593Smuzhiyun dib8000_write_word(state, 1615, 1);
1405*4882a593Smuzhiyun dib8000_write_word(state, 1603, P_Kin);
1406*4882a593Smuzhiyun dib8000_write_word(state, 1605, P_Kout);
1407*4882a593Smuzhiyun dib8000_write_word(state, 1606, insertExtSynchro);
1408*4882a593Smuzhiyun dib8000_write_word(state, 1608, synchroMode);
1409*4882a593Smuzhiyun dib8000_write_word(state, 1609, (syncWord >> 16) & 0xffff);
1410*4882a593Smuzhiyun dib8000_write_word(state, 1610, syncWord & 0xffff);
1411*4882a593Smuzhiyun dib8000_write_word(state, 1612, syncSize);
1412*4882a593Smuzhiyun dib8000_write_word(state, 1615, 0);
1413*4882a593Smuzhiyun }
1414*4882a593Smuzhiyun
dib8096p_cfg_DibRx(struct dib8000_state * state,u32 P_Kin,u32 P_Kout,u32 synchroMode,u32 insertExtSynchro,u32 syncWord,u32 syncSize,u32 dataOutRate)1415*4882a593Smuzhiyun static void dib8096p_cfg_DibRx(struct dib8000_state *state, u32 P_Kin,
1416*4882a593Smuzhiyun u32 P_Kout, u32 synchroMode, u32 insertExtSynchro,
1417*4882a593Smuzhiyun u32 syncWord, u32 syncSize, u32 dataOutRate)
1418*4882a593Smuzhiyun {
1419*4882a593Smuzhiyun u32 syncFreq;
1420*4882a593Smuzhiyun
1421*4882a593Smuzhiyun dprintk("Configure DibStream Rx synchroMode = %d\n", synchroMode);
1422*4882a593Smuzhiyun
1423*4882a593Smuzhiyun if ((P_Kin != 0) && (P_Kout != 0)) {
1424*4882a593Smuzhiyun syncFreq = dib8096p_calcSyncFreq(P_Kin, P_Kout,
1425*4882a593Smuzhiyun insertExtSynchro, syncSize);
1426*4882a593Smuzhiyun dib8000_write_word(state, 1542, syncFreq);
1427*4882a593Smuzhiyun }
1428*4882a593Smuzhiyun
1429*4882a593Smuzhiyun dib8000_write_word(state, 1554, 1);
1430*4882a593Smuzhiyun dib8000_write_word(state, 1536, P_Kin);
1431*4882a593Smuzhiyun dib8000_write_word(state, 1537, P_Kout);
1432*4882a593Smuzhiyun dib8000_write_word(state, 1539, synchroMode);
1433*4882a593Smuzhiyun dib8000_write_word(state, 1540, (syncWord >> 16) & 0xffff);
1434*4882a593Smuzhiyun dib8000_write_word(state, 1541, syncWord & 0xffff);
1435*4882a593Smuzhiyun dib8000_write_word(state, 1543, syncSize);
1436*4882a593Smuzhiyun dib8000_write_word(state, 1544, dataOutRate);
1437*4882a593Smuzhiyun dib8000_write_word(state, 1554, 0);
1438*4882a593Smuzhiyun }
1439*4882a593Smuzhiyun
dib8096p_enMpegMux(struct dib8000_state * state,int onoff)1440*4882a593Smuzhiyun static void dib8096p_enMpegMux(struct dib8000_state *state, int onoff)
1441*4882a593Smuzhiyun {
1442*4882a593Smuzhiyun u16 reg_1287;
1443*4882a593Smuzhiyun
1444*4882a593Smuzhiyun reg_1287 = dib8000_read_word(state, 1287);
1445*4882a593Smuzhiyun
1446*4882a593Smuzhiyun switch (onoff) {
1447*4882a593Smuzhiyun case 1:
1448*4882a593Smuzhiyun reg_1287 &= ~(1 << 8);
1449*4882a593Smuzhiyun break;
1450*4882a593Smuzhiyun case 0:
1451*4882a593Smuzhiyun reg_1287 |= (1 << 8);
1452*4882a593Smuzhiyun break;
1453*4882a593Smuzhiyun }
1454*4882a593Smuzhiyun
1455*4882a593Smuzhiyun dib8000_write_word(state, 1287, reg_1287);
1456*4882a593Smuzhiyun }
1457*4882a593Smuzhiyun
dib8096p_configMpegMux(struct dib8000_state * state,u16 pulseWidth,u16 enSerialMode,u16 enSerialClkDiv2)1458*4882a593Smuzhiyun static void dib8096p_configMpegMux(struct dib8000_state *state,
1459*4882a593Smuzhiyun u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2)
1460*4882a593Smuzhiyun {
1461*4882a593Smuzhiyun u16 reg_1287;
1462*4882a593Smuzhiyun
1463*4882a593Smuzhiyun dprintk("Enable Mpeg mux\n");
1464*4882a593Smuzhiyun
1465*4882a593Smuzhiyun dib8096p_enMpegMux(state, 0);
1466*4882a593Smuzhiyun
1467*4882a593Smuzhiyun /* If the input mode is MPEG do not divide the serial clock */
1468*4882a593Smuzhiyun if ((enSerialMode == 1) && (state->input_mode_mpeg == 1))
1469*4882a593Smuzhiyun enSerialClkDiv2 = 0;
1470*4882a593Smuzhiyun
1471*4882a593Smuzhiyun reg_1287 = ((pulseWidth & 0x1f) << 3) |
1472*4882a593Smuzhiyun ((enSerialMode & 0x1) << 2) | (enSerialClkDiv2 & 0x1);
1473*4882a593Smuzhiyun dib8000_write_word(state, 1287, reg_1287);
1474*4882a593Smuzhiyun
1475*4882a593Smuzhiyun dib8096p_enMpegMux(state, 1);
1476*4882a593Smuzhiyun }
1477*4882a593Smuzhiyun
dib8096p_setDibTxMux(struct dib8000_state * state,int mode)1478*4882a593Smuzhiyun static void dib8096p_setDibTxMux(struct dib8000_state *state, int mode)
1479*4882a593Smuzhiyun {
1480*4882a593Smuzhiyun u16 reg_1288 = dib8000_read_word(state, 1288) & ~(0x7 << 7);
1481*4882a593Smuzhiyun
1482*4882a593Smuzhiyun switch (mode) {
1483*4882a593Smuzhiyun case MPEG_ON_DIBTX:
1484*4882a593Smuzhiyun dprintk("SET MPEG ON DIBSTREAM TX\n");
1485*4882a593Smuzhiyun dib8096p_cfg_DibTx(state, 8, 5, 0, 0, 0, 0);
1486*4882a593Smuzhiyun reg_1288 |= (1 << 9); break;
1487*4882a593Smuzhiyun case DIV_ON_DIBTX:
1488*4882a593Smuzhiyun dprintk("SET DIV_OUT ON DIBSTREAM TX\n");
1489*4882a593Smuzhiyun dib8096p_cfg_DibTx(state, 5, 5, 0, 0, 0, 0);
1490*4882a593Smuzhiyun reg_1288 |= (1 << 8); break;
1491*4882a593Smuzhiyun case ADC_ON_DIBTX:
1492*4882a593Smuzhiyun dprintk("SET ADC_OUT ON DIBSTREAM TX\n");
1493*4882a593Smuzhiyun dib8096p_cfg_DibTx(state, 20, 5, 10, 0, 0, 0);
1494*4882a593Smuzhiyun reg_1288 |= (1 << 7); break;
1495*4882a593Smuzhiyun default:
1496*4882a593Smuzhiyun break;
1497*4882a593Smuzhiyun }
1498*4882a593Smuzhiyun dib8000_write_word(state, 1288, reg_1288);
1499*4882a593Smuzhiyun }
1500*4882a593Smuzhiyun
dib8096p_setHostBusMux(struct dib8000_state * state,int mode)1501*4882a593Smuzhiyun static void dib8096p_setHostBusMux(struct dib8000_state *state, int mode)
1502*4882a593Smuzhiyun {
1503*4882a593Smuzhiyun u16 reg_1288 = dib8000_read_word(state, 1288) & ~(0x7 << 4);
1504*4882a593Smuzhiyun
1505*4882a593Smuzhiyun switch (mode) {
1506*4882a593Smuzhiyun case DEMOUT_ON_HOSTBUS:
1507*4882a593Smuzhiyun dprintk("SET DEM OUT OLD INTERF ON HOST BUS\n");
1508*4882a593Smuzhiyun dib8096p_enMpegMux(state, 0);
1509*4882a593Smuzhiyun reg_1288 |= (1 << 6);
1510*4882a593Smuzhiyun break;
1511*4882a593Smuzhiyun case DIBTX_ON_HOSTBUS:
1512*4882a593Smuzhiyun dprintk("SET DIBSTREAM TX ON HOST BUS\n");
1513*4882a593Smuzhiyun dib8096p_enMpegMux(state, 0);
1514*4882a593Smuzhiyun reg_1288 |= (1 << 5);
1515*4882a593Smuzhiyun break;
1516*4882a593Smuzhiyun case MPEG_ON_HOSTBUS:
1517*4882a593Smuzhiyun dprintk("SET MPEG MUX ON HOST BUS\n");
1518*4882a593Smuzhiyun reg_1288 |= (1 << 4);
1519*4882a593Smuzhiyun break;
1520*4882a593Smuzhiyun default:
1521*4882a593Smuzhiyun break;
1522*4882a593Smuzhiyun }
1523*4882a593Smuzhiyun dib8000_write_word(state, 1288, reg_1288);
1524*4882a593Smuzhiyun }
1525*4882a593Smuzhiyun
dib8096p_set_diversity_in(struct dvb_frontend * fe,int onoff)1526*4882a593Smuzhiyun static int dib8096p_set_diversity_in(struct dvb_frontend *fe, int onoff)
1527*4882a593Smuzhiyun {
1528*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
1529*4882a593Smuzhiyun u16 reg_1287;
1530*4882a593Smuzhiyun
1531*4882a593Smuzhiyun switch (onoff) {
1532*4882a593Smuzhiyun case 0: /* only use the internal way - not the diversity input */
1533*4882a593Smuzhiyun dprintk("%s mode OFF : by default Enable Mpeg INPUT\n",
1534*4882a593Smuzhiyun __func__);
1535*4882a593Smuzhiyun /* outputRate = 8 */
1536*4882a593Smuzhiyun dib8096p_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0);
1537*4882a593Smuzhiyun
1538*4882a593Smuzhiyun /* Do not divide the serial clock of MPEG MUX in
1539*4882a593Smuzhiyun SERIAL MODE in case input mode MPEG is used */
1540*4882a593Smuzhiyun reg_1287 = dib8000_read_word(state, 1287);
1541*4882a593Smuzhiyun /* enSerialClkDiv2 == 1 ? */
1542*4882a593Smuzhiyun if ((reg_1287 & 0x1) == 1) {
1543*4882a593Smuzhiyun /* force enSerialClkDiv2 = 0 */
1544*4882a593Smuzhiyun reg_1287 &= ~0x1;
1545*4882a593Smuzhiyun dib8000_write_word(state, 1287, reg_1287);
1546*4882a593Smuzhiyun }
1547*4882a593Smuzhiyun state->input_mode_mpeg = 1;
1548*4882a593Smuzhiyun break;
1549*4882a593Smuzhiyun case 1: /* both ways */
1550*4882a593Smuzhiyun case 2: /* only the diversity input */
1551*4882a593Smuzhiyun dprintk("%s ON : Enable diversity INPUT\n", __func__);
1552*4882a593Smuzhiyun dib8096p_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0);
1553*4882a593Smuzhiyun state->input_mode_mpeg = 0;
1554*4882a593Smuzhiyun break;
1555*4882a593Smuzhiyun }
1556*4882a593Smuzhiyun
1557*4882a593Smuzhiyun dib8000_set_diversity_in(state->fe[0], onoff);
1558*4882a593Smuzhiyun return 0;
1559*4882a593Smuzhiyun }
1560*4882a593Smuzhiyun
dib8096p_set_output_mode(struct dvb_frontend * fe,int mode)1561*4882a593Smuzhiyun static int dib8096p_set_output_mode(struct dvb_frontend *fe, int mode)
1562*4882a593Smuzhiyun {
1563*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
1564*4882a593Smuzhiyun u16 outreg, smo_mode, fifo_threshold;
1565*4882a593Smuzhiyun u8 prefer_mpeg_mux_use = 1;
1566*4882a593Smuzhiyun int ret = 0;
1567*4882a593Smuzhiyun
1568*4882a593Smuzhiyun state->output_mode = mode;
1569*4882a593Smuzhiyun dib8096p_host_bus_drive(state, 1);
1570*4882a593Smuzhiyun
1571*4882a593Smuzhiyun fifo_threshold = 1792;
1572*4882a593Smuzhiyun smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1);
1573*4882a593Smuzhiyun outreg = dib8000_read_word(state, 1286) &
1574*4882a593Smuzhiyun ~((1 << 10) | (0x7 << 6) | (1 << 1));
1575*4882a593Smuzhiyun
1576*4882a593Smuzhiyun switch (mode) {
1577*4882a593Smuzhiyun case OUTMODE_HIGH_Z:
1578*4882a593Smuzhiyun outreg = 0;
1579*4882a593Smuzhiyun break;
1580*4882a593Smuzhiyun
1581*4882a593Smuzhiyun case OUTMODE_MPEG2_SERIAL:
1582*4882a593Smuzhiyun if (prefer_mpeg_mux_use) {
1583*4882a593Smuzhiyun dprintk("dib8096P setting output mode TS_SERIAL using Mpeg Mux\n");
1584*4882a593Smuzhiyun dib8096p_configMpegMux(state, 3, 1, 1);
1585*4882a593Smuzhiyun dib8096p_setHostBusMux(state, MPEG_ON_HOSTBUS);
1586*4882a593Smuzhiyun } else {/* Use Smooth block */
1587*4882a593Smuzhiyun dprintk("dib8096P setting output mode TS_SERIAL using Smooth bloc\n");
1588*4882a593Smuzhiyun dib8096p_setHostBusMux(state,
1589*4882a593Smuzhiyun DEMOUT_ON_HOSTBUS);
1590*4882a593Smuzhiyun outreg |= (2 << 6) | (0 << 1);
1591*4882a593Smuzhiyun }
1592*4882a593Smuzhiyun break;
1593*4882a593Smuzhiyun
1594*4882a593Smuzhiyun case OUTMODE_MPEG2_PAR_GATED_CLK:
1595*4882a593Smuzhiyun if (prefer_mpeg_mux_use) {
1596*4882a593Smuzhiyun dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Mpeg Mux\n");
1597*4882a593Smuzhiyun dib8096p_configMpegMux(state, 2, 0, 0);
1598*4882a593Smuzhiyun dib8096p_setHostBusMux(state, MPEG_ON_HOSTBUS);
1599*4882a593Smuzhiyun } else { /* Use Smooth block */
1600*4882a593Smuzhiyun dprintk("dib8096P setting output mode TS_PARALLEL_GATED using Smooth block\n");
1601*4882a593Smuzhiyun dib8096p_setHostBusMux(state,
1602*4882a593Smuzhiyun DEMOUT_ON_HOSTBUS);
1603*4882a593Smuzhiyun outreg |= (0 << 6);
1604*4882a593Smuzhiyun }
1605*4882a593Smuzhiyun break;
1606*4882a593Smuzhiyun
1607*4882a593Smuzhiyun case OUTMODE_MPEG2_PAR_CONT_CLK: /* Using Smooth block only */
1608*4882a593Smuzhiyun dprintk("dib8096P setting output mode TS_PARALLEL_CONT using Smooth block\n");
1609*4882a593Smuzhiyun dib8096p_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
1610*4882a593Smuzhiyun outreg |= (1 << 6);
1611*4882a593Smuzhiyun break;
1612*4882a593Smuzhiyun
1613*4882a593Smuzhiyun case OUTMODE_MPEG2_FIFO:
1614*4882a593Smuzhiyun /* Using Smooth block because not supported
1615*4882a593Smuzhiyun by new Mpeg Mux bloc */
1616*4882a593Smuzhiyun dprintk("dib8096P setting output mode TS_FIFO using Smooth block\n");
1617*4882a593Smuzhiyun dib8096p_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
1618*4882a593Smuzhiyun outreg |= (5 << 6);
1619*4882a593Smuzhiyun smo_mode |= (3 << 1);
1620*4882a593Smuzhiyun fifo_threshold = 512;
1621*4882a593Smuzhiyun break;
1622*4882a593Smuzhiyun
1623*4882a593Smuzhiyun case OUTMODE_DIVERSITY:
1624*4882a593Smuzhiyun dprintk("dib8096P setting output mode MODE_DIVERSITY\n");
1625*4882a593Smuzhiyun dib8096p_setDibTxMux(state, DIV_ON_DIBTX);
1626*4882a593Smuzhiyun dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
1627*4882a593Smuzhiyun break;
1628*4882a593Smuzhiyun
1629*4882a593Smuzhiyun case OUTMODE_ANALOG_ADC:
1630*4882a593Smuzhiyun dprintk("dib8096P setting output mode MODE_ANALOG_ADC\n");
1631*4882a593Smuzhiyun dib8096p_setDibTxMux(state, ADC_ON_DIBTX);
1632*4882a593Smuzhiyun dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
1633*4882a593Smuzhiyun break;
1634*4882a593Smuzhiyun }
1635*4882a593Smuzhiyun
1636*4882a593Smuzhiyun if (mode != OUTMODE_HIGH_Z)
1637*4882a593Smuzhiyun outreg |= (1<<10);
1638*4882a593Smuzhiyun
1639*4882a593Smuzhiyun dprintk("output_mpeg2_in_188_bytes = %d\n",
1640*4882a593Smuzhiyun state->cfg.output_mpeg2_in_188_bytes);
1641*4882a593Smuzhiyun if (state->cfg.output_mpeg2_in_188_bytes)
1642*4882a593Smuzhiyun smo_mode |= (1 << 5);
1643*4882a593Smuzhiyun
1644*4882a593Smuzhiyun ret |= dib8000_write_word(state, 299, smo_mode);
1645*4882a593Smuzhiyun /* synchronous fread */
1646*4882a593Smuzhiyun ret |= dib8000_write_word(state, 299 + 1, fifo_threshold);
1647*4882a593Smuzhiyun ret |= dib8000_write_word(state, 1286, outreg);
1648*4882a593Smuzhiyun
1649*4882a593Smuzhiyun return ret;
1650*4882a593Smuzhiyun }
1651*4882a593Smuzhiyun
map_addr_to_serpar_number(struct i2c_msg * msg)1652*4882a593Smuzhiyun static int map_addr_to_serpar_number(struct i2c_msg *msg)
1653*4882a593Smuzhiyun {
1654*4882a593Smuzhiyun if (msg->buf[0] <= 15)
1655*4882a593Smuzhiyun msg->buf[0] -= 1;
1656*4882a593Smuzhiyun else if (msg->buf[0] == 17)
1657*4882a593Smuzhiyun msg->buf[0] = 15;
1658*4882a593Smuzhiyun else if (msg->buf[0] == 16)
1659*4882a593Smuzhiyun msg->buf[0] = 17;
1660*4882a593Smuzhiyun else if (msg->buf[0] == 19)
1661*4882a593Smuzhiyun msg->buf[0] = 16;
1662*4882a593Smuzhiyun else if (msg->buf[0] >= 21 && msg->buf[0] <= 25)
1663*4882a593Smuzhiyun msg->buf[0] -= 3;
1664*4882a593Smuzhiyun else if (msg->buf[0] == 28)
1665*4882a593Smuzhiyun msg->buf[0] = 23;
1666*4882a593Smuzhiyun else if (msg->buf[0] == 99)
1667*4882a593Smuzhiyun msg->buf[0] = 99;
1668*4882a593Smuzhiyun else
1669*4882a593Smuzhiyun return -EINVAL;
1670*4882a593Smuzhiyun return 0;
1671*4882a593Smuzhiyun }
1672*4882a593Smuzhiyun
dib8096p_tuner_write_serpar(struct i2c_adapter * i2c_adap,struct i2c_msg msg[],int num)1673*4882a593Smuzhiyun static int dib8096p_tuner_write_serpar(struct i2c_adapter *i2c_adap,
1674*4882a593Smuzhiyun struct i2c_msg msg[], int num)
1675*4882a593Smuzhiyun {
1676*4882a593Smuzhiyun struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
1677*4882a593Smuzhiyun u8 n_overflow = 1;
1678*4882a593Smuzhiyun u16 i = 1000;
1679*4882a593Smuzhiyun u16 serpar_num = msg[0].buf[0];
1680*4882a593Smuzhiyun
1681*4882a593Smuzhiyun while (n_overflow == 1 && i) {
1682*4882a593Smuzhiyun n_overflow = (dib8000_read_word(state, 1984) >> 1) & 0x1;
1683*4882a593Smuzhiyun i--;
1684*4882a593Smuzhiyun if (i == 0)
1685*4882a593Smuzhiyun dprintk("Tuner ITF: write busy (overflow)\n");
1686*4882a593Smuzhiyun }
1687*4882a593Smuzhiyun dib8000_write_word(state, 1985, (1 << 6) | (serpar_num & 0x3f));
1688*4882a593Smuzhiyun dib8000_write_word(state, 1986, (msg[0].buf[1] << 8) | msg[0].buf[2]);
1689*4882a593Smuzhiyun
1690*4882a593Smuzhiyun return num;
1691*4882a593Smuzhiyun }
1692*4882a593Smuzhiyun
dib8096p_tuner_read_serpar(struct i2c_adapter * i2c_adap,struct i2c_msg msg[],int num)1693*4882a593Smuzhiyun static int dib8096p_tuner_read_serpar(struct i2c_adapter *i2c_adap,
1694*4882a593Smuzhiyun struct i2c_msg msg[], int num)
1695*4882a593Smuzhiyun {
1696*4882a593Smuzhiyun struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
1697*4882a593Smuzhiyun u8 n_overflow = 1, n_empty = 1;
1698*4882a593Smuzhiyun u16 i = 1000;
1699*4882a593Smuzhiyun u16 serpar_num = msg[0].buf[0];
1700*4882a593Smuzhiyun u16 read_word;
1701*4882a593Smuzhiyun
1702*4882a593Smuzhiyun while (n_overflow == 1 && i) {
1703*4882a593Smuzhiyun n_overflow = (dib8000_read_word(state, 1984) >> 1) & 0x1;
1704*4882a593Smuzhiyun i--;
1705*4882a593Smuzhiyun if (i == 0)
1706*4882a593Smuzhiyun dprintk("TunerITF: read busy (overflow)\n");
1707*4882a593Smuzhiyun }
1708*4882a593Smuzhiyun dib8000_write_word(state, 1985, (0<<6) | (serpar_num&0x3f));
1709*4882a593Smuzhiyun
1710*4882a593Smuzhiyun i = 1000;
1711*4882a593Smuzhiyun while (n_empty == 1 && i) {
1712*4882a593Smuzhiyun n_empty = dib8000_read_word(state, 1984)&0x1;
1713*4882a593Smuzhiyun i--;
1714*4882a593Smuzhiyun if (i == 0)
1715*4882a593Smuzhiyun dprintk("TunerITF: read busy (empty)\n");
1716*4882a593Smuzhiyun }
1717*4882a593Smuzhiyun
1718*4882a593Smuzhiyun read_word = dib8000_read_word(state, 1987);
1719*4882a593Smuzhiyun msg[1].buf[0] = (read_word >> 8) & 0xff;
1720*4882a593Smuzhiyun msg[1].buf[1] = (read_word) & 0xff;
1721*4882a593Smuzhiyun
1722*4882a593Smuzhiyun return num;
1723*4882a593Smuzhiyun }
1724*4882a593Smuzhiyun
dib8096p_tuner_rw_serpar(struct i2c_adapter * i2c_adap,struct i2c_msg msg[],int num)1725*4882a593Smuzhiyun static int dib8096p_tuner_rw_serpar(struct i2c_adapter *i2c_adap,
1726*4882a593Smuzhiyun struct i2c_msg msg[], int num)
1727*4882a593Smuzhiyun {
1728*4882a593Smuzhiyun if (map_addr_to_serpar_number(&msg[0]) == 0) {
1729*4882a593Smuzhiyun if (num == 1) /* write */
1730*4882a593Smuzhiyun return dib8096p_tuner_write_serpar(i2c_adap, msg, 1);
1731*4882a593Smuzhiyun else /* read */
1732*4882a593Smuzhiyun return dib8096p_tuner_read_serpar(i2c_adap, msg, 2);
1733*4882a593Smuzhiyun }
1734*4882a593Smuzhiyun return num;
1735*4882a593Smuzhiyun }
1736*4882a593Smuzhiyun
dib8096p_rw_on_apb(struct i2c_adapter * i2c_adap,struct i2c_msg msg[],int num,u16 apb_address)1737*4882a593Smuzhiyun static int dib8096p_rw_on_apb(struct i2c_adapter *i2c_adap,
1738*4882a593Smuzhiyun struct i2c_msg msg[], int num, u16 apb_address)
1739*4882a593Smuzhiyun {
1740*4882a593Smuzhiyun struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
1741*4882a593Smuzhiyun u16 word;
1742*4882a593Smuzhiyun
1743*4882a593Smuzhiyun if (num == 1) { /* write */
1744*4882a593Smuzhiyun dib8000_write_word(state, apb_address,
1745*4882a593Smuzhiyun ((msg[0].buf[1] << 8) | (msg[0].buf[2])));
1746*4882a593Smuzhiyun } else {
1747*4882a593Smuzhiyun word = dib8000_read_word(state, apb_address);
1748*4882a593Smuzhiyun msg[1].buf[0] = (word >> 8) & 0xff;
1749*4882a593Smuzhiyun msg[1].buf[1] = (word) & 0xff;
1750*4882a593Smuzhiyun }
1751*4882a593Smuzhiyun return num;
1752*4882a593Smuzhiyun }
1753*4882a593Smuzhiyun
dib8096p_tuner_xfer(struct i2c_adapter * i2c_adap,struct i2c_msg msg[],int num)1754*4882a593Smuzhiyun static int dib8096p_tuner_xfer(struct i2c_adapter *i2c_adap,
1755*4882a593Smuzhiyun struct i2c_msg msg[], int num)
1756*4882a593Smuzhiyun {
1757*4882a593Smuzhiyun struct dib8000_state *state = i2c_get_adapdata(i2c_adap);
1758*4882a593Smuzhiyun u16 apb_address = 0, word;
1759*4882a593Smuzhiyun int i = 0;
1760*4882a593Smuzhiyun
1761*4882a593Smuzhiyun switch (msg[0].buf[0]) {
1762*4882a593Smuzhiyun case 0x12:
1763*4882a593Smuzhiyun apb_address = 1920;
1764*4882a593Smuzhiyun break;
1765*4882a593Smuzhiyun case 0x14:
1766*4882a593Smuzhiyun apb_address = 1921;
1767*4882a593Smuzhiyun break;
1768*4882a593Smuzhiyun case 0x24:
1769*4882a593Smuzhiyun apb_address = 1922;
1770*4882a593Smuzhiyun break;
1771*4882a593Smuzhiyun case 0x1a:
1772*4882a593Smuzhiyun apb_address = 1923;
1773*4882a593Smuzhiyun break;
1774*4882a593Smuzhiyun case 0x22:
1775*4882a593Smuzhiyun apb_address = 1924;
1776*4882a593Smuzhiyun break;
1777*4882a593Smuzhiyun case 0x33:
1778*4882a593Smuzhiyun apb_address = 1926;
1779*4882a593Smuzhiyun break;
1780*4882a593Smuzhiyun case 0x34:
1781*4882a593Smuzhiyun apb_address = 1927;
1782*4882a593Smuzhiyun break;
1783*4882a593Smuzhiyun case 0x35:
1784*4882a593Smuzhiyun apb_address = 1928;
1785*4882a593Smuzhiyun break;
1786*4882a593Smuzhiyun case 0x36:
1787*4882a593Smuzhiyun apb_address = 1929;
1788*4882a593Smuzhiyun break;
1789*4882a593Smuzhiyun case 0x37:
1790*4882a593Smuzhiyun apb_address = 1930;
1791*4882a593Smuzhiyun break;
1792*4882a593Smuzhiyun case 0x38:
1793*4882a593Smuzhiyun apb_address = 1931;
1794*4882a593Smuzhiyun break;
1795*4882a593Smuzhiyun case 0x39:
1796*4882a593Smuzhiyun apb_address = 1932;
1797*4882a593Smuzhiyun break;
1798*4882a593Smuzhiyun case 0x2a:
1799*4882a593Smuzhiyun apb_address = 1935;
1800*4882a593Smuzhiyun break;
1801*4882a593Smuzhiyun case 0x2b:
1802*4882a593Smuzhiyun apb_address = 1936;
1803*4882a593Smuzhiyun break;
1804*4882a593Smuzhiyun case 0x2c:
1805*4882a593Smuzhiyun apb_address = 1937;
1806*4882a593Smuzhiyun break;
1807*4882a593Smuzhiyun case 0x2d:
1808*4882a593Smuzhiyun apb_address = 1938;
1809*4882a593Smuzhiyun break;
1810*4882a593Smuzhiyun case 0x2e:
1811*4882a593Smuzhiyun apb_address = 1939;
1812*4882a593Smuzhiyun break;
1813*4882a593Smuzhiyun case 0x2f:
1814*4882a593Smuzhiyun apb_address = 1940;
1815*4882a593Smuzhiyun break;
1816*4882a593Smuzhiyun case 0x30:
1817*4882a593Smuzhiyun apb_address = 1941;
1818*4882a593Smuzhiyun break;
1819*4882a593Smuzhiyun case 0x31:
1820*4882a593Smuzhiyun apb_address = 1942;
1821*4882a593Smuzhiyun break;
1822*4882a593Smuzhiyun case 0x32:
1823*4882a593Smuzhiyun apb_address = 1943;
1824*4882a593Smuzhiyun break;
1825*4882a593Smuzhiyun case 0x3e:
1826*4882a593Smuzhiyun apb_address = 1944;
1827*4882a593Smuzhiyun break;
1828*4882a593Smuzhiyun case 0x3f:
1829*4882a593Smuzhiyun apb_address = 1945;
1830*4882a593Smuzhiyun break;
1831*4882a593Smuzhiyun case 0x40:
1832*4882a593Smuzhiyun apb_address = 1948;
1833*4882a593Smuzhiyun break;
1834*4882a593Smuzhiyun case 0x25:
1835*4882a593Smuzhiyun apb_address = 936;
1836*4882a593Smuzhiyun break;
1837*4882a593Smuzhiyun case 0x26:
1838*4882a593Smuzhiyun apb_address = 937;
1839*4882a593Smuzhiyun break;
1840*4882a593Smuzhiyun case 0x27:
1841*4882a593Smuzhiyun apb_address = 938;
1842*4882a593Smuzhiyun break;
1843*4882a593Smuzhiyun case 0x28:
1844*4882a593Smuzhiyun apb_address = 939;
1845*4882a593Smuzhiyun break;
1846*4882a593Smuzhiyun case 0x1d:
1847*4882a593Smuzhiyun /* get sad sel request */
1848*4882a593Smuzhiyun i = ((dib8000_read_word(state, 921) >> 12)&0x3);
1849*4882a593Smuzhiyun word = dib8000_read_word(state, 924+i);
1850*4882a593Smuzhiyun msg[1].buf[0] = (word >> 8) & 0xff;
1851*4882a593Smuzhiyun msg[1].buf[1] = (word) & 0xff;
1852*4882a593Smuzhiyun return num;
1853*4882a593Smuzhiyun case 0x1f:
1854*4882a593Smuzhiyun if (num == 1) { /* write */
1855*4882a593Smuzhiyun word = (u16) ((msg[0].buf[1] << 8) |
1856*4882a593Smuzhiyun msg[0].buf[2]);
1857*4882a593Smuzhiyun /* in the VGAMODE Sel are located on bit 0/1 */
1858*4882a593Smuzhiyun word &= 0x3;
1859*4882a593Smuzhiyun word = (dib8000_read_word(state, 921) &
1860*4882a593Smuzhiyun ~(3<<12)) | (word<<12);
1861*4882a593Smuzhiyun /* Set the proper input */
1862*4882a593Smuzhiyun dib8000_write_word(state, 921, word);
1863*4882a593Smuzhiyun return num;
1864*4882a593Smuzhiyun }
1865*4882a593Smuzhiyun }
1866*4882a593Smuzhiyun
1867*4882a593Smuzhiyun if (apb_address != 0) /* R/W access via APB */
1868*4882a593Smuzhiyun return dib8096p_rw_on_apb(i2c_adap, msg, num, apb_address);
1869*4882a593Smuzhiyun else /* R/W access via SERPAR */
1870*4882a593Smuzhiyun return dib8096p_tuner_rw_serpar(i2c_adap, msg, num);
1871*4882a593Smuzhiyun
1872*4882a593Smuzhiyun return 0;
1873*4882a593Smuzhiyun }
1874*4882a593Smuzhiyun
dib8096p_i2c_func(struct i2c_adapter * adapter)1875*4882a593Smuzhiyun static u32 dib8096p_i2c_func(struct i2c_adapter *adapter)
1876*4882a593Smuzhiyun {
1877*4882a593Smuzhiyun return I2C_FUNC_I2C;
1878*4882a593Smuzhiyun }
1879*4882a593Smuzhiyun
1880*4882a593Smuzhiyun static const struct i2c_algorithm dib8096p_tuner_xfer_algo = {
1881*4882a593Smuzhiyun .master_xfer = dib8096p_tuner_xfer,
1882*4882a593Smuzhiyun .functionality = dib8096p_i2c_func,
1883*4882a593Smuzhiyun };
1884*4882a593Smuzhiyun
dib8096p_get_i2c_tuner(struct dvb_frontend * fe)1885*4882a593Smuzhiyun static struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe)
1886*4882a593Smuzhiyun {
1887*4882a593Smuzhiyun struct dib8000_state *st = fe->demodulator_priv;
1888*4882a593Smuzhiyun return &st->dib8096p_tuner_adap;
1889*4882a593Smuzhiyun }
1890*4882a593Smuzhiyun
dib8096p_tuner_sleep(struct dvb_frontend * fe,int onoff)1891*4882a593Smuzhiyun static int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
1892*4882a593Smuzhiyun {
1893*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
1894*4882a593Smuzhiyun u16 en_cur_state;
1895*4882a593Smuzhiyun
1896*4882a593Smuzhiyun dprintk("sleep dib8096p: %d\n", onoff);
1897*4882a593Smuzhiyun
1898*4882a593Smuzhiyun en_cur_state = dib8000_read_word(state, 1922);
1899*4882a593Smuzhiyun
1900*4882a593Smuzhiyun /* LNAs and MIX are ON and therefore it is a valid configuration */
1901*4882a593Smuzhiyun if (en_cur_state > 0xff)
1902*4882a593Smuzhiyun state->tuner_enable = en_cur_state ;
1903*4882a593Smuzhiyun
1904*4882a593Smuzhiyun if (onoff)
1905*4882a593Smuzhiyun en_cur_state &= 0x00ff;
1906*4882a593Smuzhiyun else {
1907*4882a593Smuzhiyun if (state->tuner_enable != 0)
1908*4882a593Smuzhiyun en_cur_state = state->tuner_enable;
1909*4882a593Smuzhiyun }
1910*4882a593Smuzhiyun
1911*4882a593Smuzhiyun dib8000_write_word(state, 1922, en_cur_state);
1912*4882a593Smuzhiyun
1913*4882a593Smuzhiyun return 0;
1914*4882a593Smuzhiyun }
1915*4882a593Smuzhiyun
1916*4882a593Smuzhiyun static const s32 lut_1000ln_mant[] =
1917*4882a593Smuzhiyun {
1918*4882a593Smuzhiyun 908, 7003, 7090, 7170, 7244, 7313, 7377, 7438, 7495, 7549, 7600
1919*4882a593Smuzhiyun };
1920*4882a593Smuzhiyun
dib8000_get_adc_power(struct dvb_frontend * fe,u8 mode)1921*4882a593Smuzhiyun static s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
1922*4882a593Smuzhiyun {
1923*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
1924*4882a593Smuzhiyun u32 ix = 0, tmp_val = 0, exp = 0, mant = 0;
1925*4882a593Smuzhiyun s32 val;
1926*4882a593Smuzhiyun
1927*4882a593Smuzhiyun val = dib8000_read32(state, 384);
1928*4882a593Smuzhiyun if (mode) {
1929*4882a593Smuzhiyun tmp_val = val;
1930*4882a593Smuzhiyun while (tmp_val >>= 1)
1931*4882a593Smuzhiyun exp++;
1932*4882a593Smuzhiyun mant = (val * 1000 / (1<<exp));
1933*4882a593Smuzhiyun ix = (u8)((mant-1000)/100); /* index of the LUT */
1934*4882a593Smuzhiyun val = (lut_1000ln_mant[ix] + 693*(exp-20) - 6908);
1935*4882a593Smuzhiyun val = (val*256)/1000;
1936*4882a593Smuzhiyun }
1937*4882a593Smuzhiyun return val;
1938*4882a593Smuzhiyun }
1939*4882a593Smuzhiyun
dib8090p_get_dc_power(struct dvb_frontend * fe,u8 IQ)1940*4882a593Smuzhiyun static int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
1941*4882a593Smuzhiyun {
1942*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
1943*4882a593Smuzhiyun int val = 0;
1944*4882a593Smuzhiyun
1945*4882a593Smuzhiyun switch (IQ) {
1946*4882a593Smuzhiyun case 1:
1947*4882a593Smuzhiyun val = dib8000_read_word(state, 403);
1948*4882a593Smuzhiyun break;
1949*4882a593Smuzhiyun case 0:
1950*4882a593Smuzhiyun val = dib8000_read_word(state, 404);
1951*4882a593Smuzhiyun break;
1952*4882a593Smuzhiyun }
1953*4882a593Smuzhiyun if (val & 0x200)
1954*4882a593Smuzhiyun val -= 1024;
1955*4882a593Smuzhiyun
1956*4882a593Smuzhiyun return val;
1957*4882a593Smuzhiyun }
1958*4882a593Smuzhiyun
dib8000_update_timf(struct dib8000_state * state)1959*4882a593Smuzhiyun static void dib8000_update_timf(struct dib8000_state *state)
1960*4882a593Smuzhiyun {
1961*4882a593Smuzhiyun u32 timf = state->timf = dib8000_read32(state, 435);
1962*4882a593Smuzhiyun
1963*4882a593Smuzhiyun dib8000_write_word(state, 29, (u16) (timf >> 16));
1964*4882a593Smuzhiyun dib8000_write_word(state, 30, (u16) (timf & 0xffff));
1965*4882a593Smuzhiyun dprintk("Updated timing frequency: %d (default: %d)\n", state->timf, state->timf_default);
1966*4882a593Smuzhiyun }
1967*4882a593Smuzhiyun
dib8000_ctrl_timf(struct dvb_frontend * fe,uint8_t op,uint32_t timf)1968*4882a593Smuzhiyun static u32 dib8000_ctrl_timf(struct dvb_frontend *fe, uint8_t op, uint32_t timf)
1969*4882a593Smuzhiyun {
1970*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
1971*4882a593Smuzhiyun
1972*4882a593Smuzhiyun switch (op) {
1973*4882a593Smuzhiyun case DEMOD_TIMF_SET:
1974*4882a593Smuzhiyun state->timf = timf;
1975*4882a593Smuzhiyun break;
1976*4882a593Smuzhiyun case DEMOD_TIMF_UPDATE:
1977*4882a593Smuzhiyun dib8000_update_timf(state);
1978*4882a593Smuzhiyun break;
1979*4882a593Smuzhiyun case DEMOD_TIMF_GET:
1980*4882a593Smuzhiyun break;
1981*4882a593Smuzhiyun }
1982*4882a593Smuzhiyun dib8000_set_bandwidth(state->fe[0], 6000);
1983*4882a593Smuzhiyun
1984*4882a593Smuzhiyun return state->timf;
1985*4882a593Smuzhiyun }
1986*4882a593Smuzhiyun
1987*4882a593Smuzhiyun static const u16 adc_target_16dB[11] = {
1988*4882a593Smuzhiyun 7250, 7238, 7264, 7309, 7338, 7382, 7427, 7456, 7500, 7544, 7574
1989*4882a593Smuzhiyun };
1990*4882a593Smuzhiyun
1991*4882a593Smuzhiyun static const u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 };
1992*4882a593Smuzhiyun
dib8000_set_layer(struct dib8000_state * state,u8 layer_index,u16 max_constellation)1993*4882a593Smuzhiyun static u16 dib8000_set_layer(struct dib8000_state *state, u8 layer_index, u16 max_constellation)
1994*4882a593Smuzhiyun {
1995*4882a593Smuzhiyun u8 cr, constellation, time_intlv;
1996*4882a593Smuzhiyun struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
1997*4882a593Smuzhiyun
1998*4882a593Smuzhiyun switch (c->layer[layer_index].modulation) {
1999*4882a593Smuzhiyun case DQPSK:
2000*4882a593Smuzhiyun constellation = 0;
2001*4882a593Smuzhiyun break;
2002*4882a593Smuzhiyun case QPSK:
2003*4882a593Smuzhiyun constellation = 1;
2004*4882a593Smuzhiyun break;
2005*4882a593Smuzhiyun case QAM_16:
2006*4882a593Smuzhiyun constellation = 2;
2007*4882a593Smuzhiyun break;
2008*4882a593Smuzhiyun case QAM_64:
2009*4882a593Smuzhiyun default:
2010*4882a593Smuzhiyun constellation = 3;
2011*4882a593Smuzhiyun break;
2012*4882a593Smuzhiyun }
2013*4882a593Smuzhiyun
2014*4882a593Smuzhiyun switch (c->layer[layer_index].fec) {
2015*4882a593Smuzhiyun case FEC_1_2:
2016*4882a593Smuzhiyun cr = 1;
2017*4882a593Smuzhiyun break;
2018*4882a593Smuzhiyun case FEC_2_3:
2019*4882a593Smuzhiyun cr = 2;
2020*4882a593Smuzhiyun break;
2021*4882a593Smuzhiyun case FEC_3_4:
2022*4882a593Smuzhiyun cr = 3;
2023*4882a593Smuzhiyun break;
2024*4882a593Smuzhiyun case FEC_5_6:
2025*4882a593Smuzhiyun cr = 5;
2026*4882a593Smuzhiyun break;
2027*4882a593Smuzhiyun case FEC_7_8:
2028*4882a593Smuzhiyun default:
2029*4882a593Smuzhiyun cr = 7;
2030*4882a593Smuzhiyun break;
2031*4882a593Smuzhiyun }
2032*4882a593Smuzhiyun
2033*4882a593Smuzhiyun time_intlv = fls(c->layer[layer_index].interleaving);
2034*4882a593Smuzhiyun if (time_intlv > 3 && !(time_intlv == 4 && c->isdbt_sb_mode == 1))
2035*4882a593Smuzhiyun time_intlv = 0;
2036*4882a593Smuzhiyun
2037*4882a593Smuzhiyun dib8000_write_word(state, 2 + layer_index, (constellation << 10) | ((c->layer[layer_index].segment_count & 0xf) << 6) | (cr << 3) | time_intlv);
2038*4882a593Smuzhiyun if (c->layer[layer_index].segment_count > 0) {
2039*4882a593Smuzhiyun switch (max_constellation) {
2040*4882a593Smuzhiyun case DQPSK:
2041*4882a593Smuzhiyun case QPSK:
2042*4882a593Smuzhiyun if (c->layer[layer_index].modulation == QAM_16 || c->layer[layer_index].modulation == QAM_64)
2043*4882a593Smuzhiyun max_constellation = c->layer[layer_index].modulation;
2044*4882a593Smuzhiyun break;
2045*4882a593Smuzhiyun case QAM_16:
2046*4882a593Smuzhiyun if (c->layer[layer_index].modulation == QAM_64)
2047*4882a593Smuzhiyun max_constellation = c->layer[layer_index].modulation;
2048*4882a593Smuzhiyun break;
2049*4882a593Smuzhiyun }
2050*4882a593Smuzhiyun }
2051*4882a593Smuzhiyun
2052*4882a593Smuzhiyun return max_constellation;
2053*4882a593Smuzhiyun }
2054*4882a593Smuzhiyun
2055*4882a593Smuzhiyun static const u16 adp_Q64[4] = {0x0148, 0xfff0, 0x00a4, 0xfff8}; /* P_adp_regul_cnt 0.04, P_adp_noise_cnt -0.002, P_adp_regul_ext 0.02, P_adp_noise_ext -0.001 */
2056*4882a593Smuzhiyun static const u16 adp_Q16[4] = {0x023d, 0xffdf, 0x00a4, 0xfff0}; /* P_adp_regul_cnt 0.07, P_adp_noise_cnt -0.004, P_adp_regul_ext 0.02, P_adp_noise_ext -0.002 */
2057*4882a593Smuzhiyun static const u16 adp_Qdefault[4] = {0x099a, 0xffae, 0x0333, 0xfff8}; /* P_adp_regul_cnt 0.3, P_adp_noise_cnt -0.01, P_adp_regul_ext 0.1, P_adp_noise_ext -0.002 */
dib8000_adp_fine_tune(struct dib8000_state * state,u16 max_constellation)2058*4882a593Smuzhiyun static u16 dib8000_adp_fine_tune(struct dib8000_state *state, u16 max_constellation)
2059*4882a593Smuzhiyun {
2060*4882a593Smuzhiyun u16 i, ana_gain = 0;
2061*4882a593Smuzhiyun const u16 *adp;
2062*4882a593Smuzhiyun
2063*4882a593Smuzhiyun /* channel estimation fine configuration */
2064*4882a593Smuzhiyun switch (max_constellation) {
2065*4882a593Smuzhiyun case QAM_64:
2066*4882a593Smuzhiyun ana_gain = 0x7;
2067*4882a593Smuzhiyun adp = &adp_Q64[0];
2068*4882a593Smuzhiyun break;
2069*4882a593Smuzhiyun case QAM_16:
2070*4882a593Smuzhiyun ana_gain = 0x7;
2071*4882a593Smuzhiyun adp = &adp_Q16[0];
2072*4882a593Smuzhiyun break;
2073*4882a593Smuzhiyun default:
2074*4882a593Smuzhiyun ana_gain = 0;
2075*4882a593Smuzhiyun adp = &adp_Qdefault[0];
2076*4882a593Smuzhiyun break;
2077*4882a593Smuzhiyun }
2078*4882a593Smuzhiyun
2079*4882a593Smuzhiyun for (i = 0; i < 4; i++)
2080*4882a593Smuzhiyun dib8000_write_word(state, 215 + i, adp[i]);
2081*4882a593Smuzhiyun
2082*4882a593Smuzhiyun return ana_gain;
2083*4882a593Smuzhiyun }
2084*4882a593Smuzhiyun
dib8000_update_ana_gain(struct dib8000_state * state,u16 ana_gain)2085*4882a593Smuzhiyun static void dib8000_update_ana_gain(struct dib8000_state *state, u16 ana_gain)
2086*4882a593Smuzhiyun {
2087*4882a593Smuzhiyun u16 i;
2088*4882a593Smuzhiyun
2089*4882a593Smuzhiyun dib8000_write_word(state, 116, ana_gain);
2090*4882a593Smuzhiyun
2091*4882a593Smuzhiyun /* update ADC target depending on ana_gain */
2092*4882a593Smuzhiyun if (ana_gain) { /* set -16dB ADC target for ana_gain=-1 */
2093*4882a593Smuzhiyun for (i = 0; i < 10; i++)
2094*4882a593Smuzhiyun dib8000_write_word(state, 80 + i, adc_target_16dB[i]);
2095*4882a593Smuzhiyun } else { /* set -22dB ADC target for ana_gain=0 */
2096*4882a593Smuzhiyun for (i = 0; i < 10; i++)
2097*4882a593Smuzhiyun dib8000_write_word(state, 80 + i, adc_target_16dB[i] - 355);
2098*4882a593Smuzhiyun }
2099*4882a593Smuzhiyun }
2100*4882a593Smuzhiyun
dib8000_load_ana_fe_coefs(struct dib8000_state * state,const s16 * ana_fe)2101*4882a593Smuzhiyun static void dib8000_load_ana_fe_coefs(struct dib8000_state *state, const s16 *ana_fe)
2102*4882a593Smuzhiyun {
2103*4882a593Smuzhiyun u16 mode = 0;
2104*4882a593Smuzhiyun
2105*4882a593Smuzhiyun if (state->isdbt_cfg_loaded == 0)
2106*4882a593Smuzhiyun for (mode = 0; mode < 24; mode++)
2107*4882a593Smuzhiyun dib8000_write_word(state, 117 + mode, ana_fe[mode]);
2108*4882a593Smuzhiyun }
2109*4882a593Smuzhiyun
2110*4882a593Smuzhiyun static const u16 lut_prbs_2k[13] = {
2111*4882a593Smuzhiyun 0x423, 0x009, 0x5C7,
2112*4882a593Smuzhiyun 0x7A6, 0x3D8, 0x527,
2113*4882a593Smuzhiyun 0x7FF, 0x79B, 0x3D6,
2114*4882a593Smuzhiyun 0x3A2, 0x53B, 0x2F4,
2115*4882a593Smuzhiyun 0x213
2116*4882a593Smuzhiyun };
2117*4882a593Smuzhiyun
2118*4882a593Smuzhiyun static const u16 lut_prbs_4k[13] = {
2119*4882a593Smuzhiyun 0x208, 0x0C3, 0x7B9,
2120*4882a593Smuzhiyun 0x423, 0x5C7, 0x3D8,
2121*4882a593Smuzhiyun 0x7FF, 0x3D6, 0x53B,
2122*4882a593Smuzhiyun 0x213, 0x029, 0x0D0,
2123*4882a593Smuzhiyun 0x48E
2124*4882a593Smuzhiyun };
2125*4882a593Smuzhiyun
2126*4882a593Smuzhiyun static const u16 lut_prbs_8k[13] = {
2127*4882a593Smuzhiyun 0x740, 0x069, 0x7DD,
2128*4882a593Smuzhiyun 0x208, 0x7B9, 0x5C7,
2129*4882a593Smuzhiyun 0x7FF, 0x53B, 0x029,
2130*4882a593Smuzhiyun 0x48E, 0x4C4, 0x367,
2131*4882a593Smuzhiyun 0x684
2132*4882a593Smuzhiyun };
2133*4882a593Smuzhiyun
dib8000_get_init_prbs(struct dib8000_state * state,u16 subchannel)2134*4882a593Smuzhiyun static u16 dib8000_get_init_prbs(struct dib8000_state *state, u16 subchannel)
2135*4882a593Smuzhiyun {
2136*4882a593Smuzhiyun int sub_channel_prbs_group = 0;
2137*4882a593Smuzhiyun int prbs_group;
2138*4882a593Smuzhiyun
2139*4882a593Smuzhiyun sub_channel_prbs_group = subchannel / 3;
2140*4882a593Smuzhiyun if (sub_channel_prbs_group >= ARRAY_SIZE(lut_prbs_2k))
2141*4882a593Smuzhiyun return 0;
2142*4882a593Smuzhiyun
2143*4882a593Smuzhiyun switch (state->fe[0]->dtv_property_cache.transmission_mode) {
2144*4882a593Smuzhiyun case TRANSMISSION_MODE_2K:
2145*4882a593Smuzhiyun prbs_group = lut_prbs_2k[sub_channel_prbs_group];
2146*4882a593Smuzhiyun break;
2147*4882a593Smuzhiyun case TRANSMISSION_MODE_4K:
2148*4882a593Smuzhiyun prbs_group = lut_prbs_4k[sub_channel_prbs_group];
2149*4882a593Smuzhiyun break;
2150*4882a593Smuzhiyun default:
2151*4882a593Smuzhiyun case TRANSMISSION_MODE_8K:
2152*4882a593Smuzhiyun prbs_group = lut_prbs_8k[sub_channel_prbs_group];
2153*4882a593Smuzhiyun }
2154*4882a593Smuzhiyun
2155*4882a593Smuzhiyun dprintk("sub_channel_prbs_group = %d , subchannel =%d prbs = 0x%04x\n",
2156*4882a593Smuzhiyun sub_channel_prbs_group, subchannel, prbs_group);
2157*4882a593Smuzhiyun
2158*4882a593Smuzhiyun return prbs_group;
2159*4882a593Smuzhiyun }
2160*4882a593Smuzhiyun
dib8000_set_13seg_channel(struct dib8000_state * state)2161*4882a593Smuzhiyun static void dib8000_set_13seg_channel(struct dib8000_state *state)
2162*4882a593Smuzhiyun {
2163*4882a593Smuzhiyun u16 i;
2164*4882a593Smuzhiyun u16 coff_pow = 0x2800;
2165*4882a593Smuzhiyun
2166*4882a593Smuzhiyun state->seg_mask = 0x1fff; /* All 13 segments enabled */
2167*4882a593Smuzhiyun
2168*4882a593Smuzhiyun /* ---- COFF ---- Carloff, the most robust --- */
2169*4882a593Smuzhiyun if (state->isdbt_cfg_loaded == 0) { /* if not Sound Broadcasting mode : put default values for 13 segments */
2170*4882a593Smuzhiyun dib8000_write_word(state, 180, (16 << 6) | 9);
2171*4882a593Smuzhiyun dib8000_write_word(state, 187, (4 << 12) | (8 << 5) | 0x2);
2172*4882a593Smuzhiyun coff_pow = 0x2800;
2173*4882a593Smuzhiyun for (i = 0; i < 6; i++)
2174*4882a593Smuzhiyun dib8000_write_word(state, 181+i, coff_pow);
2175*4882a593Smuzhiyun
2176*4882a593Smuzhiyun /* P_ctrl_corm_thres4pre_freq_inh=1, P_ctrl_pre_freq_mode_sat=1 */
2177*4882a593Smuzhiyun /* P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 3, P_pre_freq_win_len=1 */
2178*4882a593Smuzhiyun dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (3 << 5) | 1);
2179*4882a593Smuzhiyun
2180*4882a593Smuzhiyun /* P_ctrl_pre_freq_win_len=8, P_ctrl_pre_freq_thres_lockin=6 */
2181*4882a593Smuzhiyun dib8000_write_word(state, 340, (8 << 6) | (6 << 0));
2182*4882a593Smuzhiyun /* P_ctrl_pre_freq_thres_lockout=4, P_small_use_tmcc/ac/cp=1 */
2183*4882a593Smuzhiyun dib8000_write_word(state, 341, (4 << 3) | (1 << 2) | (1 << 1) | (1 << 0));
2184*4882a593Smuzhiyun
2185*4882a593Smuzhiyun dib8000_write_word(state, 228, 0); /* default value */
2186*4882a593Smuzhiyun dib8000_write_word(state, 265, 31); /* default value */
2187*4882a593Smuzhiyun dib8000_write_word(state, 205, 0x200f); /* init value */
2188*4882a593Smuzhiyun }
2189*4882a593Smuzhiyun
2190*4882a593Smuzhiyun /*
2191*4882a593Smuzhiyun * make the cpil_coff_lock more robust but slower p_coff_winlen
2192*4882a593Smuzhiyun * 6bits; p_coff_thres_lock 6bits (for coff lock if needed)
2193*4882a593Smuzhiyun */
2194*4882a593Smuzhiyun
2195*4882a593Smuzhiyun if (state->cfg.pll->ifreq == 0)
2196*4882a593Smuzhiyun dib8000_write_word(state, 266, ~state->seg_mask | state->seg_diff_mask | 0x40); /* P_equal_noise_seg_inh */
2197*4882a593Smuzhiyun
2198*4882a593Smuzhiyun dib8000_load_ana_fe_coefs(state, ana_fe_coeff_13seg);
2199*4882a593Smuzhiyun }
2200*4882a593Smuzhiyun
dib8000_set_subchannel_prbs(struct dib8000_state * state,u16 init_prbs)2201*4882a593Smuzhiyun static void dib8000_set_subchannel_prbs(struct dib8000_state *state, u16 init_prbs)
2202*4882a593Smuzhiyun {
2203*4882a593Smuzhiyun u16 reg_1;
2204*4882a593Smuzhiyun
2205*4882a593Smuzhiyun reg_1 = dib8000_read_word(state, 1);
2206*4882a593Smuzhiyun dib8000_write_word(state, 1, (init_prbs << 2) | (reg_1 & 0x3)); /* ADDR 1 */
2207*4882a593Smuzhiyun }
2208*4882a593Smuzhiyun
dib8000_small_fine_tune(struct dib8000_state * state)2209*4882a593Smuzhiyun static void dib8000_small_fine_tune(struct dib8000_state *state)
2210*4882a593Smuzhiyun {
2211*4882a593Smuzhiyun u16 i;
2212*4882a593Smuzhiyun const s16 *ncoeff;
2213*4882a593Smuzhiyun struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
2214*4882a593Smuzhiyun
2215*4882a593Smuzhiyun dib8000_write_word(state, 352, state->seg_diff_mask);
2216*4882a593Smuzhiyun dib8000_write_word(state, 353, state->seg_mask);
2217*4882a593Smuzhiyun
2218*4882a593Smuzhiyun /* P_small_coef_ext_enable=ISDB-Tsb, P_small_narrow_band=ISDB-Tsb, P_small_last_seg=13, P_small_offset_num_car=5 */
2219*4882a593Smuzhiyun dib8000_write_word(state, 351, (c->isdbt_sb_mode << 9) | (c->isdbt_sb_mode << 8) | (13 << 4) | 5);
2220*4882a593Smuzhiyun
2221*4882a593Smuzhiyun if (c->isdbt_sb_mode) {
2222*4882a593Smuzhiyun /* ---- SMALL ---- */
2223*4882a593Smuzhiyun switch (c->transmission_mode) {
2224*4882a593Smuzhiyun case TRANSMISSION_MODE_2K:
2225*4882a593Smuzhiyun if (c->isdbt_partial_reception == 0) { /* 1-seg */
2226*4882a593Smuzhiyun if (c->layer[0].modulation == DQPSK) /* DQPSK */
2227*4882a593Smuzhiyun ncoeff = coeff_2k_sb_1seg_dqpsk;
2228*4882a593Smuzhiyun else /* QPSK or QAM */
2229*4882a593Smuzhiyun ncoeff = coeff_2k_sb_1seg;
2230*4882a593Smuzhiyun } else { /* 3-segments */
2231*4882a593Smuzhiyun if (c->layer[0].modulation == DQPSK) { /* DQPSK on central segment */
2232*4882a593Smuzhiyun if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */
2233*4882a593Smuzhiyun ncoeff = coeff_2k_sb_3seg_0dqpsk_1dqpsk;
2234*4882a593Smuzhiyun else /* QPSK or QAM on external segments */
2235*4882a593Smuzhiyun ncoeff = coeff_2k_sb_3seg_0dqpsk;
2236*4882a593Smuzhiyun } else { /* QPSK or QAM on central segment */
2237*4882a593Smuzhiyun if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */
2238*4882a593Smuzhiyun ncoeff = coeff_2k_sb_3seg_1dqpsk;
2239*4882a593Smuzhiyun else /* QPSK or QAM on external segments */
2240*4882a593Smuzhiyun ncoeff = coeff_2k_sb_3seg;
2241*4882a593Smuzhiyun }
2242*4882a593Smuzhiyun }
2243*4882a593Smuzhiyun break;
2244*4882a593Smuzhiyun case TRANSMISSION_MODE_4K:
2245*4882a593Smuzhiyun if (c->isdbt_partial_reception == 0) { /* 1-seg */
2246*4882a593Smuzhiyun if (c->layer[0].modulation == DQPSK) /* DQPSK */
2247*4882a593Smuzhiyun ncoeff = coeff_4k_sb_1seg_dqpsk;
2248*4882a593Smuzhiyun else /* QPSK or QAM */
2249*4882a593Smuzhiyun ncoeff = coeff_4k_sb_1seg;
2250*4882a593Smuzhiyun } else { /* 3-segments */
2251*4882a593Smuzhiyun if (c->layer[0].modulation == DQPSK) { /* DQPSK on central segment */
2252*4882a593Smuzhiyun if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */
2253*4882a593Smuzhiyun ncoeff = coeff_4k_sb_3seg_0dqpsk_1dqpsk;
2254*4882a593Smuzhiyun else /* QPSK or QAM on external segments */
2255*4882a593Smuzhiyun ncoeff = coeff_4k_sb_3seg_0dqpsk;
2256*4882a593Smuzhiyun } else { /* QPSK or QAM on central segment */
2257*4882a593Smuzhiyun if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */
2258*4882a593Smuzhiyun ncoeff = coeff_4k_sb_3seg_1dqpsk;
2259*4882a593Smuzhiyun else /* QPSK or QAM on external segments */
2260*4882a593Smuzhiyun ncoeff = coeff_4k_sb_3seg;
2261*4882a593Smuzhiyun }
2262*4882a593Smuzhiyun }
2263*4882a593Smuzhiyun break;
2264*4882a593Smuzhiyun case TRANSMISSION_MODE_AUTO:
2265*4882a593Smuzhiyun case TRANSMISSION_MODE_8K:
2266*4882a593Smuzhiyun default:
2267*4882a593Smuzhiyun if (c->isdbt_partial_reception == 0) { /* 1-seg */
2268*4882a593Smuzhiyun if (c->layer[0].modulation == DQPSK) /* DQPSK */
2269*4882a593Smuzhiyun ncoeff = coeff_8k_sb_1seg_dqpsk;
2270*4882a593Smuzhiyun else /* QPSK or QAM */
2271*4882a593Smuzhiyun ncoeff = coeff_8k_sb_1seg;
2272*4882a593Smuzhiyun } else { /* 3-segments */
2273*4882a593Smuzhiyun if (c->layer[0].modulation == DQPSK) { /* DQPSK on central segment */
2274*4882a593Smuzhiyun if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */
2275*4882a593Smuzhiyun ncoeff = coeff_8k_sb_3seg_0dqpsk_1dqpsk;
2276*4882a593Smuzhiyun else /* QPSK or QAM on external segments */
2277*4882a593Smuzhiyun ncoeff = coeff_8k_sb_3seg_0dqpsk;
2278*4882a593Smuzhiyun } else { /* QPSK or QAM on central segment */
2279*4882a593Smuzhiyun if (c->layer[1].modulation == DQPSK) /* DQPSK on external segments */
2280*4882a593Smuzhiyun ncoeff = coeff_8k_sb_3seg_1dqpsk;
2281*4882a593Smuzhiyun else /* QPSK or QAM on external segments */
2282*4882a593Smuzhiyun ncoeff = coeff_8k_sb_3seg;
2283*4882a593Smuzhiyun }
2284*4882a593Smuzhiyun }
2285*4882a593Smuzhiyun break;
2286*4882a593Smuzhiyun }
2287*4882a593Smuzhiyun
2288*4882a593Smuzhiyun for (i = 0; i < 8; i++)
2289*4882a593Smuzhiyun dib8000_write_word(state, 343 + i, ncoeff[i]);
2290*4882a593Smuzhiyun }
2291*4882a593Smuzhiyun }
2292*4882a593Smuzhiyun
2293*4882a593Smuzhiyun static const u16 coff_thres_1seg[3] = {300, 150, 80};
2294*4882a593Smuzhiyun static const u16 coff_thres_3seg[3] = {350, 300, 250};
dib8000_set_sb_channel(struct dib8000_state * state)2295*4882a593Smuzhiyun static void dib8000_set_sb_channel(struct dib8000_state *state)
2296*4882a593Smuzhiyun {
2297*4882a593Smuzhiyun struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
2298*4882a593Smuzhiyun const u16 *coff;
2299*4882a593Smuzhiyun u16 i;
2300*4882a593Smuzhiyun
2301*4882a593Smuzhiyun if (c->transmission_mode == TRANSMISSION_MODE_2K || c->transmission_mode == TRANSMISSION_MODE_4K) {
2302*4882a593Smuzhiyun dib8000_write_word(state, 219, dib8000_read_word(state, 219) | 0x1); /* adp_pass =1 */
2303*4882a593Smuzhiyun dib8000_write_word(state, 190, dib8000_read_word(state, 190) | (0x1 << 14)); /* pha3_force_pha_shift = 1 */
2304*4882a593Smuzhiyun } else {
2305*4882a593Smuzhiyun dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe); /* adp_pass =0 */
2306*4882a593Smuzhiyun dib8000_write_word(state, 190, dib8000_read_word(state, 190) & 0xbfff); /* pha3_force_pha_shift = 0 */
2307*4882a593Smuzhiyun }
2308*4882a593Smuzhiyun
2309*4882a593Smuzhiyun if (c->isdbt_partial_reception == 1) /* 3-segments */
2310*4882a593Smuzhiyun state->seg_mask = 0x00E0;
2311*4882a593Smuzhiyun else /* 1-segment */
2312*4882a593Smuzhiyun state->seg_mask = 0x0040;
2313*4882a593Smuzhiyun
2314*4882a593Smuzhiyun dib8000_write_word(state, 268, (dib8000_read_word(state, 268) & 0xF9FF) | 0x0200);
2315*4882a593Smuzhiyun
2316*4882a593Smuzhiyun /* ---- COFF ---- Carloff, the most robust --- */
2317*4882a593Smuzhiyun /* P_coff_cpil_alpha=4, P_coff_inh=0, P_coff_cpil_winlen=64, P_coff_narrow_band=1, P_coff_square_val=1, P_coff_one_seg=~partial_rcpt, P_coff_use_tmcc=1, P_coff_use_ac=1 */
2318*4882a593Smuzhiyun dib8000_write_word(state, 187, (4 << 12) | (0 << 11) | (63 << 5) | (0x3 << 3) | ((~c->isdbt_partial_reception & 1) << 2) | 0x3);
2319*4882a593Smuzhiyun
2320*4882a593Smuzhiyun dib8000_write_word(state, 340, (16 << 6) | (8 << 0)); /* P_ctrl_pre_freq_win_len=16, P_ctrl_pre_freq_thres_lockin=8 */
2321*4882a593Smuzhiyun dib8000_write_word(state, 341, (6 << 3) | (1 << 2) | (1 << 1) | (1 << 0));/* P_ctrl_pre_freq_thres_lockout=6, P_small_use_tmcc/ac/cp=1 */
2322*4882a593Smuzhiyun
2323*4882a593Smuzhiyun /* Sound Broadcasting mode 1 seg */
2324*4882a593Smuzhiyun if (c->isdbt_partial_reception == 0) {
2325*4882a593Smuzhiyun /* P_coff_winlen=63, P_coff_thres_lock=15, P_coff_one_seg_width = (P_mode == 3) , P_coff_one_seg_sym = (P_mode-1) */
2326*4882a593Smuzhiyun if (state->mode == 3)
2327*4882a593Smuzhiyun dib8000_write_word(state, 180, 0x1fcf | ((state->mode - 1) << 14));
2328*4882a593Smuzhiyun else
2329*4882a593Smuzhiyun dib8000_write_word(state, 180, 0x0fcf | ((state->mode - 1) << 14));
2330*4882a593Smuzhiyun
2331*4882a593Smuzhiyun /* P_ctrl_corm_thres4pre_freq_inh=1,P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 5, P_pre_freq_win_len=4 */
2332*4882a593Smuzhiyun dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (5 << 5) | 4);
2333*4882a593Smuzhiyun coff = &coff_thres_1seg[0];
2334*4882a593Smuzhiyun } else { /* Sound Broadcasting mode 3 seg */
2335*4882a593Smuzhiyun dib8000_write_word(state, 180, 0x1fcf | (1 << 14));
2336*4882a593Smuzhiyun /* P_ctrl_corm_thres4pre_freq_inh = 1, P_ctrl_pre_freq_mode_sat=1, P_ctrl_pre_freq_inh=0, P_ctrl_pre_freq_step = 4, P_pre_freq_win_len=4 */
2337*4882a593Smuzhiyun dib8000_write_word(state, 338, (1 << 12) | (1 << 10) | (0 << 9) | (4 << 5) | 4);
2338*4882a593Smuzhiyun coff = &coff_thres_3seg[0];
2339*4882a593Smuzhiyun }
2340*4882a593Smuzhiyun
2341*4882a593Smuzhiyun dib8000_write_word(state, 228, 1); /* P_2d_mode_byp=1 */
2342*4882a593Smuzhiyun dib8000_write_word(state, 205, dib8000_read_word(state, 205) & 0xfff0); /* P_cspu_win_cut = 0 */
2343*4882a593Smuzhiyun
2344*4882a593Smuzhiyun if (c->isdbt_partial_reception == 0 && c->transmission_mode == TRANSMISSION_MODE_2K)
2345*4882a593Smuzhiyun dib8000_write_word(state, 265, 15); /* P_equal_noise_sel = 15 */
2346*4882a593Smuzhiyun
2347*4882a593Smuzhiyun /* Write COFF thres */
2348*4882a593Smuzhiyun for (i = 0 ; i < 3; i++) {
2349*4882a593Smuzhiyun dib8000_write_word(state, 181+i, coff[i]);
2350*4882a593Smuzhiyun dib8000_write_word(state, 184+i, coff[i]);
2351*4882a593Smuzhiyun }
2352*4882a593Smuzhiyun
2353*4882a593Smuzhiyun /*
2354*4882a593Smuzhiyun * make the cpil_coff_lock more robust but slower p_coff_winlen
2355*4882a593Smuzhiyun * 6bits; p_coff_thres_lock 6bits (for coff lock if needed)
2356*4882a593Smuzhiyun */
2357*4882a593Smuzhiyun
2358*4882a593Smuzhiyun dib8000_write_word(state, 266, ~state->seg_mask | state->seg_diff_mask); /* P_equal_noise_seg_inh */
2359*4882a593Smuzhiyun
2360*4882a593Smuzhiyun if (c->isdbt_partial_reception == 0)
2361*4882a593Smuzhiyun dib8000_write_word(state, 178, 64); /* P_fft_powrange = 64 */
2362*4882a593Smuzhiyun else
2363*4882a593Smuzhiyun dib8000_write_word(state, 178, 32); /* P_fft_powrange = 32 */
2364*4882a593Smuzhiyun }
2365*4882a593Smuzhiyun
dib8000_set_isdbt_common_channel(struct dib8000_state * state,u8 seq,u8 autosearching)2366*4882a593Smuzhiyun static void dib8000_set_isdbt_common_channel(struct dib8000_state *state, u8 seq, u8 autosearching)
2367*4882a593Smuzhiyun {
2368*4882a593Smuzhiyun u16 p_cfr_left_edge = 0, p_cfr_right_edge = 0;
2369*4882a593Smuzhiyun u16 tmcc_pow = 0, ana_gain = 0, tmp = 0, i = 0, nbseg_diff = 0 ;
2370*4882a593Smuzhiyun u16 max_constellation = DQPSK;
2371*4882a593Smuzhiyun int init_prbs;
2372*4882a593Smuzhiyun struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
2373*4882a593Smuzhiyun
2374*4882a593Smuzhiyun if (autosearching)
2375*4882a593Smuzhiyun c->isdbt_partial_reception = 1;
2376*4882a593Smuzhiyun
2377*4882a593Smuzhiyun /* P_mode */
2378*4882a593Smuzhiyun dib8000_write_word(state, 10, (seq << 4));
2379*4882a593Smuzhiyun
2380*4882a593Smuzhiyun /* init mode */
2381*4882a593Smuzhiyun state->mode = fft_to_mode(state);
2382*4882a593Smuzhiyun
2383*4882a593Smuzhiyun /* set guard */
2384*4882a593Smuzhiyun tmp = dib8000_read_word(state, 1);
2385*4882a593Smuzhiyun dib8000_write_word(state, 1, (tmp&0xfffc) | (c->guard_interval & 0x3));
2386*4882a593Smuzhiyun
2387*4882a593Smuzhiyun dib8000_write_word(state, 274, (dib8000_read_word(state, 274) & 0xffcf) | ((c->isdbt_partial_reception & 1) << 5) | ((c->isdbt_sb_mode & 1) << 4));
2388*4882a593Smuzhiyun
2389*4882a593Smuzhiyun /* signal optimization parameter */
2390*4882a593Smuzhiyun if (c->isdbt_partial_reception) {
2391*4882a593Smuzhiyun state->seg_diff_mask = (c->layer[0].modulation == DQPSK) << permu_seg[0];
2392*4882a593Smuzhiyun for (i = 1; i < 3; i++)
2393*4882a593Smuzhiyun nbseg_diff += (c->layer[i].modulation == DQPSK) * c->layer[i].segment_count;
2394*4882a593Smuzhiyun for (i = 0; i < nbseg_diff; i++)
2395*4882a593Smuzhiyun state->seg_diff_mask |= 1 << permu_seg[i+1];
2396*4882a593Smuzhiyun } else {
2397*4882a593Smuzhiyun for (i = 0; i < 3; i++)
2398*4882a593Smuzhiyun nbseg_diff += (c->layer[i].modulation == DQPSK) * c->layer[i].segment_count;
2399*4882a593Smuzhiyun for (i = 0; i < nbseg_diff; i++)
2400*4882a593Smuzhiyun state->seg_diff_mask |= 1 << permu_seg[i];
2401*4882a593Smuzhiyun }
2402*4882a593Smuzhiyun
2403*4882a593Smuzhiyun if (state->seg_diff_mask)
2404*4882a593Smuzhiyun dib8000_write_word(state, 268, (dib8000_read_word(state, 268) & 0xF9FF) | 0x0200);
2405*4882a593Smuzhiyun else
2406*4882a593Smuzhiyun dib8000_write_word(state, 268, (2 << 9) | 39); /*init value */
2407*4882a593Smuzhiyun
2408*4882a593Smuzhiyun for (i = 0; i < 3; i++)
2409*4882a593Smuzhiyun max_constellation = dib8000_set_layer(state, i, max_constellation);
2410*4882a593Smuzhiyun if (autosearching == 0) {
2411*4882a593Smuzhiyun state->layer_b_nb_seg = c->layer[1].segment_count;
2412*4882a593Smuzhiyun state->layer_c_nb_seg = c->layer[2].segment_count;
2413*4882a593Smuzhiyun }
2414*4882a593Smuzhiyun
2415*4882a593Smuzhiyun /* WRITE: Mode & Diff mask */
2416*4882a593Smuzhiyun dib8000_write_word(state, 0, (state->mode << 13) | state->seg_diff_mask);
2417*4882a593Smuzhiyun
2418*4882a593Smuzhiyun state->differential_constellation = (state->seg_diff_mask != 0);
2419*4882a593Smuzhiyun
2420*4882a593Smuzhiyun /* channel estimation fine configuration */
2421*4882a593Smuzhiyun ana_gain = dib8000_adp_fine_tune(state, max_constellation);
2422*4882a593Smuzhiyun
2423*4882a593Smuzhiyun /* update ana_gain depending on max constellation */
2424*4882a593Smuzhiyun dib8000_update_ana_gain(state, ana_gain);
2425*4882a593Smuzhiyun
2426*4882a593Smuzhiyun /* ---- ANA_FE ---- */
2427*4882a593Smuzhiyun if (c->isdbt_partial_reception) /* 3-segments */
2428*4882a593Smuzhiyun dib8000_load_ana_fe_coefs(state, ana_fe_coeff_3seg);
2429*4882a593Smuzhiyun else
2430*4882a593Smuzhiyun dib8000_load_ana_fe_coefs(state, ana_fe_coeff_1seg); /* 1-segment */
2431*4882a593Smuzhiyun
2432*4882a593Smuzhiyun /* TSB or ISDBT ? apply it now */
2433*4882a593Smuzhiyun if (c->isdbt_sb_mode) {
2434*4882a593Smuzhiyun dib8000_set_sb_channel(state);
2435*4882a593Smuzhiyun init_prbs = dib8000_get_init_prbs(state,
2436*4882a593Smuzhiyun c->isdbt_sb_subchannel);
2437*4882a593Smuzhiyun } else {
2438*4882a593Smuzhiyun dib8000_set_13seg_channel(state);
2439*4882a593Smuzhiyun init_prbs = 0xfff;
2440*4882a593Smuzhiyun }
2441*4882a593Smuzhiyun
2442*4882a593Smuzhiyun /* SMALL */
2443*4882a593Smuzhiyun dib8000_small_fine_tune(state);
2444*4882a593Smuzhiyun
2445*4882a593Smuzhiyun dib8000_set_subchannel_prbs(state, init_prbs);
2446*4882a593Smuzhiyun
2447*4882a593Smuzhiyun /* ---- CHAN_BLK ---- */
2448*4882a593Smuzhiyun for (i = 0; i < 13; i++) {
2449*4882a593Smuzhiyun if ((((~state->seg_diff_mask) >> i) & 1) == 1) {
2450*4882a593Smuzhiyun p_cfr_left_edge += (1 << i) * ((i == 0) || ((((state->seg_mask & (~state->seg_diff_mask)) >> (i - 1)) & 1) == 0));
2451*4882a593Smuzhiyun p_cfr_right_edge += (1 << i) * ((i == 12) || ((((state->seg_mask & (~state->seg_diff_mask)) >> (i + 1)) & 1) == 0));
2452*4882a593Smuzhiyun }
2453*4882a593Smuzhiyun }
2454*4882a593Smuzhiyun dib8000_write_word(state, 222, p_cfr_left_edge); /* p_cfr_left_edge */
2455*4882a593Smuzhiyun dib8000_write_word(state, 223, p_cfr_right_edge); /* p_cfr_right_edge */
2456*4882a593Smuzhiyun /* "P_cspu_left_edge" & "P_cspu_right_edge" not used => do not care */
2457*4882a593Smuzhiyun
2458*4882a593Smuzhiyun dib8000_write_word(state, 189, ~state->seg_mask | state->seg_diff_mask); /* P_lmod4_seg_inh */
2459*4882a593Smuzhiyun dib8000_write_word(state, 192, ~state->seg_mask | state->seg_diff_mask); /* P_pha3_seg_inh */
2460*4882a593Smuzhiyun dib8000_write_word(state, 225, ~state->seg_mask | state->seg_diff_mask); /* P_tac_seg_inh */
2461*4882a593Smuzhiyun
2462*4882a593Smuzhiyun if (!autosearching)
2463*4882a593Smuzhiyun dib8000_write_word(state, 288, (~state->seg_mask | state->seg_diff_mask) & 0x1fff); /* P_tmcc_seg_eq_inh */
2464*4882a593Smuzhiyun else
2465*4882a593Smuzhiyun dib8000_write_word(state, 288, 0x1fff); /*disable equalisation of the tmcc when autosearch to be able to find the DQPSK channels. */
2466*4882a593Smuzhiyun
2467*4882a593Smuzhiyun dib8000_write_word(state, 211, state->seg_mask & (~state->seg_diff_mask)); /* P_des_seg_enabled */
2468*4882a593Smuzhiyun dib8000_write_word(state, 287, ~state->seg_mask | 0x1000); /* P_tmcc_seg_inh */
2469*4882a593Smuzhiyun
2470*4882a593Smuzhiyun dib8000_write_word(state, 178, 32); /* P_fft_powrange = 32 */
2471*4882a593Smuzhiyun
2472*4882a593Smuzhiyun /* ---- TMCC ---- */
2473*4882a593Smuzhiyun for (i = 0; i < 3; i++)
2474*4882a593Smuzhiyun tmcc_pow += (((c->layer[i].modulation == DQPSK) * 4 + 1) * c->layer[i].segment_count) ;
2475*4882a593Smuzhiyun
2476*4882a593Smuzhiyun /* Quantif of "P_tmcc_dec_thres_?k" is (0, 5+mode, 9); */
2477*4882a593Smuzhiyun /* Threshold is set at 1/4 of max power. */
2478*4882a593Smuzhiyun tmcc_pow *= (1 << (9-2));
2479*4882a593Smuzhiyun dib8000_write_word(state, 290, tmcc_pow); /* P_tmcc_dec_thres_2k */
2480*4882a593Smuzhiyun dib8000_write_word(state, 291, tmcc_pow); /* P_tmcc_dec_thres_4k */
2481*4882a593Smuzhiyun dib8000_write_word(state, 292, tmcc_pow); /* P_tmcc_dec_thres_8k */
2482*4882a593Smuzhiyun /*dib8000_write_word(state, 287, (1 << 13) | 0x1000 ); */
2483*4882a593Smuzhiyun
2484*4882a593Smuzhiyun /* ---- PHA3 ---- */
2485*4882a593Smuzhiyun if (state->isdbt_cfg_loaded == 0)
2486*4882a593Smuzhiyun dib8000_write_word(state, 250, 3285); /* p_2d_hspeed_thr0 */
2487*4882a593Smuzhiyun
2488*4882a593Smuzhiyun state->isdbt_cfg_loaded = 0;
2489*4882a593Smuzhiyun }
2490*4882a593Smuzhiyun
dib8000_wait_lock(struct dib8000_state * state,u32 internal,u32 wait0_ms,u32 wait1_ms,u32 wait2_ms)2491*4882a593Smuzhiyun static u32 dib8000_wait_lock(struct dib8000_state *state, u32 internal,
2492*4882a593Smuzhiyun u32 wait0_ms, u32 wait1_ms, u32 wait2_ms)
2493*4882a593Smuzhiyun {
2494*4882a593Smuzhiyun u32 value = 0; /* P_search_end0 wait time */
2495*4882a593Smuzhiyun u16 reg = 11; /* P_search_end0 start addr */
2496*4882a593Smuzhiyun
2497*4882a593Smuzhiyun for (reg = 11; reg < 16; reg += 2) {
2498*4882a593Smuzhiyun if (reg == 11) {
2499*4882a593Smuzhiyun if (state->revision == 0x8090)
2500*4882a593Smuzhiyun value = internal * wait1_ms;
2501*4882a593Smuzhiyun else
2502*4882a593Smuzhiyun value = internal * wait0_ms;
2503*4882a593Smuzhiyun } else if (reg == 13)
2504*4882a593Smuzhiyun value = internal * wait1_ms;
2505*4882a593Smuzhiyun else if (reg == 15)
2506*4882a593Smuzhiyun value = internal * wait2_ms;
2507*4882a593Smuzhiyun dib8000_write_word(state, reg, (u16)((value >> 16) & 0xffff));
2508*4882a593Smuzhiyun dib8000_write_word(state, (reg + 1), (u16)(value & 0xffff));
2509*4882a593Smuzhiyun }
2510*4882a593Smuzhiyun return value;
2511*4882a593Smuzhiyun }
2512*4882a593Smuzhiyun
dib8000_autosearch_start(struct dvb_frontend * fe)2513*4882a593Smuzhiyun static int dib8000_autosearch_start(struct dvb_frontend *fe)
2514*4882a593Smuzhiyun {
2515*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
2516*4882a593Smuzhiyun struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
2517*4882a593Smuzhiyun u8 slist = 0;
2518*4882a593Smuzhiyun u32 value, internal = state->cfg.pll->internal;
2519*4882a593Smuzhiyun
2520*4882a593Smuzhiyun if (state->revision == 0x8090)
2521*4882a593Smuzhiyun internal = dib8000_read32(state, 23) / 1000;
2522*4882a593Smuzhiyun
2523*4882a593Smuzhiyun if ((state->revision >= 0x8002) &&
2524*4882a593Smuzhiyun (state->autosearch_state == AS_SEARCHING_FFT)) {
2525*4882a593Smuzhiyun dib8000_write_word(state, 37, 0x0065); /* P_ctrl_pha_off_max default values */
2526*4882a593Smuzhiyun dib8000_write_word(state, 116, 0x0000); /* P_ana_gain to 0 */
2527*4882a593Smuzhiyun
2528*4882a593Smuzhiyun dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x1fff) | (0 << 13) | (1 << 15)); /* P_mode = 0, P_restart_search=1 */
2529*4882a593Smuzhiyun dib8000_write_word(state, 1, (dib8000_read_word(state, 1) & 0xfffc) | 0); /* P_guard = 0 */
2530*4882a593Smuzhiyun dib8000_write_word(state, 6, 0); /* P_lock0_mask = 0 */
2531*4882a593Smuzhiyun dib8000_write_word(state, 7, 0); /* P_lock1_mask = 0 */
2532*4882a593Smuzhiyun dib8000_write_word(state, 8, 0); /* P_lock2_mask = 0 */
2533*4882a593Smuzhiyun dib8000_write_word(state, 10, (dib8000_read_word(state, 10) & 0x200) | (16 << 4) | (0 << 0)); /* P_search_list=16, P_search_maxtrial=0 */
2534*4882a593Smuzhiyun
2535*4882a593Smuzhiyun if (state->revision == 0x8090)
2536*4882a593Smuzhiyun value = dib8000_wait_lock(state, internal, 10, 10, 10); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
2537*4882a593Smuzhiyun else
2538*4882a593Smuzhiyun value = dib8000_wait_lock(state, internal, 20, 20, 20); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
2539*4882a593Smuzhiyun
2540*4882a593Smuzhiyun dib8000_write_word(state, 17, 0);
2541*4882a593Smuzhiyun dib8000_write_word(state, 18, 200); /* P_search_rstst = 200 */
2542*4882a593Smuzhiyun dib8000_write_word(state, 19, 0);
2543*4882a593Smuzhiyun dib8000_write_word(state, 20, 400); /* P_search_rstend = 400 */
2544*4882a593Smuzhiyun dib8000_write_word(state, 21, (value >> 16) & 0xffff); /* P_search_checkst */
2545*4882a593Smuzhiyun dib8000_write_word(state, 22, value & 0xffff);
2546*4882a593Smuzhiyun
2547*4882a593Smuzhiyun if (state->revision == 0x8090)
2548*4882a593Smuzhiyun dib8000_write_word(state, 32, (dib8000_read_word(state, 32) & 0xf0ff) | (0 << 8)); /* P_corm_alpha = 0 */
2549*4882a593Smuzhiyun else
2550*4882a593Smuzhiyun dib8000_write_word(state, 32, (dib8000_read_word(state, 32) & 0xf0ff) | (9 << 8)); /* P_corm_alpha = 3 */
2551*4882a593Smuzhiyun dib8000_write_word(state, 355, 2); /* P_search_param_max = 2 */
2552*4882a593Smuzhiyun
2553*4882a593Smuzhiyun /* P_search_param_select = (1 | 1<<4 | 1 << 8) */
2554*4882a593Smuzhiyun dib8000_write_word(state, 356, 0);
2555*4882a593Smuzhiyun dib8000_write_word(state, 357, 0x111);
2556*4882a593Smuzhiyun
2557*4882a593Smuzhiyun dib8000_write_word(state, 770, (dib8000_read_word(state, 770) & 0xdfff) | (1 << 13)); /* P_restart_ccg = 1 */
2558*4882a593Smuzhiyun dib8000_write_word(state, 770, (dib8000_read_word(state, 770) & 0xdfff) | (0 << 13)); /* P_restart_ccg = 0 */
2559*4882a593Smuzhiyun dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x7ff) | (0 << 15) | (1 << 13)); /* P_restart_search = 0; */
2560*4882a593Smuzhiyun } else if ((state->revision >= 0x8002) &&
2561*4882a593Smuzhiyun (state->autosearch_state == AS_SEARCHING_GUARD)) {
2562*4882a593Smuzhiyun c->transmission_mode = TRANSMISSION_MODE_8K;
2563*4882a593Smuzhiyun c->guard_interval = GUARD_INTERVAL_1_8;
2564*4882a593Smuzhiyun c->inversion = 0;
2565*4882a593Smuzhiyun c->layer[0].modulation = QAM_64;
2566*4882a593Smuzhiyun c->layer[0].fec = FEC_2_3;
2567*4882a593Smuzhiyun c->layer[0].interleaving = 0;
2568*4882a593Smuzhiyun c->layer[0].segment_count = 13;
2569*4882a593Smuzhiyun
2570*4882a593Smuzhiyun slist = 16;
2571*4882a593Smuzhiyun c->transmission_mode = state->found_nfft;
2572*4882a593Smuzhiyun
2573*4882a593Smuzhiyun dib8000_set_isdbt_common_channel(state, slist, 1);
2574*4882a593Smuzhiyun
2575*4882a593Smuzhiyun /* set lock_mask values */
2576*4882a593Smuzhiyun dib8000_write_word(state, 6, 0x4);
2577*4882a593Smuzhiyun if (state->revision == 0x8090)
2578*4882a593Smuzhiyun dib8000_write_word(state, 7, ((1 << 12) | (1 << 11) | (1 << 10)));/* tmcc_dec_lock, tmcc_sync_lock, tmcc_data_lock, tmcc_bch_uncor */
2579*4882a593Smuzhiyun else
2580*4882a593Smuzhiyun dib8000_write_word(state, 7, 0x8);
2581*4882a593Smuzhiyun dib8000_write_word(state, 8, 0x1000);
2582*4882a593Smuzhiyun
2583*4882a593Smuzhiyun /* set lock_mask wait time values */
2584*4882a593Smuzhiyun if (state->revision == 0x8090)
2585*4882a593Smuzhiyun dib8000_wait_lock(state, internal, 50, 100, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
2586*4882a593Smuzhiyun else
2587*4882a593Smuzhiyun dib8000_wait_lock(state, internal, 50, 200, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
2588*4882a593Smuzhiyun
2589*4882a593Smuzhiyun dib8000_write_word(state, 355, 3); /* P_search_param_max = 3 */
2590*4882a593Smuzhiyun
2591*4882a593Smuzhiyun /* P_search_param_select = 0xf; look for the 4 different guard intervals */
2592*4882a593Smuzhiyun dib8000_write_word(state, 356, 0);
2593*4882a593Smuzhiyun dib8000_write_word(state, 357, 0xf);
2594*4882a593Smuzhiyun
2595*4882a593Smuzhiyun value = dib8000_read_word(state, 0);
2596*4882a593Smuzhiyun dib8000_write_word(state, 0, (u16)((1 << 15) | value));
2597*4882a593Smuzhiyun dib8000_read_word(state, 1284); /* reset the INT. n_irq_pending */
2598*4882a593Smuzhiyun dib8000_write_word(state, 0, (u16)value);
2599*4882a593Smuzhiyun } else {
2600*4882a593Smuzhiyun c->inversion = 0;
2601*4882a593Smuzhiyun c->layer[0].modulation = QAM_64;
2602*4882a593Smuzhiyun c->layer[0].fec = FEC_2_3;
2603*4882a593Smuzhiyun c->layer[0].interleaving = 0;
2604*4882a593Smuzhiyun c->layer[0].segment_count = 13;
2605*4882a593Smuzhiyun if (!c->isdbt_sb_mode)
2606*4882a593Smuzhiyun c->layer[0].segment_count = 13;
2607*4882a593Smuzhiyun
2608*4882a593Smuzhiyun /* choose the right list, in sb, always do everything */
2609*4882a593Smuzhiyun if (c->isdbt_sb_mode) {
2610*4882a593Smuzhiyun slist = 7;
2611*4882a593Smuzhiyun dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13));
2612*4882a593Smuzhiyun } else {
2613*4882a593Smuzhiyun if (c->guard_interval == GUARD_INTERVAL_AUTO) {
2614*4882a593Smuzhiyun if (c->transmission_mode == TRANSMISSION_MODE_AUTO) {
2615*4882a593Smuzhiyun c->transmission_mode = TRANSMISSION_MODE_8K;
2616*4882a593Smuzhiyun c->guard_interval = GUARD_INTERVAL_1_8;
2617*4882a593Smuzhiyun slist = 7;
2618*4882a593Smuzhiyun dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); /* P_mode = 1 to have autosearch start ok with mode2 */
2619*4882a593Smuzhiyun } else {
2620*4882a593Smuzhiyun c->guard_interval = GUARD_INTERVAL_1_8;
2621*4882a593Smuzhiyun slist = 3;
2622*4882a593Smuzhiyun }
2623*4882a593Smuzhiyun } else {
2624*4882a593Smuzhiyun if (c->transmission_mode == TRANSMISSION_MODE_AUTO) {
2625*4882a593Smuzhiyun c->transmission_mode = TRANSMISSION_MODE_8K;
2626*4882a593Smuzhiyun slist = 2;
2627*4882a593Smuzhiyun dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13)); /* P_mode = 1 */
2628*4882a593Smuzhiyun } else
2629*4882a593Smuzhiyun slist = 0;
2630*4882a593Smuzhiyun }
2631*4882a593Smuzhiyun }
2632*4882a593Smuzhiyun dprintk("Using list for autosearch : %d\n", slist);
2633*4882a593Smuzhiyun
2634*4882a593Smuzhiyun dib8000_set_isdbt_common_channel(state, slist, 1);
2635*4882a593Smuzhiyun
2636*4882a593Smuzhiyun /* set lock_mask values */
2637*4882a593Smuzhiyun dib8000_write_word(state, 6, 0x4);
2638*4882a593Smuzhiyun if (state->revision == 0x8090)
2639*4882a593Smuzhiyun dib8000_write_word(state, 7, (1 << 12) | (1 << 11) | (1 << 10));
2640*4882a593Smuzhiyun else
2641*4882a593Smuzhiyun dib8000_write_word(state, 7, 0x8);
2642*4882a593Smuzhiyun dib8000_write_word(state, 8, 0x1000);
2643*4882a593Smuzhiyun
2644*4882a593Smuzhiyun /* set lock_mask wait time values */
2645*4882a593Smuzhiyun if (state->revision == 0x8090)
2646*4882a593Smuzhiyun dib8000_wait_lock(state, internal, 50, 200, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
2647*4882a593Smuzhiyun else
2648*4882a593Smuzhiyun dib8000_wait_lock(state, internal, 50, 100, 1000); /* time in ms configure P_search_end0 P_search_end1 P_search_end2 */
2649*4882a593Smuzhiyun
2650*4882a593Smuzhiyun value = dib8000_read_word(state, 0);
2651*4882a593Smuzhiyun dib8000_write_word(state, 0, (u16)((1 << 15) | value));
2652*4882a593Smuzhiyun dib8000_read_word(state, 1284); /* reset the INT. n_irq_pending */
2653*4882a593Smuzhiyun dib8000_write_word(state, 0, (u16)value);
2654*4882a593Smuzhiyun }
2655*4882a593Smuzhiyun return 0;
2656*4882a593Smuzhiyun }
2657*4882a593Smuzhiyun
dib8000_autosearch_irq(struct dvb_frontend * fe)2658*4882a593Smuzhiyun static int dib8000_autosearch_irq(struct dvb_frontend *fe)
2659*4882a593Smuzhiyun {
2660*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
2661*4882a593Smuzhiyun u16 irq_pending = dib8000_read_word(state, 1284);
2662*4882a593Smuzhiyun
2663*4882a593Smuzhiyun if ((state->revision >= 0x8002) &&
2664*4882a593Smuzhiyun (state->autosearch_state == AS_SEARCHING_FFT)) {
2665*4882a593Smuzhiyun if (irq_pending & 0x1) {
2666*4882a593Smuzhiyun dprintk("dib8000_autosearch_irq: max correlation result available\n");
2667*4882a593Smuzhiyun return 3;
2668*4882a593Smuzhiyun }
2669*4882a593Smuzhiyun } else {
2670*4882a593Smuzhiyun if (irq_pending & 0x1) { /* failed */
2671*4882a593Smuzhiyun dprintk("dib8000_autosearch_irq failed\n");
2672*4882a593Smuzhiyun return 1;
2673*4882a593Smuzhiyun }
2674*4882a593Smuzhiyun
2675*4882a593Smuzhiyun if (irq_pending & 0x2) { /* succeeded */
2676*4882a593Smuzhiyun dprintk("dib8000_autosearch_irq succeeded\n");
2677*4882a593Smuzhiyun return 2;
2678*4882a593Smuzhiyun }
2679*4882a593Smuzhiyun }
2680*4882a593Smuzhiyun
2681*4882a593Smuzhiyun return 0; // still pending
2682*4882a593Smuzhiyun }
2683*4882a593Smuzhiyun
dib8000_viterbi_state(struct dib8000_state * state,u8 onoff)2684*4882a593Smuzhiyun static void dib8000_viterbi_state(struct dib8000_state *state, u8 onoff)
2685*4882a593Smuzhiyun {
2686*4882a593Smuzhiyun u16 tmp;
2687*4882a593Smuzhiyun
2688*4882a593Smuzhiyun tmp = dib8000_read_word(state, 771);
2689*4882a593Smuzhiyun if (onoff) /* start P_restart_chd : channel_decoder */
2690*4882a593Smuzhiyun dib8000_write_word(state, 771, tmp & 0xfffd);
2691*4882a593Smuzhiyun else /* stop P_restart_chd : channel_decoder */
2692*4882a593Smuzhiyun dib8000_write_word(state, 771, tmp | (1<<1));
2693*4882a593Smuzhiyun }
2694*4882a593Smuzhiyun
dib8000_set_dds(struct dib8000_state * state,s32 offset_khz)2695*4882a593Smuzhiyun static void dib8000_set_dds(struct dib8000_state *state, s32 offset_khz)
2696*4882a593Smuzhiyun {
2697*4882a593Smuzhiyun s16 unit_khz_dds_val;
2698*4882a593Smuzhiyun u32 abs_offset_khz = abs(offset_khz);
2699*4882a593Smuzhiyun u32 dds = state->cfg.pll->ifreq & 0x1ffffff;
2700*4882a593Smuzhiyun u8 invert = !!(state->cfg.pll->ifreq & (1 << 25));
2701*4882a593Smuzhiyun u8 ratio;
2702*4882a593Smuzhiyun
2703*4882a593Smuzhiyun if (state->revision == 0x8090) {
2704*4882a593Smuzhiyun ratio = 4;
2705*4882a593Smuzhiyun unit_khz_dds_val = (1<<26) / (dib8000_read32(state, 23) / 1000);
2706*4882a593Smuzhiyun if (offset_khz < 0)
2707*4882a593Smuzhiyun dds = (1 << 26) - (abs_offset_khz * unit_khz_dds_val);
2708*4882a593Smuzhiyun else
2709*4882a593Smuzhiyun dds = (abs_offset_khz * unit_khz_dds_val);
2710*4882a593Smuzhiyun
2711*4882a593Smuzhiyun if (invert)
2712*4882a593Smuzhiyun dds = (1<<26) - dds;
2713*4882a593Smuzhiyun } else {
2714*4882a593Smuzhiyun ratio = 2;
2715*4882a593Smuzhiyun unit_khz_dds_val = (u16) (67108864 / state->cfg.pll->internal);
2716*4882a593Smuzhiyun
2717*4882a593Smuzhiyun if (offset_khz < 0)
2718*4882a593Smuzhiyun unit_khz_dds_val *= -1;
2719*4882a593Smuzhiyun
2720*4882a593Smuzhiyun /* IF tuner */
2721*4882a593Smuzhiyun if (invert)
2722*4882a593Smuzhiyun dds -= abs_offset_khz * unit_khz_dds_val;
2723*4882a593Smuzhiyun else
2724*4882a593Smuzhiyun dds += abs_offset_khz * unit_khz_dds_val;
2725*4882a593Smuzhiyun }
2726*4882a593Smuzhiyun
2727*4882a593Smuzhiyun dprintk("setting a DDS frequency offset of %c%dkHz\n", invert ? '-' : ' ', dds / unit_khz_dds_val);
2728*4882a593Smuzhiyun
2729*4882a593Smuzhiyun if (abs_offset_khz <= (state->cfg.pll->internal / ratio)) {
2730*4882a593Smuzhiyun /* Max dds offset is the half of the demod freq */
2731*4882a593Smuzhiyun dib8000_write_word(state, 26, invert);
2732*4882a593Smuzhiyun dib8000_write_word(state, 27, (u16)(dds >> 16) & 0x1ff);
2733*4882a593Smuzhiyun dib8000_write_word(state, 28, (u16)(dds & 0xffff));
2734*4882a593Smuzhiyun }
2735*4882a593Smuzhiyun }
2736*4882a593Smuzhiyun
dib8000_set_frequency_offset(struct dib8000_state * state)2737*4882a593Smuzhiyun static void dib8000_set_frequency_offset(struct dib8000_state *state)
2738*4882a593Smuzhiyun {
2739*4882a593Smuzhiyun struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
2740*4882a593Smuzhiyun int i;
2741*4882a593Smuzhiyun u32 current_rf;
2742*4882a593Smuzhiyun int total_dds_offset_khz;
2743*4882a593Smuzhiyun
2744*4882a593Smuzhiyun if (state->fe[0]->ops.tuner_ops.get_frequency)
2745*4882a593Smuzhiyun state->fe[0]->ops.tuner_ops.get_frequency(state->fe[0], ¤t_rf);
2746*4882a593Smuzhiyun else
2747*4882a593Smuzhiyun current_rf = c->frequency;
2748*4882a593Smuzhiyun current_rf /= 1000;
2749*4882a593Smuzhiyun total_dds_offset_khz = (int)current_rf - (int)c->frequency / 1000;
2750*4882a593Smuzhiyun
2751*4882a593Smuzhiyun if (c->isdbt_sb_mode) {
2752*4882a593Smuzhiyun state->subchannel = c->isdbt_sb_subchannel;
2753*4882a593Smuzhiyun
2754*4882a593Smuzhiyun i = dib8000_read_word(state, 26) & 1; /* P_dds_invspec */
2755*4882a593Smuzhiyun dib8000_write_word(state, 26, c->inversion ^ i);
2756*4882a593Smuzhiyun
2757*4882a593Smuzhiyun if (state->cfg.pll->ifreq == 0) { /* low if tuner */
2758*4882a593Smuzhiyun if ((c->inversion ^ i) == 0)
2759*4882a593Smuzhiyun dib8000_write_word(state, 26, dib8000_read_word(state, 26) | 1);
2760*4882a593Smuzhiyun } else {
2761*4882a593Smuzhiyun if ((c->inversion ^ i) == 0)
2762*4882a593Smuzhiyun total_dds_offset_khz *= -1;
2763*4882a593Smuzhiyun }
2764*4882a593Smuzhiyun }
2765*4882a593Smuzhiyun
2766*4882a593Smuzhiyun dprintk("%dkhz tuner offset (frequency = %dHz & current_rf = %dHz) total_dds_offset_hz = %d\n", c->frequency - current_rf, c->frequency, current_rf, total_dds_offset_khz);
2767*4882a593Smuzhiyun
2768*4882a593Smuzhiyun /* apply dds offset now */
2769*4882a593Smuzhiyun dib8000_set_dds(state, total_dds_offset_khz);
2770*4882a593Smuzhiyun }
2771*4882a593Smuzhiyun
2772*4882a593Smuzhiyun static u16 LUT_isdbt_symbol_duration[4] = { 26, 101, 63 };
2773*4882a593Smuzhiyun
dib8000_get_symbol_duration(struct dib8000_state * state)2774*4882a593Smuzhiyun static u32 dib8000_get_symbol_duration(struct dib8000_state *state)
2775*4882a593Smuzhiyun {
2776*4882a593Smuzhiyun struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
2777*4882a593Smuzhiyun u16 i;
2778*4882a593Smuzhiyun
2779*4882a593Smuzhiyun switch (c->transmission_mode) {
2780*4882a593Smuzhiyun case TRANSMISSION_MODE_2K:
2781*4882a593Smuzhiyun i = 0;
2782*4882a593Smuzhiyun break;
2783*4882a593Smuzhiyun case TRANSMISSION_MODE_4K:
2784*4882a593Smuzhiyun i = 2;
2785*4882a593Smuzhiyun break;
2786*4882a593Smuzhiyun default:
2787*4882a593Smuzhiyun case TRANSMISSION_MODE_AUTO:
2788*4882a593Smuzhiyun case TRANSMISSION_MODE_8K:
2789*4882a593Smuzhiyun i = 1;
2790*4882a593Smuzhiyun break;
2791*4882a593Smuzhiyun }
2792*4882a593Smuzhiyun
2793*4882a593Smuzhiyun return (LUT_isdbt_symbol_duration[i] / (c->bandwidth_hz / 1000)) + 1;
2794*4882a593Smuzhiyun }
2795*4882a593Smuzhiyun
dib8000_set_isdbt_loop_params(struct dib8000_state * state,enum param_loop_step loop_step)2796*4882a593Smuzhiyun static void dib8000_set_isdbt_loop_params(struct dib8000_state *state, enum param_loop_step loop_step)
2797*4882a593Smuzhiyun {
2798*4882a593Smuzhiyun struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
2799*4882a593Smuzhiyun u16 reg_32 = 0, reg_37 = 0;
2800*4882a593Smuzhiyun
2801*4882a593Smuzhiyun switch (loop_step) {
2802*4882a593Smuzhiyun case LOOP_TUNE_1:
2803*4882a593Smuzhiyun if (c->isdbt_sb_mode) {
2804*4882a593Smuzhiyun if (c->isdbt_partial_reception == 0) {
2805*4882a593Smuzhiyun reg_32 = ((11 - state->mode) << 12) | (6 << 8) | 0x40; /* P_timf_alpha = (11-P_mode), P_corm_alpha=6, P_corm_thres=0x40 */
2806*4882a593Smuzhiyun reg_37 = (3 << 5) | (0 << 4) | (10 - state->mode); /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = (10-P_mode) */
2807*4882a593Smuzhiyun } else { /* Sound Broadcasting mode 3 seg */
2808*4882a593Smuzhiyun reg_32 = ((10 - state->mode) << 12) | (6 << 8) | 0x60; /* P_timf_alpha = (10-P_mode), P_corm_alpha=6, P_corm_thres=0x60 */
2809*4882a593Smuzhiyun reg_37 = (3 << 5) | (0 << 4) | (9 - state->mode); /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = (9-P_mode) */
2810*4882a593Smuzhiyun }
2811*4882a593Smuzhiyun } else { /* 13-seg start conf offset loop parameters */
2812*4882a593Smuzhiyun reg_32 = ((9 - state->mode) << 12) | (6 << 8) | 0x80; /* P_timf_alpha = (9-P_mode, P_corm_alpha=6, P_corm_thres=0x80 */
2813*4882a593Smuzhiyun reg_37 = (3 << 5) | (0 << 4) | (8 - state->mode); /* P_ctrl_pha_off_max=3 P_ctrl_sfreq_inh =0 P_ctrl_sfreq_step = 9 */
2814*4882a593Smuzhiyun }
2815*4882a593Smuzhiyun break;
2816*4882a593Smuzhiyun case LOOP_TUNE_2:
2817*4882a593Smuzhiyun if (c->isdbt_sb_mode) {
2818*4882a593Smuzhiyun if (c->isdbt_partial_reception == 0) { /* Sound Broadcasting mode 1 seg */
2819*4882a593Smuzhiyun reg_32 = ((13-state->mode) << 12) | (6 << 8) | 0x40; /* P_timf_alpha = (13-P_mode) , P_corm_alpha=6, P_corm_thres=0x40*/
2820*4882a593Smuzhiyun reg_37 = (12-state->mode) | ((5 + state->mode) << 5);
2821*4882a593Smuzhiyun } else { /* Sound Broadcasting mode 3 seg */
2822*4882a593Smuzhiyun reg_32 = ((12-state->mode) << 12) | (6 << 8) | 0x60; /* P_timf_alpha = (12-P_mode) , P_corm_alpha=6, P_corm_thres=0x60 */
2823*4882a593Smuzhiyun reg_37 = (11-state->mode) | ((5 + state->mode) << 5);
2824*4882a593Smuzhiyun }
2825*4882a593Smuzhiyun } else { /* 13 seg */
2826*4882a593Smuzhiyun reg_32 = ((11-state->mode) << 12) | (6 << 8) | 0x80; /* P_timf_alpha = 8 , P_corm_alpha=6, P_corm_thres=0x80 */
2827*4882a593Smuzhiyun reg_37 = ((5+state->mode) << 5) | (10 - state->mode);
2828*4882a593Smuzhiyun }
2829*4882a593Smuzhiyun break;
2830*4882a593Smuzhiyun }
2831*4882a593Smuzhiyun dib8000_write_word(state, 32, reg_32);
2832*4882a593Smuzhiyun dib8000_write_word(state, 37, reg_37);
2833*4882a593Smuzhiyun }
2834*4882a593Smuzhiyun
dib8000_demod_restart(struct dib8000_state * state)2835*4882a593Smuzhiyun static void dib8000_demod_restart(struct dib8000_state *state)
2836*4882a593Smuzhiyun {
2837*4882a593Smuzhiyun dib8000_write_word(state, 770, 0x4000);
2838*4882a593Smuzhiyun dib8000_write_word(state, 770, 0x0000);
2839*4882a593Smuzhiyun return;
2840*4882a593Smuzhiyun }
2841*4882a593Smuzhiyun
dib8000_set_sync_wait(struct dib8000_state * state)2842*4882a593Smuzhiyun static void dib8000_set_sync_wait(struct dib8000_state *state)
2843*4882a593Smuzhiyun {
2844*4882a593Smuzhiyun struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
2845*4882a593Smuzhiyun u16 sync_wait = 64;
2846*4882a593Smuzhiyun
2847*4882a593Smuzhiyun /* P_dvsy_sync_wait - reuse mode */
2848*4882a593Smuzhiyun switch (c->transmission_mode) {
2849*4882a593Smuzhiyun case TRANSMISSION_MODE_8K:
2850*4882a593Smuzhiyun sync_wait = 256;
2851*4882a593Smuzhiyun break;
2852*4882a593Smuzhiyun case TRANSMISSION_MODE_4K:
2853*4882a593Smuzhiyun sync_wait = 128;
2854*4882a593Smuzhiyun break;
2855*4882a593Smuzhiyun default:
2856*4882a593Smuzhiyun case TRANSMISSION_MODE_2K:
2857*4882a593Smuzhiyun sync_wait = 64;
2858*4882a593Smuzhiyun break;
2859*4882a593Smuzhiyun }
2860*4882a593Smuzhiyun
2861*4882a593Smuzhiyun if (state->cfg.diversity_delay == 0)
2862*4882a593Smuzhiyun sync_wait = (sync_wait * (1 << (c->guard_interval)) * 3) / 2 + 48; /* add 50% SFN margin + compensate for one DVSY-fifo */
2863*4882a593Smuzhiyun else
2864*4882a593Smuzhiyun sync_wait = (sync_wait * (1 << (c->guard_interval)) * 3) / 2 + state->cfg.diversity_delay; /* add 50% SFN margin + compensate for DVSY-fifo */
2865*4882a593Smuzhiyun
2866*4882a593Smuzhiyun dib8000_write_word(state, 273, (dib8000_read_word(state, 273) & 0x000f) | (sync_wait << 4));
2867*4882a593Smuzhiyun }
2868*4882a593Smuzhiyun
dib8000_get_timeout(struct dib8000_state * state,u32 delay,enum timeout_mode mode)2869*4882a593Smuzhiyun static unsigned long dib8000_get_timeout(struct dib8000_state *state, u32 delay, enum timeout_mode mode)
2870*4882a593Smuzhiyun {
2871*4882a593Smuzhiyun if (mode == SYMBOL_DEPENDENT_ON)
2872*4882a593Smuzhiyun delay *= state->symbol_duration;
2873*4882a593Smuzhiyun
2874*4882a593Smuzhiyun return jiffies + usecs_to_jiffies(delay * 100);
2875*4882a593Smuzhiyun }
2876*4882a593Smuzhiyun
dib8000_get_status(struct dvb_frontend * fe)2877*4882a593Smuzhiyun static s32 dib8000_get_status(struct dvb_frontend *fe)
2878*4882a593Smuzhiyun {
2879*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
2880*4882a593Smuzhiyun return state->status;
2881*4882a593Smuzhiyun }
2882*4882a593Smuzhiyun
dib8000_get_tune_state(struct dvb_frontend * fe)2883*4882a593Smuzhiyun static enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
2884*4882a593Smuzhiyun {
2885*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
2886*4882a593Smuzhiyun return state->tune_state;
2887*4882a593Smuzhiyun }
2888*4882a593Smuzhiyun
dib8000_set_tune_state(struct dvb_frontend * fe,enum frontend_tune_state tune_state)2889*4882a593Smuzhiyun static int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
2890*4882a593Smuzhiyun {
2891*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
2892*4882a593Smuzhiyun
2893*4882a593Smuzhiyun state->tune_state = tune_state;
2894*4882a593Smuzhiyun return 0;
2895*4882a593Smuzhiyun }
2896*4882a593Smuzhiyun
dib8000_tune_restart_from_demod(struct dvb_frontend * fe)2897*4882a593Smuzhiyun static int dib8000_tune_restart_from_demod(struct dvb_frontend *fe)
2898*4882a593Smuzhiyun {
2899*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
2900*4882a593Smuzhiyun
2901*4882a593Smuzhiyun state->status = FE_STATUS_TUNE_PENDING;
2902*4882a593Smuzhiyun state->tune_state = CT_DEMOD_START;
2903*4882a593Smuzhiyun return 0;
2904*4882a593Smuzhiyun }
2905*4882a593Smuzhiyun
dib8000_read_lock(struct dvb_frontend * fe)2906*4882a593Smuzhiyun static u16 dib8000_read_lock(struct dvb_frontend *fe)
2907*4882a593Smuzhiyun {
2908*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
2909*4882a593Smuzhiyun
2910*4882a593Smuzhiyun if (state->revision == 0x8090)
2911*4882a593Smuzhiyun return dib8000_read_word(state, 570);
2912*4882a593Smuzhiyun return dib8000_read_word(state, 568);
2913*4882a593Smuzhiyun }
2914*4882a593Smuzhiyun
dib8090p_init_sdram(struct dib8000_state * state)2915*4882a593Smuzhiyun static int dib8090p_init_sdram(struct dib8000_state *state)
2916*4882a593Smuzhiyun {
2917*4882a593Smuzhiyun u16 reg = 0;
2918*4882a593Smuzhiyun dprintk("init sdram\n");
2919*4882a593Smuzhiyun
2920*4882a593Smuzhiyun reg = dib8000_read_word(state, 274) & 0xfff0;
2921*4882a593Smuzhiyun dib8000_write_word(state, 274, reg | 0x7); /* P_dintlv_delay_ram = 7 because of MobileSdram */
2922*4882a593Smuzhiyun
2923*4882a593Smuzhiyun dib8000_write_word(state, 1803, (7 << 2));
2924*4882a593Smuzhiyun
2925*4882a593Smuzhiyun reg = dib8000_read_word(state, 1280);
2926*4882a593Smuzhiyun dib8000_write_word(state, 1280, reg | (1 << 2)); /* force restart P_restart_sdram */
2927*4882a593Smuzhiyun dib8000_write_word(state, 1280, reg); /* release restart P_restart_sdram */
2928*4882a593Smuzhiyun
2929*4882a593Smuzhiyun return 0;
2930*4882a593Smuzhiyun }
2931*4882a593Smuzhiyun
2932*4882a593Smuzhiyun /**
2933*4882a593Smuzhiyun * is_manual_mode - Check if TMCC should be used for parameters settings
2934*4882a593Smuzhiyun * @c: struct dvb_frontend_properties
2935*4882a593Smuzhiyun *
2936*4882a593Smuzhiyun * By default, TMCC table should be used for parameter settings on most
2937*4882a593Smuzhiyun * usercases. However, sometimes it is desirable to lock the demod to
2938*4882a593Smuzhiyun * use the manual parameters.
2939*4882a593Smuzhiyun *
2940*4882a593Smuzhiyun * On manual mode, the current dib8000_tune state machine is very restrict:
2941*4882a593Smuzhiyun * It requires that both per-layer and per-transponder parameters to be
2942*4882a593Smuzhiyun * properly specified, otherwise the device won't lock.
2943*4882a593Smuzhiyun *
2944*4882a593Smuzhiyun * Check if all those conditions are properly satisfied before allowing
2945*4882a593Smuzhiyun * the device to use the manual frequency lock mode.
2946*4882a593Smuzhiyun */
is_manual_mode(struct dtv_frontend_properties * c)2947*4882a593Smuzhiyun static int is_manual_mode(struct dtv_frontend_properties *c)
2948*4882a593Smuzhiyun {
2949*4882a593Smuzhiyun int i, n_segs = 0;
2950*4882a593Smuzhiyun
2951*4882a593Smuzhiyun /* Use auto mode on DVB-T compat mode */
2952*4882a593Smuzhiyun if (c->delivery_system != SYS_ISDBT)
2953*4882a593Smuzhiyun return 0;
2954*4882a593Smuzhiyun
2955*4882a593Smuzhiyun /*
2956*4882a593Smuzhiyun * Transmission mode is only detected on auto mode, currently
2957*4882a593Smuzhiyun */
2958*4882a593Smuzhiyun if (c->transmission_mode == TRANSMISSION_MODE_AUTO) {
2959*4882a593Smuzhiyun dprintk("transmission mode auto\n");
2960*4882a593Smuzhiyun return 0;
2961*4882a593Smuzhiyun }
2962*4882a593Smuzhiyun
2963*4882a593Smuzhiyun /*
2964*4882a593Smuzhiyun * Guard interval is only detected on auto mode, currently
2965*4882a593Smuzhiyun */
2966*4882a593Smuzhiyun if (c->guard_interval == GUARD_INTERVAL_AUTO) {
2967*4882a593Smuzhiyun dprintk("guard interval auto\n");
2968*4882a593Smuzhiyun return 0;
2969*4882a593Smuzhiyun }
2970*4882a593Smuzhiyun
2971*4882a593Smuzhiyun /*
2972*4882a593Smuzhiyun * If no layer is enabled, assume auto mode, as at least one
2973*4882a593Smuzhiyun * layer should be enabled
2974*4882a593Smuzhiyun */
2975*4882a593Smuzhiyun if (!c->isdbt_layer_enabled) {
2976*4882a593Smuzhiyun dprintk("no layer modulation specified\n");
2977*4882a593Smuzhiyun return 0;
2978*4882a593Smuzhiyun }
2979*4882a593Smuzhiyun
2980*4882a593Smuzhiyun /*
2981*4882a593Smuzhiyun * Check if the per-layer parameters aren't auto and
2982*4882a593Smuzhiyun * disable a layer if segment count is 0 or invalid.
2983*4882a593Smuzhiyun */
2984*4882a593Smuzhiyun for (i = 0; i < 3; i++) {
2985*4882a593Smuzhiyun if (!(c->isdbt_layer_enabled & 1 << i))
2986*4882a593Smuzhiyun continue;
2987*4882a593Smuzhiyun
2988*4882a593Smuzhiyun if ((c->layer[i].segment_count > 13) ||
2989*4882a593Smuzhiyun (c->layer[i].segment_count == 0)) {
2990*4882a593Smuzhiyun c->isdbt_layer_enabled &= ~(1 << i);
2991*4882a593Smuzhiyun continue;
2992*4882a593Smuzhiyun }
2993*4882a593Smuzhiyun
2994*4882a593Smuzhiyun n_segs += c->layer[i].segment_count;
2995*4882a593Smuzhiyun
2996*4882a593Smuzhiyun if ((c->layer[i].modulation == QAM_AUTO) ||
2997*4882a593Smuzhiyun (c->layer[i].fec == FEC_AUTO)) {
2998*4882a593Smuzhiyun dprintk("layer %c has either modulation or FEC auto\n",
2999*4882a593Smuzhiyun 'A' + i);
3000*4882a593Smuzhiyun return 0;
3001*4882a593Smuzhiyun }
3002*4882a593Smuzhiyun }
3003*4882a593Smuzhiyun
3004*4882a593Smuzhiyun /*
3005*4882a593Smuzhiyun * Userspace specified a wrong number of segments.
3006*4882a593Smuzhiyun * fallback to auto mode.
3007*4882a593Smuzhiyun */
3008*4882a593Smuzhiyun if (n_segs == 0 || n_segs > 13) {
3009*4882a593Smuzhiyun dprintk("number of segments is invalid\n");
3010*4882a593Smuzhiyun return 0;
3011*4882a593Smuzhiyun }
3012*4882a593Smuzhiyun
3013*4882a593Smuzhiyun /* Everything looks ok for manual mode */
3014*4882a593Smuzhiyun return 1;
3015*4882a593Smuzhiyun }
3016*4882a593Smuzhiyun
dib8000_tune(struct dvb_frontend * fe)3017*4882a593Smuzhiyun static int dib8000_tune(struct dvb_frontend *fe)
3018*4882a593Smuzhiyun {
3019*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
3020*4882a593Smuzhiyun struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
3021*4882a593Smuzhiyun enum frontend_tune_state *tune_state = &state->tune_state;
3022*4882a593Smuzhiyun
3023*4882a593Smuzhiyun u16 locks, deeper_interleaver = 0, i;
3024*4882a593Smuzhiyun int ret = 1; /* 1 symbol duration (in 100us unit) delay most of the time */
3025*4882a593Smuzhiyun
3026*4882a593Smuzhiyun unsigned long *timeout = &state->timeout;
3027*4882a593Smuzhiyun unsigned long now = jiffies;
3028*4882a593Smuzhiyun u16 init_prbs;
3029*4882a593Smuzhiyun #ifdef DIB8000_AGC_FREEZE
3030*4882a593Smuzhiyun u16 agc1, agc2;
3031*4882a593Smuzhiyun #endif
3032*4882a593Smuzhiyun
3033*4882a593Smuzhiyun u32 corm[4] = {0, 0, 0, 0};
3034*4882a593Smuzhiyun u8 find_index, max_value;
3035*4882a593Smuzhiyun
3036*4882a593Smuzhiyun #if 0
3037*4882a593Smuzhiyun if (*tune_state < CT_DEMOD_STOP)
3038*4882a593Smuzhiyun dprintk("IN: context status = %d, TUNE_STATE %d autosearch step = %u jiffies = %lu\n",
3039*4882a593Smuzhiyun state->channel_parameters_set, *tune_state, state->autosearch_state, now);
3040*4882a593Smuzhiyun #endif
3041*4882a593Smuzhiyun
3042*4882a593Smuzhiyun switch (*tune_state) {
3043*4882a593Smuzhiyun case CT_DEMOD_START: /* 30 */
3044*4882a593Smuzhiyun dib8000_reset_stats(fe);
3045*4882a593Smuzhiyun
3046*4882a593Smuzhiyun if (state->revision == 0x8090)
3047*4882a593Smuzhiyun dib8090p_init_sdram(state);
3048*4882a593Smuzhiyun state->status = FE_STATUS_TUNE_PENDING;
3049*4882a593Smuzhiyun state->channel_parameters_set = is_manual_mode(c);
3050*4882a593Smuzhiyun
3051*4882a593Smuzhiyun dprintk("Tuning channel on %s search mode\n",
3052*4882a593Smuzhiyun state->channel_parameters_set ? "manual" : "auto");
3053*4882a593Smuzhiyun
3054*4882a593Smuzhiyun dib8000_viterbi_state(state, 0); /* force chan dec in restart */
3055*4882a593Smuzhiyun
3056*4882a593Smuzhiyun /* Layer monitor */
3057*4882a593Smuzhiyun dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60);
3058*4882a593Smuzhiyun
3059*4882a593Smuzhiyun dib8000_set_frequency_offset(state);
3060*4882a593Smuzhiyun dib8000_set_bandwidth(fe, c->bandwidth_hz / 1000);
3061*4882a593Smuzhiyun
3062*4882a593Smuzhiyun if (state->channel_parameters_set == 0) { /* The channel struct is unknown, search it ! */
3063*4882a593Smuzhiyun #ifdef DIB8000_AGC_FREEZE
3064*4882a593Smuzhiyun if (state->revision != 0x8090) {
3065*4882a593Smuzhiyun state->agc1_max = dib8000_read_word(state, 108);
3066*4882a593Smuzhiyun state->agc1_min = dib8000_read_word(state, 109);
3067*4882a593Smuzhiyun state->agc2_max = dib8000_read_word(state, 110);
3068*4882a593Smuzhiyun state->agc2_min = dib8000_read_word(state, 111);
3069*4882a593Smuzhiyun agc1 = dib8000_read_word(state, 388);
3070*4882a593Smuzhiyun agc2 = dib8000_read_word(state, 389);
3071*4882a593Smuzhiyun dib8000_write_word(state, 108, agc1);
3072*4882a593Smuzhiyun dib8000_write_word(state, 109, agc1);
3073*4882a593Smuzhiyun dib8000_write_word(state, 110, agc2);
3074*4882a593Smuzhiyun dib8000_write_word(state, 111, agc2);
3075*4882a593Smuzhiyun }
3076*4882a593Smuzhiyun #endif
3077*4882a593Smuzhiyun state->autosearch_state = AS_SEARCHING_FFT;
3078*4882a593Smuzhiyun state->found_nfft = TRANSMISSION_MODE_AUTO;
3079*4882a593Smuzhiyun state->found_guard = GUARD_INTERVAL_AUTO;
3080*4882a593Smuzhiyun *tune_state = CT_DEMOD_SEARCH_NEXT;
3081*4882a593Smuzhiyun } else { /* we already know the channel struct so TUNE only ! */
3082*4882a593Smuzhiyun state->autosearch_state = AS_DONE;
3083*4882a593Smuzhiyun *tune_state = CT_DEMOD_STEP_3;
3084*4882a593Smuzhiyun }
3085*4882a593Smuzhiyun state->symbol_duration = dib8000_get_symbol_duration(state);
3086*4882a593Smuzhiyun break;
3087*4882a593Smuzhiyun
3088*4882a593Smuzhiyun case CT_DEMOD_SEARCH_NEXT: /* 51 */
3089*4882a593Smuzhiyun dib8000_autosearch_start(fe);
3090*4882a593Smuzhiyun if (state->revision == 0x8090)
3091*4882a593Smuzhiyun ret = 50;
3092*4882a593Smuzhiyun else
3093*4882a593Smuzhiyun ret = 15;
3094*4882a593Smuzhiyun *tune_state = CT_DEMOD_STEP_1;
3095*4882a593Smuzhiyun break;
3096*4882a593Smuzhiyun
3097*4882a593Smuzhiyun case CT_DEMOD_STEP_1: /* 31 */
3098*4882a593Smuzhiyun switch (dib8000_autosearch_irq(fe)) {
3099*4882a593Smuzhiyun case 1: /* fail */
3100*4882a593Smuzhiyun state->status = FE_STATUS_TUNE_FAILED;
3101*4882a593Smuzhiyun state->autosearch_state = AS_DONE;
3102*4882a593Smuzhiyun *tune_state = CT_DEMOD_STOP; /* else we are done here */
3103*4882a593Smuzhiyun break;
3104*4882a593Smuzhiyun case 2: /* Success */
3105*4882a593Smuzhiyun state->status = FE_STATUS_FFT_SUCCESS; /* signal to the upper layer, that there was a channel found and the parameters can be read */
3106*4882a593Smuzhiyun *tune_state = CT_DEMOD_STEP_3;
3107*4882a593Smuzhiyun if (state->autosearch_state == AS_SEARCHING_GUARD)
3108*4882a593Smuzhiyun *tune_state = CT_DEMOD_STEP_2;
3109*4882a593Smuzhiyun else
3110*4882a593Smuzhiyun state->autosearch_state = AS_DONE;
3111*4882a593Smuzhiyun break;
3112*4882a593Smuzhiyun case 3: /* Autosearch FFT max correlation endded */
3113*4882a593Smuzhiyun *tune_state = CT_DEMOD_STEP_2;
3114*4882a593Smuzhiyun break;
3115*4882a593Smuzhiyun }
3116*4882a593Smuzhiyun break;
3117*4882a593Smuzhiyun
3118*4882a593Smuzhiyun case CT_DEMOD_STEP_2:
3119*4882a593Smuzhiyun switch (state->autosearch_state) {
3120*4882a593Smuzhiyun case AS_SEARCHING_FFT:
3121*4882a593Smuzhiyun /* searching for the correct FFT */
3122*4882a593Smuzhiyun if (state->revision == 0x8090) {
3123*4882a593Smuzhiyun corm[2] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597));
3124*4882a593Smuzhiyun corm[1] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599));
3125*4882a593Smuzhiyun corm[0] = (dib8000_read_word(state, 600) << 16) | (dib8000_read_word(state, 601));
3126*4882a593Smuzhiyun } else {
3127*4882a593Smuzhiyun corm[2] = (dib8000_read_word(state, 594) << 16) | (dib8000_read_word(state, 595));
3128*4882a593Smuzhiyun corm[1] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597));
3129*4882a593Smuzhiyun corm[0] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599));
3130*4882a593Smuzhiyun }
3131*4882a593Smuzhiyun /* dprintk("corm fft: %u %u %u\n", corm[0], corm[1], corm[2]); */
3132*4882a593Smuzhiyun
3133*4882a593Smuzhiyun max_value = 0;
3134*4882a593Smuzhiyun for (find_index = 1 ; find_index < 3 ; find_index++) {
3135*4882a593Smuzhiyun if (corm[max_value] < corm[find_index])
3136*4882a593Smuzhiyun max_value = find_index ;
3137*4882a593Smuzhiyun }
3138*4882a593Smuzhiyun
3139*4882a593Smuzhiyun switch (max_value) {
3140*4882a593Smuzhiyun case 0:
3141*4882a593Smuzhiyun state->found_nfft = TRANSMISSION_MODE_2K;
3142*4882a593Smuzhiyun break;
3143*4882a593Smuzhiyun case 1:
3144*4882a593Smuzhiyun state->found_nfft = TRANSMISSION_MODE_4K;
3145*4882a593Smuzhiyun break;
3146*4882a593Smuzhiyun case 2:
3147*4882a593Smuzhiyun default:
3148*4882a593Smuzhiyun state->found_nfft = TRANSMISSION_MODE_8K;
3149*4882a593Smuzhiyun break;
3150*4882a593Smuzhiyun }
3151*4882a593Smuzhiyun /* dprintk("Autosearch FFT has found Mode %d\n", max_value + 1); */
3152*4882a593Smuzhiyun
3153*4882a593Smuzhiyun *tune_state = CT_DEMOD_SEARCH_NEXT;
3154*4882a593Smuzhiyun state->autosearch_state = AS_SEARCHING_GUARD;
3155*4882a593Smuzhiyun if (state->revision == 0x8090)
3156*4882a593Smuzhiyun ret = 50;
3157*4882a593Smuzhiyun else
3158*4882a593Smuzhiyun ret = 10;
3159*4882a593Smuzhiyun break;
3160*4882a593Smuzhiyun case AS_SEARCHING_GUARD:
3161*4882a593Smuzhiyun /* searching for the correct guard interval */
3162*4882a593Smuzhiyun if (state->revision == 0x8090)
3163*4882a593Smuzhiyun state->found_guard = dib8000_read_word(state, 572) & 0x3;
3164*4882a593Smuzhiyun else
3165*4882a593Smuzhiyun state->found_guard = dib8000_read_word(state, 570) & 0x3;
3166*4882a593Smuzhiyun /* dprintk("guard interval found=%i\n", state->found_guard); */
3167*4882a593Smuzhiyun
3168*4882a593Smuzhiyun *tune_state = CT_DEMOD_STEP_3;
3169*4882a593Smuzhiyun break;
3170*4882a593Smuzhiyun default:
3171*4882a593Smuzhiyun /* the demod should never be in this state */
3172*4882a593Smuzhiyun state->status = FE_STATUS_TUNE_FAILED;
3173*4882a593Smuzhiyun state->autosearch_state = AS_DONE;
3174*4882a593Smuzhiyun *tune_state = CT_DEMOD_STOP; /* else we are done here */
3175*4882a593Smuzhiyun break;
3176*4882a593Smuzhiyun }
3177*4882a593Smuzhiyun break;
3178*4882a593Smuzhiyun
3179*4882a593Smuzhiyun case CT_DEMOD_STEP_3: /* 33 */
3180*4882a593Smuzhiyun dib8000_set_isdbt_loop_params(state, LOOP_TUNE_1);
3181*4882a593Smuzhiyun dib8000_set_isdbt_common_channel(state, 0, 0);/* setting the known channel parameters here */
3182*4882a593Smuzhiyun *tune_state = CT_DEMOD_STEP_4;
3183*4882a593Smuzhiyun break;
3184*4882a593Smuzhiyun
3185*4882a593Smuzhiyun case CT_DEMOD_STEP_4: /* (34) */
3186*4882a593Smuzhiyun dib8000_demod_restart(state);
3187*4882a593Smuzhiyun
3188*4882a593Smuzhiyun dib8000_set_sync_wait(state);
3189*4882a593Smuzhiyun dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
3190*4882a593Smuzhiyun
3191*4882a593Smuzhiyun locks = (dib8000_read_word(state, 180) >> 6) & 0x3f; /* P_coff_winlen ? */
3192*4882a593Smuzhiyun /* coff should lock over P_coff_winlen ofdm symbols : give 3 times this length to lock */
3193*4882a593Smuzhiyun *timeout = dib8000_get_timeout(state, 2 * locks, SYMBOL_DEPENDENT_ON);
3194*4882a593Smuzhiyun *tune_state = CT_DEMOD_STEP_5;
3195*4882a593Smuzhiyun break;
3196*4882a593Smuzhiyun
3197*4882a593Smuzhiyun case CT_DEMOD_STEP_5: /* (35) */
3198*4882a593Smuzhiyun locks = dib8000_read_lock(fe);
3199*4882a593Smuzhiyun if (locks & (0x3 << 11)) { /* coff-lock and off_cpil_lock achieved */
3200*4882a593Smuzhiyun dib8000_update_timf(state); /* we achieved a coff_cpil_lock - it's time to update the timf */
3201*4882a593Smuzhiyun if (!state->differential_constellation) {
3202*4882a593Smuzhiyun /* 2 times lmod4_win_len + 10 symbols (pipe delay after coff + nb to compute a 1st correlation) */
3203*4882a593Smuzhiyun *timeout = dib8000_get_timeout(state, (20 * ((dib8000_read_word(state, 188)>>5)&0x1f)), SYMBOL_DEPENDENT_ON);
3204*4882a593Smuzhiyun *tune_state = CT_DEMOD_STEP_7;
3205*4882a593Smuzhiyun } else {
3206*4882a593Smuzhiyun *tune_state = CT_DEMOD_STEP_8;
3207*4882a593Smuzhiyun }
3208*4882a593Smuzhiyun } else if (time_after(now, *timeout)) {
3209*4882a593Smuzhiyun *tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
3210*4882a593Smuzhiyun }
3211*4882a593Smuzhiyun break;
3212*4882a593Smuzhiyun
3213*4882a593Smuzhiyun case CT_DEMOD_STEP_6: /* (36) if there is an input (diversity) */
3214*4882a593Smuzhiyun if ((state->fe[1] != NULL) && (state->output_mode != OUTMODE_DIVERSITY)) {
3215*4882a593Smuzhiyun /* if there is a diversity fe in input and this fe is has not already failed : wait here until this this fe has succedeed or failed */
3216*4882a593Smuzhiyun if (dib8000_get_status(state->fe[1]) <= FE_STATUS_STD_SUCCESS) /* Something is locked on the input fe */
3217*4882a593Smuzhiyun *tune_state = CT_DEMOD_STEP_8; /* go for mpeg */
3218*4882a593Smuzhiyun else if (dib8000_get_status(state->fe[1]) >= FE_STATUS_TUNE_TIME_TOO_SHORT) { /* fe in input failed also, break the current one */
3219*4882a593Smuzhiyun *tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
3220*4882a593Smuzhiyun dib8000_viterbi_state(state, 1); /* start viterbi chandec */
3221*4882a593Smuzhiyun dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
3222*4882a593Smuzhiyun state->status = FE_STATUS_TUNE_FAILED;
3223*4882a593Smuzhiyun }
3224*4882a593Smuzhiyun } else {
3225*4882a593Smuzhiyun dib8000_viterbi_state(state, 1); /* start viterbi chandec */
3226*4882a593Smuzhiyun dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
3227*4882a593Smuzhiyun *tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
3228*4882a593Smuzhiyun state->status = FE_STATUS_TUNE_FAILED;
3229*4882a593Smuzhiyun }
3230*4882a593Smuzhiyun break;
3231*4882a593Smuzhiyun
3232*4882a593Smuzhiyun case CT_DEMOD_STEP_7: /* 37 */
3233*4882a593Smuzhiyun locks = dib8000_read_lock(fe);
3234*4882a593Smuzhiyun if (locks & (1<<10)) { /* lmod4_lock */
3235*4882a593Smuzhiyun ret = 14; /* wait for 14 symbols */
3236*4882a593Smuzhiyun *tune_state = CT_DEMOD_STEP_8;
3237*4882a593Smuzhiyun } else if (time_after(now, *timeout))
3238*4882a593Smuzhiyun *tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
3239*4882a593Smuzhiyun break;
3240*4882a593Smuzhiyun
3241*4882a593Smuzhiyun case CT_DEMOD_STEP_8: /* 38 */
3242*4882a593Smuzhiyun dib8000_viterbi_state(state, 1); /* start viterbi chandec */
3243*4882a593Smuzhiyun dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
3244*4882a593Smuzhiyun
3245*4882a593Smuzhiyun /* mpeg will never lock on this condition because init_prbs is not set : search for it !*/
3246*4882a593Smuzhiyun if (c->isdbt_sb_mode
3247*4882a593Smuzhiyun && c->isdbt_sb_subchannel < 14
3248*4882a593Smuzhiyun && !state->differential_constellation) {
3249*4882a593Smuzhiyun state->subchannel = 0;
3250*4882a593Smuzhiyun *tune_state = CT_DEMOD_STEP_11;
3251*4882a593Smuzhiyun } else {
3252*4882a593Smuzhiyun *tune_state = CT_DEMOD_STEP_9;
3253*4882a593Smuzhiyun state->status = FE_STATUS_LOCKED;
3254*4882a593Smuzhiyun }
3255*4882a593Smuzhiyun break;
3256*4882a593Smuzhiyun
3257*4882a593Smuzhiyun case CT_DEMOD_STEP_9: /* 39 */
3258*4882a593Smuzhiyun if ((state->revision == 0x8090) || ((dib8000_read_word(state, 1291) >> 9) & 0x1)) { /* fe capable of deinterleaving : esram */
3259*4882a593Smuzhiyun /* defines timeout for mpeg lock depending on interleaver length of longest layer */
3260*4882a593Smuzhiyun for (i = 0; i < 3; i++) {
3261*4882a593Smuzhiyun if (c->layer[i].interleaving >= deeper_interleaver) {
3262*4882a593Smuzhiyun dprintk("layer%i: time interleaver = %d\n", i, c->layer[i].interleaving);
3263*4882a593Smuzhiyun if (c->layer[i].segment_count > 0) { /* valid layer */
3264*4882a593Smuzhiyun deeper_interleaver = c->layer[0].interleaving;
3265*4882a593Smuzhiyun state->longest_intlv_layer = i;
3266*4882a593Smuzhiyun }
3267*4882a593Smuzhiyun }
3268*4882a593Smuzhiyun }
3269*4882a593Smuzhiyun
3270*4882a593Smuzhiyun if (deeper_interleaver == 0)
3271*4882a593Smuzhiyun locks = 2; /* locks is the tmp local variable name */
3272*4882a593Smuzhiyun else if (deeper_interleaver == 3)
3273*4882a593Smuzhiyun locks = 8;
3274*4882a593Smuzhiyun else
3275*4882a593Smuzhiyun locks = 2 * deeper_interleaver;
3276*4882a593Smuzhiyun
3277*4882a593Smuzhiyun if (state->diversity_onoff != 0) /* because of diversity sync */
3278*4882a593Smuzhiyun locks *= 2;
3279*4882a593Smuzhiyun
3280*4882a593Smuzhiyun *timeout = now + msecs_to_jiffies(200 * locks); /* give the mpeg lock 800ms if sram is present */
3281*4882a593Smuzhiyun dprintk("Deeper interleaver mode = %d on layer %d : timeout mult factor = %d => will use timeout = %ld\n",
3282*4882a593Smuzhiyun deeper_interleaver, state->longest_intlv_layer, locks, *timeout);
3283*4882a593Smuzhiyun
3284*4882a593Smuzhiyun *tune_state = CT_DEMOD_STEP_10;
3285*4882a593Smuzhiyun } else
3286*4882a593Smuzhiyun *tune_state = CT_DEMOD_STOP;
3287*4882a593Smuzhiyun break;
3288*4882a593Smuzhiyun
3289*4882a593Smuzhiyun case CT_DEMOD_STEP_10: /* 40 */
3290*4882a593Smuzhiyun locks = dib8000_read_lock(fe);
3291*4882a593Smuzhiyun if (locks&(1<<(7-state->longest_intlv_layer))) { /* mpeg lock : check the longest one */
3292*4882a593Smuzhiyun dprintk("ISDB-T layer locks: Layer A %s, Layer B %s, Layer C %s\n",
3293*4882a593Smuzhiyun c->layer[0].segment_count ? (locks >> 7) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled",
3294*4882a593Smuzhiyun c->layer[1].segment_count ? (locks >> 6) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled",
3295*4882a593Smuzhiyun c->layer[2].segment_count ? (locks >> 5) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled");
3296*4882a593Smuzhiyun if (c->isdbt_sb_mode
3297*4882a593Smuzhiyun && c->isdbt_sb_subchannel < 14
3298*4882a593Smuzhiyun && !state->differential_constellation)
3299*4882a593Smuzhiyun /* signal to the upper layer, that there was a channel found and the parameters can be read */
3300*4882a593Smuzhiyun state->status = FE_STATUS_DEMOD_SUCCESS;
3301*4882a593Smuzhiyun else
3302*4882a593Smuzhiyun state->status = FE_STATUS_DATA_LOCKED;
3303*4882a593Smuzhiyun *tune_state = CT_DEMOD_STOP;
3304*4882a593Smuzhiyun } else if (time_after(now, *timeout)) {
3305*4882a593Smuzhiyun if (c->isdbt_sb_mode
3306*4882a593Smuzhiyun && c->isdbt_sb_subchannel < 14
3307*4882a593Smuzhiyun && !state->differential_constellation) { /* continue to try init prbs autosearch */
3308*4882a593Smuzhiyun state->subchannel += 3;
3309*4882a593Smuzhiyun *tune_state = CT_DEMOD_STEP_11;
3310*4882a593Smuzhiyun } else { /* we are done mpeg of the longest interleaver xas not locking but let's try if an other layer has locked in the same time */
3311*4882a593Smuzhiyun if (locks & (0x7 << 5)) {
3312*4882a593Smuzhiyun dprintk("Not all ISDB-T layers locked in %d ms: Layer A %s, Layer B %s, Layer C %s\n",
3313*4882a593Smuzhiyun jiffies_to_msecs(now - *timeout),
3314*4882a593Smuzhiyun c->layer[0].segment_count ? (locks >> 7) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled",
3315*4882a593Smuzhiyun c->layer[1].segment_count ? (locks >> 6) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled",
3316*4882a593Smuzhiyun c->layer[2].segment_count ? (locks >> 5) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled");
3317*4882a593Smuzhiyun
3318*4882a593Smuzhiyun state->status = FE_STATUS_DATA_LOCKED;
3319*4882a593Smuzhiyun } else
3320*4882a593Smuzhiyun state->status = FE_STATUS_TUNE_FAILED;
3321*4882a593Smuzhiyun *tune_state = CT_DEMOD_STOP;
3322*4882a593Smuzhiyun }
3323*4882a593Smuzhiyun }
3324*4882a593Smuzhiyun break;
3325*4882a593Smuzhiyun
3326*4882a593Smuzhiyun case CT_DEMOD_STEP_11: /* 41 : init prbs autosearch */
3327*4882a593Smuzhiyun init_prbs = dib8000_get_init_prbs(state, state->subchannel);
3328*4882a593Smuzhiyun
3329*4882a593Smuzhiyun if (init_prbs) {
3330*4882a593Smuzhiyun dib8000_set_subchannel_prbs(state, init_prbs);
3331*4882a593Smuzhiyun *tune_state = CT_DEMOD_STEP_9;
3332*4882a593Smuzhiyun } else {
3333*4882a593Smuzhiyun *tune_state = CT_DEMOD_STOP;
3334*4882a593Smuzhiyun state->status = FE_STATUS_TUNE_FAILED;
3335*4882a593Smuzhiyun }
3336*4882a593Smuzhiyun break;
3337*4882a593Smuzhiyun
3338*4882a593Smuzhiyun default:
3339*4882a593Smuzhiyun break;
3340*4882a593Smuzhiyun }
3341*4882a593Smuzhiyun
3342*4882a593Smuzhiyun /* tuning is finished - cleanup the demod */
3343*4882a593Smuzhiyun switch (*tune_state) {
3344*4882a593Smuzhiyun case CT_DEMOD_STOP: /* (42) */
3345*4882a593Smuzhiyun #ifdef DIB8000_AGC_FREEZE
3346*4882a593Smuzhiyun if ((state->revision != 0x8090) && (state->agc1_max != 0)) {
3347*4882a593Smuzhiyun dib8000_write_word(state, 108, state->agc1_max);
3348*4882a593Smuzhiyun dib8000_write_word(state, 109, state->agc1_min);
3349*4882a593Smuzhiyun dib8000_write_word(state, 110, state->agc2_max);
3350*4882a593Smuzhiyun dib8000_write_word(state, 111, state->agc2_min);
3351*4882a593Smuzhiyun state->agc1_max = 0;
3352*4882a593Smuzhiyun state->agc1_min = 0;
3353*4882a593Smuzhiyun state->agc2_max = 0;
3354*4882a593Smuzhiyun state->agc2_min = 0;
3355*4882a593Smuzhiyun }
3356*4882a593Smuzhiyun #endif
3357*4882a593Smuzhiyun ret = 0;
3358*4882a593Smuzhiyun break;
3359*4882a593Smuzhiyun default:
3360*4882a593Smuzhiyun break;
3361*4882a593Smuzhiyun }
3362*4882a593Smuzhiyun
3363*4882a593Smuzhiyun if ((ret > 0) && (*tune_state > CT_DEMOD_STEP_3))
3364*4882a593Smuzhiyun return ret * state->symbol_duration;
3365*4882a593Smuzhiyun if ((ret > 0) && (ret < state->symbol_duration))
3366*4882a593Smuzhiyun return state->symbol_duration; /* at least one symbol */
3367*4882a593Smuzhiyun return ret;
3368*4882a593Smuzhiyun }
3369*4882a593Smuzhiyun
dib8000_wakeup(struct dvb_frontend * fe)3370*4882a593Smuzhiyun static int dib8000_wakeup(struct dvb_frontend *fe)
3371*4882a593Smuzhiyun {
3372*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
3373*4882a593Smuzhiyun u8 index_frontend;
3374*4882a593Smuzhiyun int ret;
3375*4882a593Smuzhiyun
3376*4882a593Smuzhiyun dib8000_set_power_mode(state, DIB8000_POWER_ALL);
3377*4882a593Smuzhiyun dib8000_set_adc_state(state, DIBX000_ADC_ON);
3378*4882a593Smuzhiyun if (dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
3379*4882a593Smuzhiyun dprintk("could not start Slow ADC\n");
3380*4882a593Smuzhiyun
3381*4882a593Smuzhiyun if (state->revision == 0x8090)
3382*4882a593Smuzhiyun dib8000_sad_calib(state);
3383*4882a593Smuzhiyun
3384*4882a593Smuzhiyun for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
3385*4882a593Smuzhiyun ret = state->fe[index_frontend]->ops.init(state->fe[index_frontend]);
3386*4882a593Smuzhiyun if (ret < 0)
3387*4882a593Smuzhiyun return ret;
3388*4882a593Smuzhiyun }
3389*4882a593Smuzhiyun
3390*4882a593Smuzhiyun return 0;
3391*4882a593Smuzhiyun }
3392*4882a593Smuzhiyun
dib8000_sleep(struct dvb_frontend * fe)3393*4882a593Smuzhiyun static int dib8000_sleep(struct dvb_frontend *fe)
3394*4882a593Smuzhiyun {
3395*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
3396*4882a593Smuzhiyun u8 index_frontend;
3397*4882a593Smuzhiyun int ret;
3398*4882a593Smuzhiyun
3399*4882a593Smuzhiyun for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
3400*4882a593Smuzhiyun ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]);
3401*4882a593Smuzhiyun if (ret < 0)
3402*4882a593Smuzhiyun return ret;
3403*4882a593Smuzhiyun }
3404*4882a593Smuzhiyun
3405*4882a593Smuzhiyun if (state->revision != 0x8090)
3406*4882a593Smuzhiyun dib8000_set_output_mode(fe, OUTMODE_HIGH_Z);
3407*4882a593Smuzhiyun dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY);
3408*4882a593Smuzhiyun return dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF) | dib8000_set_adc_state(state, DIBX000_ADC_OFF);
3409*4882a593Smuzhiyun }
3410*4882a593Smuzhiyun
3411*4882a593Smuzhiyun static int dib8000_read_status(struct dvb_frontend *fe, enum fe_status *stat);
3412*4882a593Smuzhiyun
dib8000_get_frontend(struct dvb_frontend * fe,struct dtv_frontend_properties * c)3413*4882a593Smuzhiyun static int dib8000_get_frontend(struct dvb_frontend *fe,
3414*4882a593Smuzhiyun struct dtv_frontend_properties *c)
3415*4882a593Smuzhiyun {
3416*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
3417*4882a593Smuzhiyun u16 i, val = 0;
3418*4882a593Smuzhiyun enum fe_status stat = 0;
3419*4882a593Smuzhiyun u8 index_frontend, sub_index_frontend;
3420*4882a593Smuzhiyun
3421*4882a593Smuzhiyun c->bandwidth_hz = 6000000;
3422*4882a593Smuzhiyun
3423*4882a593Smuzhiyun /*
3424*4882a593Smuzhiyun * If called to early, get_frontend makes dib8000_tune to either
3425*4882a593Smuzhiyun * not lock or not sync. This causes dvbv5-scan/dvbv5-zap to fail.
3426*4882a593Smuzhiyun * So, let's just return if frontend 0 has not locked.
3427*4882a593Smuzhiyun */
3428*4882a593Smuzhiyun dib8000_read_status(fe, &stat);
3429*4882a593Smuzhiyun if (!(stat & FE_HAS_SYNC))
3430*4882a593Smuzhiyun return 0;
3431*4882a593Smuzhiyun
3432*4882a593Smuzhiyun dprintk("dib8000_get_frontend: TMCC lock\n");
3433*4882a593Smuzhiyun for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
3434*4882a593Smuzhiyun state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat);
3435*4882a593Smuzhiyun if (stat&FE_HAS_SYNC) {
3436*4882a593Smuzhiyun dprintk("TMCC lock on the slave%i\n", index_frontend);
3437*4882a593Smuzhiyun /* synchronize the cache with the other frontends */
3438*4882a593Smuzhiyun state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend], c);
3439*4882a593Smuzhiyun for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL); sub_index_frontend++) {
3440*4882a593Smuzhiyun if (sub_index_frontend != index_frontend) {
3441*4882a593Smuzhiyun state->fe[sub_index_frontend]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode;
3442*4882a593Smuzhiyun state->fe[sub_index_frontend]->dtv_property_cache.inversion = state->fe[index_frontend]->dtv_property_cache.inversion;
3443*4882a593Smuzhiyun state->fe[sub_index_frontend]->dtv_property_cache.transmission_mode = state->fe[index_frontend]->dtv_property_cache.transmission_mode;
3444*4882a593Smuzhiyun state->fe[sub_index_frontend]->dtv_property_cache.guard_interval = state->fe[index_frontend]->dtv_property_cache.guard_interval;
3445*4882a593Smuzhiyun state->fe[sub_index_frontend]->dtv_property_cache.isdbt_partial_reception = state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception;
3446*4882a593Smuzhiyun for (i = 0; i < 3; i++) {
3447*4882a593Smuzhiyun state->fe[sub_index_frontend]->dtv_property_cache.layer[i].segment_count = state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count;
3448*4882a593Smuzhiyun state->fe[sub_index_frontend]->dtv_property_cache.layer[i].interleaving = state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving;
3449*4882a593Smuzhiyun state->fe[sub_index_frontend]->dtv_property_cache.layer[i].fec = state->fe[index_frontend]->dtv_property_cache.layer[i].fec;
3450*4882a593Smuzhiyun state->fe[sub_index_frontend]->dtv_property_cache.layer[i].modulation = state->fe[index_frontend]->dtv_property_cache.layer[i].modulation;
3451*4882a593Smuzhiyun }
3452*4882a593Smuzhiyun }
3453*4882a593Smuzhiyun }
3454*4882a593Smuzhiyun return 0;
3455*4882a593Smuzhiyun }
3456*4882a593Smuzhiyun }
3457*4882a593Smuzhiyun
3458*4882a593Smuzhiyun c->isdbt_sb_mode = dib8000_read_word(state, 508) & 0x1;
3459*4882a593Smuzhiyun
3460*4882a593Smuzhiyun if (state->revision == 0x8090)
3461*4882a593Smuzhiyun val = dib8000_read_word(state, 572);
3462*4882a593Smuzhiyun else
3463*4882a593Smuzhiyun val = dib8000_read_word(state, 570);
3464*4882a593Smuzhiyun c->inversion = (val & 0x40) >> 6;
3465*4882a593Smuzhiyun switch ((val & 0x30) >> 4) {
3466*4882a593Smuzhiyun case 1:
3467*4882a593Smuzhiyun c->transmission_mode = TRANSMISSION_MODE_2K;
3468*4882a593Smuzhiyun dprintk("dib8000_get_frontend: transmission mode 2K\n");
3469*4882a593Smuzhiyun break;
3470*4882a593Smuzhiyun case 2:
3471*4882a593Smuzhiyun c->transmission_mode = TRANSMISSION_MODE_4K;
3472*4882a593Smuzhiyun dprintk("dib8000_get_frontend: transmission mode 4K\n");
3473*4882a593Smuzhiyun break;
3474*4882a593Smuzhiyun case 3:
3475*4882a593Smuzhiyun default:
3476*4882a593Smuzhiyun c->transmission_mode = TRANSMISSION_MODE_8K;
3477*4882a593Smuzhiyun dprintk("dib8000_get_frontend: transmission mode 8K\n");
3478*4882a593Smuzhiyun break;
3479*4882a593Smuzhiyun }
3480*4882a593Smuzhiyun
3481*4882a593Smuzhiyun switch (val & 0x3) {
3482*4882a593Smuzhiyun case 0:
3483*4882a593Smuzhiyun c->guard_interval = GUARD_INTERVAL_1_32;
3484*4882a593Smuzhiyun dprintk("dib8000_get_frontend: Guard Interval = 1/32\n");
3485*4882a593Smuzhiyun break;
3486*4882a593Smuzhiyun case 1:
3487*4882a593Smuzhiyun c->guard_interval = GUARD_INTERVAL_1_16;
3488*4882a593Smuzhiyun dprintk("dib8000_get_frontend: Guard Interval = 1/16\n");
3489*4882a593Smuzhiyun break;
3490*4882a593Smuzhiyun case 2:
3491*4882a593Smuzhiyun dprintk("dib8000_get_frontend: Guard Interval = 1/8\n");
3492*4882a593Smuzhiyun c->guard_interval = GUARD_INTERVAL_1_8;
3493*4882a593Smuzhiyun break;
3494*4882a593Smuzhiyun case 3:
3495*4882a593Smuzhiyun dprintk("dib8000_get_frontend: Guard Interval = 1/4\n");
3496*4882a593Smuzhiyun c->guard_interval = GUARD_INTERVAL_1_4;
3497*4882a593Smuzhiyun break;
3498*4882a593Smuzhiyun }
3499*4882a593Smuzhiyun
3500*4882a593Smuzhiyun val = dib8000_read_word(state, 505);
3501*4882a593Smuzhiyun c->isdbt_partial_reception = val & 1;
3502*4882a593Smuzhiyun dprintk("dib8000_get_frontend: partial_reception = %d\n", c->isdbt_partial_reception);
3503*4882a593Smuzhiyun
3504*4882a593Smuzhiyun for (i = 0; i < 3; i++) {
3505*4882a593Smuzhiyun int show;
3506*4882a593Smuzhiyun
3507*4882a593Smuzhiyun val = dib8000_read_word(state, 493 + i) & 0x0f;
3508*4882a593Smuzhiyun c->layer[i].segment_count = val;
3509*4882a593Smuzhiyun
3510*4882a593Smuzhiyun if (val == 0 || val > 13)
3511*4882a593Smuzhiyun show = 0;
3512*4882a593Smuzhiyun else
3513*4882a593Smuzhiyun show = 1;
3514*4882a593Smuzhiyun
3515*4882a593Smuzhiyun if (show)
3516*4882a593Smuzhiyun dprintk("dib8000_get_frontend: Layer %d segments = %d\n",
3517*4882a593Smuzhiyun i, c->layer[i].segment_count);
3518*4882a593Smuzhiyun
3519*4882a593Smuzhiyun val = dib8000_read_word(state, 499 + i) & 0x3;
3520*4882a593Smuzhiyun /* Interleaving can be 0, 1, 2 or 4 */
3521*4882a593Smuzhiyun if (val == 3)
3522*4882a593Smuzhiyun val = 4;
3523*4882a593Smuzhiyun c->layer[i].interleaving = val;
3524*4882a593Smuzhiyun if (show)
3525*4882a593Smuzhiyun dprintk("dib8000_get_frontend: Layer %d time_intlv = %d\n",
3526*4882a593Smuzhiyun i, c->layer[i].interleaving);
3527*4882a593Smuzhiyun
3528*4882a593Smuzhiyun val = dib8000_read_word(state, 481 + i);
3529*4882a593Smuzhiyun switch (val & 0x7) {
3530*4882a593Smuzhiyun case 1:
3531*4882a593Smuzhiyun c->layer[i].fec = FEC_1_2;
3532*4882a593Smuzhiyun if (show)
3533*4882a593Smuzhiyun dprintk("dib8000_get_frontend: Layer %d Code Rate = 1/2\n", i);
3534*4882a593Smuzhiyun break;
3535*4882a593Smuzhiyun case 2:
3536*4882a593Smuzhiyun c->layer[i].fec = FEC_2_3;
3537*4882a593Smuzhiyun if (show)
3538*4882a593Smuzhiyun dprintk("dib8000_get_frontend: Layer %d Code Rate = 2/3\n", i);
3539*4882a593Smuzhiyun break;
3540*4882a593Smuzhiyun case 3:
3541*4882a593Smuzhiyun c->layer[i].fec = FEC_3_4;
3542*4882a593Smuzhiyun if (show)
3543*4882a593Smuzhiyun dprintk("dib8000_get_frontend: Layer %d Code Rate = 3/4\n", i);
3544*4882a593Smuzhiyun break;
3545*4882a593Smuzhiyun case 5:
3546*4882a593Smuzhiyun c->layer[i].fec = FEC_5_6;
3547*4882a593Smuzhiyun if (show)
3548*4882a593Smuzhiyun dprintk("dib8000_get_frontend: Layer %d Code Rate = 5/6\n", i);
3549*4882a593Smuzhiyun break;
3550*4882a593Smuzhiyun default:
3551*4882a593Smuzhiyun c->layer[i].fec = FEC_7_8;
3552*4882a593Smuzhiyun if (show)
3553*4882a593Smuzhiyun dprintk("dib8000_get_frontend: Layer %d Code Rate = 7/8\n", i);
3554*4882a593Smuzhiyun break;
3555*4882a593Smuzhiyun }
3556*4882a593Smuzhiyun
3557*4882a593Smuzhiyun val = dib8000_read_word(state, 487 + i);
3558*4882a593Smuzhiyun switch (val & 0x3) {
3559*4882a593Smuzhiyun case 0:
3560*4882a593Smuzhiyun c->layer[i].modulation = DQPSK;
3561*4882a593Smuzhiyun if (show)
3562*4882a593Smuzhiyun dprintk("dib8000_get_frontend: Layer %d DQPSK\n", i);
3563*4882a593Smuzhiyun break;
3564*4882a593Smuzhiyun case 1:
3565*4882a593Smuzhiyun c->layer[i].modulation = QPSK;
3566*4882a593Smuzhiyun if (show)
3567*4882a593Smuzhiyun dprintk("dib8000_get_frontend: Layer %d QPSK\n", i);
3568*4882a593Smuzhiyun break;
3569*4882a593Smuzhiyun case 2:
3570*4882a593Smuzhiyun c->layer[i].modulation = QAM_16;
3571*4882a593Smuzhiyun if (show)
3572*4882a593Smuzhiyun dprintk("dib8000_get_frontend: Layer %d QAM16\n", i);
3573*4882a593Smuzhiyun break;
3574*4882a593Smuzhiyun case 3:
3575*4882a593Smuzhiyun default:
3576*4882a593Smuzhiyun c->layer[i].modulation = QAM_64;
3577*4882a593Smuzhiyun if (show)
3578*4882a593Smuzhiyun dprintk("dib8000_get_frontend: Layer %d QAM64\n", i);
3579*4882a593Smuzhiyun break;
3580*4882a593Smuzhiyun }
3581*4882a593Smuzhiyun }
3582*4882a593Smuzhiyun
3583*4882a593Smuzhiyun /* synchronize the cache with the other frontends */
3584*4882a593Smuzhiyun for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
3585*4882a593Smuzhiyun state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode = c->isdbt_sb_mode;
3586*4882a593Smuzhiyun state->fe[index_frontend]->dtv_property_cache.inversion = c->inversion;
3587*4882a593Smuzhiyun state->fe[index_frontend]->dtv_property_cache.transmission_mode = c->transmission_mode;
3588*4882a593Smuzhiyun state->fe[index_frontend]->dtv_property_cache.guard_interval = c->guard_interval;
3589*4882a593Smuzhiyun state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception = c->isdbt_partial_reception;
3590*4882a593Smuzhiyun for (i = 0; i < 3; i++) {
3591*4882a593Smuzhiyun state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count = c->layer[i].segment_count;
3592*4882a593Smuzhiyun state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving = c->layer[i].interleaving;
3593*4882a593Smuzhiyun state->fe[index_frontend]->dtv_property_cache.layer[i].fec = c->layer[i].fec;
3594*4882a593Smuzhiyun state->fe[index_frontend]->dtv_property_cache.layer[i].modulation = c->layer[i].modulation;
3595*4882a593Smuzhiyun }
3596*4882a593Smuzhiyun }
3597*4882a593Smuzhiyun return 0;
3598*4882a593Smuzhiyun }
3599*4882a593Smuzhiyun
dib8000_set_frontend(struct dvb_frontend * fe)3600*4882a593Smuzhiyun static int dib8000_set_frontend(struct dvb_frontend *fe)
3601*4882a593Smuzhiyun {
3602*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
3603*4882a593Smuzhiyun struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
3604*4882a593Smuzhiyun int l, i, active, time, time_slave = 0;
3605*4882a593Smuzhiyun u8 exit_condition, index_frontend;
3606*4882a593Smuzhiyun unsigned long delay, callback_time;
3607*4882a593Smuzhiyun
3608*4882a593Smuzhiyun if (c->frequency == 0) {
3609*4882a593Smuzhiyun dprintk("dib8000: must at least specify frequency\n");
3610*4882a593Smuzhiyun return 0;
3611*4882a593Smuzhiyun }
3612*4882a593Smuzhiyun
3613*4882a593Smuzhiyun if (c->bandwidth_hz == 0) {
3614*4882a593Smuzhiyun dprintk("dib8000: no bandwidth specified, set to default\n");
3615*4882a593Smuzhiyun c->bandwidth_hz = 6000000;
3616*4882a593Smuzhiyun }
3617*4882a593Smuzhiyun
3618*4882a593Smuzhiyun for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
3619*4882a593Smuzhiyun /* synchronization of the cache */
3620*4882a593Smuzhiyun state->fe[index_frontend]->dtv_property_cache.delivery_system = SYS_ISDBT;
3621*4882a593Smuzhiyun memcpy(&state->fe[index_frontend]->dtv_property_cache, &fe->dtv_property_cache, sizeof(struct dtv_frontend_properties));
3622*4882a593Smuzhiyun
3623*4882a593Smuzhiyun /* set output mode and diversity input */
3624*4882a593Smuzhiyun if (state->revision != 0x8090) {
3625*4882a593Smuzhiyun dib8000_set_diversity_in(state->fe[index_frontend], 1);
3626*4882a593Smuzhiyun if (index_frontend != 0)
3627*4882a593Smuzhiyun dib8000_set_output_mode(state->fe[index_frontend],
3628*4882a593Smuzhiyun OUTMODE_DIVERSITY);
3629*4882a593Smuzhiyun else
3630*4882a593Smuzhiyun dib8000_set_output_mode(state->fe[0], OUTMODE_HIGH_Z);
3631*4882a593Smuzhiyun } else {
3632*4882a593Smuzhiyun dib8096p_set_diversity_in(state->fe[index_frontend], 1);
3633*4882a593Smuzhiyun if (index_frontend != 0)
3634*4882a593Smuzhiyun dib8096p_set_output_mode(state->fe[index_frontend],
3635*4882a593Smuzhiyun OUTMODE_DIVERSITY);
3636*4882a593Smuzhiyun else
3637*4882a593Smuzhiyun dib8096p_set_output_mode(state->fe[0], OUTMODE_HIGH_Z);
3638*4882a593Smuzhiyun }
3639*4882a593Smuzhiyun
3640*4882a593Smuzhiyun /* tune the tuner */
3641*4882a593Smuzhiyun if (state->fe[index_frontend]->ops.tuner_ops.set_params)
3642*4882a593Smuzhiyun state->fe[index_frontend]->ops.tuner_ops.set_params(state->fe[index_frontend]);
3643*4882a593Smuzhiyun
3644*4882a593Smuzhiyun dib8000_set_tune_state(state->fe[index_frontend], CT_AGC_START);
3645*4882a593Smuzhiyun }
3646*4882a593Smuzhiyun
3647*4882a593Smuzhiyun /* turn off the diversity of the last chip */
3648*4882a593Smuzhiyun if (state->revision != 0x8090)
3649*4882a593Smuzhiyun dib8000_set_diversity_in(state->fe[index_frontend - 1], 0);
3650*4882a593Smuzhiyun else
3651*4882a593Smuzhiyun dib8096p_set_diversity_in(state->fe[index_frontend - 1], 0);
3652*4882a593Smuzhiyun
3653*4882a593Smuzhiyun /* start up the AGC */
3654*4882a593Smuzhiyun do {
3655*4882a593Smuzhiyun time = dib8000_agc_startup(state->fe[0]);
3656*4882a593Smuzhiyun for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
3657*4882a593Smuzhiyun time_slave = dib8000_agc_startup(state->fe[index_frontend]);
3658*4882a593Smuzhiyun if (time == 0)
3659*4882a593Smuzhiyun time = time_slave;
3660*4882a593Smuzhiyun else if ((time_slave != 0) && (time_slave > time))
3661*4882a593Smuzhiyun time = time_slave;
3662*4882a593Smuzhiyun }
3663*4882a593Smuzhiyun if (time == 0)
3664*4882a593Smuzhiyun break;
3665*4882a593Smuzhiyun
3666*4882a593Smuzhiyun /*
3667*4882a593Smuzhiyun * Despite dib8000_agc_startup returns time at a 0.1 ms range,
3668*4882a593Smuzhiyun * the actual sleep time depends on CONFIG_HZ. The worse case
3669*4882a593Smuzhiyun * is when CONFIG_HZ=100. In such case, the minimum granularity
3670*4882a593Smuzhiyun * is 10ms. On some real field tests, the tuner sometimes don't
3671*4882a593Smuzhiyun * lock when this timer is lower than 10ms. So, enforce a 10ms
3672*4882a593Smuzhiyun * granularity.
3673*4882a593Smuzhiyun */
3674*4882a593Smuzhiyun time = 10 * (time + 99)/100;
3675*4882a593Smuzhiyun usleep_range(time * 1000, (time + 1) * 1000);
3676*4882a593Smuzhiyun exit_condition = 1;
3677*4882a593Smuzhiyun for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
3678*4882a593Smuzhiyun if (dib8000_get_tune_state(state->fe[index_frontend]) != CT_AGC_STOP) {
3679*4882a593Smuzhiyun exit_condition = 0;
3680*4882a593Smuzhiyun break;
3681*4882a593Smuzhiyun }
3682*4882a593Smuzhiyun }
3683*4882a593Smuzhiyun } while (exit_condition == 0);
3684*4882a593Smuzhiyun
3685*4882a593Smuzhiyun for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
3686*4882a593Smuzhiyun dib8000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START);
3687*4882a593Smuzhiyun
3688*4882a593Smuzhiyun active = 1;
3689*4882a593Smuzhiyun do {
3690*4882a593Smuzhiyun callback_time = 0;
3691*4882a593Smuzhiyun for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
3692*4882a593Smuzhiyun delay = dib8000_tune(state->fe[index_frontend]);
3693*4882a593Smuzhiyun if (delay != 0) {
3694*4882a593Smuzhiyun delay = jiffies + usecs_to_jiffies(100 * delay);
3695*4882a593Smuzhiyun if (!callback_time || delay < callback_time)
3696*4882a593Smuzhiyun callback_time = delay;
3697*4882a593Smuzhiyun }
3698*4882a593Smuzhiyun
3699*4882a593Smuzhiyun /* we are in autosearch */
3700*4882a593Smuzhiyun if (state->channel_parameters_set == 0) { /* searching */
3701*4882a593Smuzhiyun if ((dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_DEMOD_SUCCESS) || (dib8000_get_status(state->fe[index_frontend]) == FE_STATUS_FFT_SUCCESS)) {
3702*4882a593Smuzhiyun dprintk("autosearch succeeded on fe%i\n", index_frontend);
3703*4882a593Smuzhiyun dib8000_get_frontend(state->fe[index_frontend], c); /* we read the channel parameters from the frontend which was successful */
3704*4882a593Smuzhiyun state->channel_parameters_set = 1;
3705*4882a593Smuzhiyun
3706*4882a593Smuzhiyun for (l = 0; (l < MAX_NUMBER_OF_FRONTENDS) && (state->fe[l] != NULL); l++) {
3707*4882a593Smuzhiyun if (l != index_frontend) { /* and for all frontend except the successful one */
3708*4882a593Smuzhiyun dprintk("Restarting frontend %d\n", l);
3709*4882a593Smuzhiyun dib8000_tune_restart_from_demod(state->fe[l]);
3710*4882a593Smuzhiyun
3711*4882a593Smuzhiyun state->fe[l]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode;
3712*4882a593Smuzhiyun state->fe[l]->dtv_property_cache.inversion = state->fe[index_frontend]->dtv_property_cache.inversion;
3713*4882a593Smuzhiyun state->fe[l]->dtv_property_cache.transmission_mode = state->fe[index_frontend]->dtv_property_cache.transmission_mode;
3714*4882a593Smuzhiyun state->fe[l]->dtv_property_cache.guard_interval = state->fe[index_frontend]->dtv_property_cache.guard_interval;
3715*4882a593Smuzhiyun state->fe[l]->dtv_property_cache.isdbt_partial_reception = state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception;
3716*4882a593Smuzhiyun for (i = 0; i < 3; i++) {
3717*4882a593Smuzhiyun state->fe[l]->dtv_property_cache.layer[i].segment_count = state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count;
3718*4882a593Smuzhiyun state->fe[l]->dtv_property_cache.layer[i].interleaving = state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving;
3719*4882a593Smuzhiyun state->fe[l]->dtv_property_cache.layer[i].fec = state->fe[index_frontend]->dtv_property_cache.layer[i].fec;
3720*4882a593Smuzhiyun state->fe[l]->dtv_property_cache.layer[i].modulation = state->fe[index_frontend]->dtv_property_cache.layer[i].modulation;
3721*4882a593Smuzhiyun }
3722*4882a593Smuzhiyun
3723*4882a593Smuzhiyun }
3724*4882a593Smuzhiyun }
3725*4882a593Smuzhiyun }
3726*4882a593Smuzhiyun }
3727*4882a593Smuzhiyun }
3728*4882a593Smuzhiyun /* tuning is done when the master frontend is done (failed or success) */
3729*4882a593Smuzhiyun if (dib8000_get_status(state->fe[0]) == FE_STATUS_TUNE_FAILED ||
3730*4882a593Smuzhiyun dib8000_get_status(state->fe[0]) == FE_STATUS_LOCKED ||
3731*4882a593Smuzhiyun dib8000_get_status(state->fe[0]) == FE_STATUS_DATA_LOCKED) {
3732*4882a593Smuzhiyun active = 0;
3733*4882a593Smuzhiyun /* we need to wait for all frontends to be finished */
3734*4882a593Smuzhiyun for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
3735*4882a593Smuzhiyun if (dib8000_get_tune_state(state->fe[index_frontend]) != CT_DEMOD_STOP)
3736*4882a593Smuzhiyun active = 1;
3737*4882a593Smuzhiyun }
3738*4882a593Smuzhiyun if (active == 0)
3739*4882a593Smuzhiyun dprintk("tuning done with status %d\n", dib8000_get_status(state->fe[0]));
3740*4882a593Smuzhiyun }
3741*4882a593Smuzhiyun
3742*4882a593Smuzhiyun if ((active == 1) && (callback_time == 0)) {
3743*4882a593Smuzhiyun dprintk("strange callback time something went wrong\n");
3744*4882a593Smuzhiyun active = 0;
3745*4882a593Smuzhiyun }
3746*4882a593Smuzhiyun
3747*4882a593Smuzhiyun while ((active == 1) && (time_before(jiffies, callback_time)))
3748*4882a593Smuzhiyun msleep(100);
3749*4882a593Smuzhiyun } while (active);
3750*4882a593Smuzhiyun
3751*4882a593Smuzhiyun /* set output mode */
3752*4882a593Smuzhiyun if (state->revision != 0x8090)
3753*4882a593Smuzhiyun dib8000_set_output_mode(state->fe[0], state->cfg.output_mode);
3754*4882a593Smuzhiyun else {
3755*4882a593Smuzhiyun dib8096p_set_output_mode(state->fe[0], state->cfg.output_mode);
3756*4882a593Smuzhiyun if (state->cfg.enMpegOutput == 0) {
3757*4882a593Smuzhiyun dib8096p_setDibTxMux(state, MPEG_ON_DIBTX);
3758*4882a593Smuzhiyun dib8096p_setHostBusMux(state, DIBTX_ON_HOSTBUS);
3759*4882a593Smuzhiyun }
3760*4882a593Smuzhiyun }
3761*4882a593Smuzhiyun
3762*4882a593Smuzhiyun return 0;
3763*4882a593Smuzhiyun }
3764*4882a593Smuzhiyun
3765*4882a593Smuzhiyun static int dib8000_get_stats(struct dvb_frontend *fe, enum fe_status stat);
3766*4882a593Smuzhiyun
dib8000_read_status(struct dvb_frontend * fe,enum fe_status * stat)3767*4882a593Smuzhiyun static int dib8000_read_status(struct dvb_frontend *fe, enum fe_status *stat)
3768*4882a593Smuzhiyun {
3769*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
3770*4882a593Smuzhiyun u16 lock_slave = 0, lock;
3771*4882a593Smuzhiyun u8 index_frontend;
3772*4882a593Smuzhiyun
3773*4882a593Smuzhiyun lock = dib8000_read_lock(fe);
3774*4882a593Smuzhiyun for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
3775*4882a593Smuzhiyun lock_slave |= dib8000_read_lock(state->fe[index_frontend]);
3776*4882a593Smuzhiyun
3777*4882a593Smuzhiyun *stat = 0;
3778*4882a593Smuzhiyun
3779*4882a593Smuzhiyun if (((lock >> 13) & 1) || ((lock_slave >> 13) & 1))
3780*4882a593Smuzhiyun *stat |= FE_HAS_SIGNAL;
3781*4882a593Smuzhiyun
3782*4882a593Smuzhiyun if (((lock >> 8) & 1) || ((lock_slave >> 8) & 1)) /* Equal */
3783*4882a593Smuzhiyun *stat |= FE_HAS_CARRIER;
3784*4882a593Smuzhiyun
3785*4882a593Smuzhiyun if ((((lock >> 1) & 0xf) == 0xf) || (((lock_slave >> 1) & 0xf) == 0xf)) /* TMCC_SYNC */
3786*4882a593Smuzhiyun *stat |= FE_HAS_SYNC;
3787*4882a593Smuzhiyun
3788*4882a593Smuzhiyun if ((((lock >> 12) & 1) || ((lock_slave >> 12) & 1)) && ((lock >> 5) & 7)) /* FEC MPEG */
3789*4882a593Smuzhiyun *stat |= FE_HAS_LOCK;
3790*4882a593Smuzhiyun
3791*4882a593Smuzhiyun if (((lock >> 12) & 1) || ((lock_slave >> 12) & 1)) {
3792*4882a593Smuzhiyun lock = dib8000_read_word(state, 554); /* Viterbi Layer A */
3793*4882a593Smuzhiyun if (lock & 0x01)
3794*4882a593Smuzhiyun *stat |= FE_HAS_VITERBI;
3795*4882a593Smuzhiyun
3796*4882a593Smuzhiyun lock = dib8000_read_word(state, 555); /* Viterbi Layer B */
3797*4882a593Smuzhiyun if (lock & 0x01)
3798*4882a593Smuzhiyun *stat |= FE_HAS_VITERBI;
3799*4882a593Smuzhiyun
3800*4882a593Smuzhiyun lock = dib8000_read_word(state, 556); /* Viterbi Layer C */
3801*4882a593Smuzhiyun if (lock & 0x01)
3802*4882a593Smuzhiyun *stat |= FE_HAS_VITERBI;
3803*4882a593Smuzhiyun }
3804*4882a593Smuzhiyun dib8000_get_stats(fe, *stat);
3805*4882a593Smuzhiyun
3806*4882a593Smuzhiyun return 0;
3807*4882a593Smuzhiyun }
3808*4882a593Smuzhiyun
dib8000_read_ber(struct dvb_frontend * fe,u32 * ber)3809*4882a593Smuzhiyun static int dib8000_read_ber(struct dvb_frontend *fe, u32 * ber)
3810*4882a593Smuzhiyun {
3811*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
3812*4882a593Smuzhiyun
3813*4882a593Smuzhiyun /* 13 segments */
3814*4882a593Smuzhiyun if (state->revision == 0x8090)
3815*4882a593Smuzhiyun *ber = (dib8000_read_word(state, 562) << 16) |
3816*4882a593Smuzhiyun dib8000_read_word(state, 563);
3817*4882a593Smuzhiyun else
3818*4882a593Smuzhiyun *ber = (dib8000_read_word(state, 560) << 16) |
3819*4882a593Smuzhiyun dib8000_read_word(state, 561);
3820*4882a593Smuzhiyun return 0;
3821*4882a593Smuzhiyun }
3822*4882a593Smuzhiyun
dib8000_read_unc_blocks(struct dvb_frontend * fe,u32 * unc)3823*4882a593Smuzhiyun static int dib8000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
3824*4882a593Smuzhiyun {
3825*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
3826*4882a593Smuzhiyun
3827*4882a593Smuzhiyun /* packet error on 13 seg */
3828*4882a593Smuzhiyun if (state->revision == 0x8090)
3829*4882a593Smuzhiyun *unc = dib8000_read_word(state, 567);
3830*4882a593Smuzhiyun else
3831*4882a593Smuzhiyun *unc = dib8000_read_word(state, 565);
3832*4882a593Smuzhiyun return 0;
3833*4882a593Smuzhiyun }
3834*4882a593Smuzhiyun
dib8000_read_signal_strength(struct dvb_frontend * fe,u16 * strength)3835*4882a593Smuzhiyun static int dib8000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
3836*4882a593Smuzhiyun {
3837*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
3838*4882a593Smuzhiyun u8 index_frontend;
3839*4882a593Smuzhiyun u16 val;
3840*4882a593Smuzhiyun
3841*4882a593Smuzhiyun *strength = 0;
3842*4882a593Smuzhiyun for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
3843*4882a593Smuzhiyun state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val);
3844*4882a593Smuzhiyun if (val > 65535 - *strength)
3845*4882a593Smuzhiyun *strength = 65535;
3846*4882a593Smuzhiyun else
3847*4882a593Smuzhiyun *strength += val;
3848*4882a593Smuzhiyun }
3849*4882a593Smuzhiyun
3850*4882a593Smuzhiyun val = 65535 - dib8000_read_word(state, 390);
3851*4882a593Smuzhiyun if (val > 65535 - *strength)
3852*4882a593Smuzhiyun *strength = 65535;
3853*4882a593Smuzhiyun else
3854*4882a593Smuzhiyun *strength += val;
3855*4882a593Smuzhiyun return 0;
3856*4882a593Smuzhiyun }
3857*4882a593Smuzhiyun
dib8000_get_snr(struct dvb_frontend * fe)3858*4882a593Smuzhiyun static u32 dib8000_get_snr(struct dvb_frontend *fe)
3859*4882a593Smuzhiyun {
3860*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
3861*4882a593Smuzhiyun u32 n, s, exp;
3862*4882a593Smuzhiyun u16 val;
3863*4882a593Smuzhiyun
3864*4882a593Smuzhiyun if (state->revision != 0x8090)
3865*4882a593Smuzhiyun val = dib8000_read_word(state, 542);
3866*4882a593Smuzhiyun else
3867*4882a593Smuzhiyun val = dib8000_read_word(state, 544);
3868*4882a593Smuzhiyun n = (val >> 6) & 0xff;
3869*4882a593Smuzhiyun exp = (val & 0x3f);
3870*4882a593Smuzhiyun if ((exp & 0x20) != 0)
3871*4882a593Smuzhiyun exp -= 0x40;
3872*4882a593Smuzhiyun n <<= exp+16;
3873*4882a593Smuzhiyun
3874*4882a593Smuzhiyun if (state->revision != 0x8090)
3875*4882a593Smuzhiyun val = dib8000_read_word(state, 543);
3876*4882a593Smuzhiyun else
3877*4882a593Smuzhiyun val = dib8000_read_word(state, 545);
3878*4882a593Smuzhiyun s = (val >> 6) & 0xff;
3879*4882a593Smuzhiyun exp = (val & 0x3f);
3880*4882a593Smuzhiyun if ((exp & 0x20) != 0)
3881*4882a593Smuzhiyun exp -= 0x40;
3882*4882a593Smuzhiyun s <<= exp+16;
3883*4882a593Smuzhiyun
3884*4882a593Smuzhiyun if (n > 0) {
3885*4882a593Smuzhiyun u32 t = (s/n) << 16;
3886*4882a593Smuzhiyun return t + ((s << 16) - n*t) / n;
3887*4882a593Smuzhiyun }
3888*4882a593Smuzhiyun return 0xffffffff;
3889*4882a593Smuzhiyun }
3890*4882a593Smuzhiyun
dib8000_read_snr(struct dvb_frontend * fe,u16 * snr)3891*4882a593Smuzhiyun static int dib8000_read_snr(struct dvb_frontend *fe, u16 * snr)
3892*4882a593Smuzhiyun {
3893*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
3894*4882a593Smuzhiyun u8 index_frontend;
3895*4882a593Smuzhiyun u32 snr_master;
3896*4882a593Smuzhiyun
3897*4882a593Smuzhiyun snr_master = dib8000_get_snr(fe);
3898*4882a593Smuzhiyun for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
3899*4882a593Smuzhiyun snr_master += dib8000_get_snr(state->fe[index_frontend]);
3900*4882a593Smuzhiyun
3901*4882a593Smuzhiyun if ((snr_master >> 16) != 0) {
3902*4882a593Smuzhiyun snr_master = 10*intlog10(snr_master>>16);
3903*4882a593Smuzhiyun *snr = snr_master / ((1 << 24) / 10);
3904*4882a593Smuzhiyun }
3905*4882a593Smuzhiyun else
3906*4882a593Smuzhiyun *snr = 0;
3907*4882a593Smuzhiyun
3908*4882a593Smuzhiyun return 0;
3909*4882a593Smuzhiyun }
3910*4882a593Smuzhiyun
3911*4882a593Smuzhiyun struct per_layer_regs {
3912*4882a593Smuzhiyun u16 lock, ber, per;
3913*4882a593Smuzhiyun };
3914*4882a593Smuzhiyun
3915*4882a593Smuzhiyun static const struct per_layer_regs per_layer_regs[] = {
3916*4882a593Smuzhiyun { 554, 560, 562 },
3917*4882a593Smuzhiyun { 555, 576, 578 },
3918*4882a593Smuzhiyun { 556, 581, 583 },
3919*4882a593Smuzhiyun };
3920*4882a593Smuzhiyun
3921*4882a593Smuzhiyun struct linear_segments {
3922*4882a593Smuzhiyun unsigned x;
3923*4882a593Smuzhiyun signed y;
3924*4882a593Smuzhiyun };
3925*4882a593Smuzhiyun
3926*4882a593Smuzhiyun /*
3927*4882a593Smuzhiyun * Table to estimate signal strength in dBm.
3928*4882a593Smuzhiyun * This table was empirically determinated by measuring the signal
3929*4882a593Smuzhiyun * strength generated by a DTA-2111 RF generator directly connected into
3930*4882a593Smuzhiyun * a dib8076 device (a PixelView PV-D231U stick), using a good quality
3931*4882a593Smuzhiyun * 3 meters RC6 cable and good RC6 connectors.
3932*4882a593Smuzhiyun * The real value can actually be different on other devices, depending
3933*4882a593Smuzhiyun * on several factors, like if LNA is enabled or not, if diversity is
3934*4882a593Smuzhiyun * enabled, type of connectors, etc.
3935*4882a593Smuzhiyun * Yet, it is better to use this measure in dB than a random non-linear
3936*4882a593Smuzhiyun * percentage value, especially for antenna adjustments.
3937*4882a593Smuzhiyun * On my tests, the precision of the measure using this table is about
3938*4882a593Smuzhiyun * 0.5 dB, with sounds reasonable enough.
3939*4882a593Smuzhiyun */
3940*4882a593Smuzhiyun static struct linear_segments strength_to_db_table[] = {
3941*4882a593Smuzhiyun { 55953, 108500 }, /* -22.5 dBm */
3942*4882a593Smuzhiyun { 55394, 108000 },
3943*4882a593Smuzhiyun { 53834, 107000 },
3944*4882a593Smuzhiyun { 52863, 106000 },
3945*4882a593Smuzhiyun { 52239, 105000 },
3946*4882a593Smuzhiyun { 52012, 104000 },
3947*4882a593Smuzhiyun { 51803, 103000 },
3948*4882a593Smuzhiyun { 51566, 102000 },
3949*4882a593Smuzhiyun { 51356, 101000 },
3950*4882a593Smuzhiyun { 51112, 100000 },
3951*4882a593Smuzhiyun { 50869, 99000 },
3952*4882a593Smuzhiyun { 50600, 98000 },
3953*4882a593Smuzhiyun { 50363, 97000 },
3954*4882a593Smuzhiyun { 50117, 96000 }, /* -35 dBm */
3955*4882a593Smuzhiyun { 49889, 95000 },
3956*4882a593Smuzhiyun { 49680, 94000 },
3957*4882a593Smuzhiyun { 49493, 93000 },
3958*4882a593Smuzhiyun { 49302, 92000 },
3959*4882a593Smuzhiyun { 48929, 91000 },
3960*4882a593Smuzhiyun { 48416, 90000 },
3961*4882a593Smuzhiyun { 48035, 89000 },
3962*4882a593Smuzhiyun { 47593, 88000 },
3963*4882a593Smuzhiyun { 47282, 87000 },
3964*4882a593Smuzhiyun { 46953, 86000 },
3965*4882a593Smuzhiyun { 46698, 85000 },
3966*4882a593Smuzhiyun { 45617, 84000 },
3967*4882a593Smuzhiyun { 44773, 83000 },
3968*4882a593Smuzhiyun { 43845, 82000 },
3969*4882a593Smuzhiyun { 43020, 81000 },
3970*4882a593Smuzhiyun { 42010, 80000 }, /* -51 dBm */
3971*4882a593Smuzhiyun { 0, 0 },
3972*4882a593Smuzhiyun };
3973*4882a593Smuzhiyun
interpolate_value(u32 value,struct linear_segments * segments,unsigned len)3974*4882a593Smuzhiyun static u32 interpolate_value(u32 value, struct linear_segments *segments,
3975*4882a593Smuzhiyun unsigned len)
3976*4882a593Smuzhiyun {
3977*4882a593Smuzhiyun u64 tmp64;
3978*4882a593Smuzhiyun u32 dx;
3979*4882a593Smuzhiyun s32 dy;
3980*4882a593Smuzhiyun int i, ret;
3981*4882a593Smuzhiyun
3982*4882a593Smuzhiyun if (value >= segments[0].x)
3983*4882a593Smuzhiyun return segments[0].y;
3984*4882a593Smuzhiyun if (value < segments[len-1].x)
3985*4882a593Smuzhiyun return segments[len-1].y;
3986*4882a593Smuzhiyun
3987*4882a593Smuzhiyun for (i = 1; i < len - 1; i++) {
3988*4882a593Smuzhiyun /* If value is identical, no need to interpolate */
3989*4882a593Smuzhiyun if (value == segments[i].x)
3990*4882a593Smuzhiyun return segments[i].y;
3991*4882a593Smuzhiyun if (value > segments[i].x)
3992*4882a593Smuzhiyun break;
3993*4882a593Smuzhiyun }
3994*4882a593Smuzhiyun
3995*4882a593Smuzhiyun /* Linear interpolation between the two (x,y) points */
3996*4882a593Smuzhiyun dy = segments[i - 1].y - segments[i].y;
3997*4882a593Smuzhiyun dx = segments[i - 1].x - segments[i].x;
3998*4882a593Smuzhiyun
3999*4882a593Smuzhiyun tmp64 = value - segments[i].x;
4000*4882a593Smuzhiyun tmp64 *= dy;
4001*4882a593Smuzhiyun do_div(tmp64, dx);
4002*4882a593Smuzhiyun ret = segments[i].y + tmp64;
4003*4882a593Smuzhiyun
4004*4882a593Smuzhiyun return ret;
4005*4882a593Smuzhiyun }
4006*4882a593Smuzhiyun
dib8000_get_time_us(struct dvb_frontend * fe,int layer)4007*4882a593Smuzhiyun static u32 dib8000_get_time_us(struct dvb_frontend *fe, int layer)
4008*4882a593Smuzhiyun {
4009*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
4010*4882a593Smuzhiyun struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
4011*4882a593Smuzhiyun int ini_layer, end_layer, i;
4012*4882a593Smuzhiyun u64 time_us, tmp64;
4013*4882a593Smuzhiyun u32 tmp, denom;
4014*4882a593Smuzhiyun int guard, rate_num, rate_denum = 1, bits_per_symbol, nsegs;
4015*4882a593Smuzhiyun int interleaving = 0, fft_div;
4016*4882a593Smuzhiyun
4017*4882a593Smuzhiyun if (layer >= 0) {
4018*4882a593Smuzhiyun ini_layer = layer;
4019*4882a593Smuzhiyun end_layer = layer + 1;
4020*4882a593Smuzhiyun } else {
4021*4882a593Smuzhiyun ini_layer = 0;
4022*4882a593Smuzhiyun end_layer = 3;
4023*4882a593Smuzhiyun }
4024*4882a593Smuzhiyun
4025*4882a593Smuzhiyun switch (c->guard_interval) {
4026*4882a593Smuzhiyun case GUARD_INTERVAL_1_4:
4027*4882a593Smuzhiyun guard = 4;
4028*4882a593Smuzhiyun break;
4029*4882a593Smuzhiyun case GUARD_INTERVAL_1_8:
4030*4882a593Smuzhiyun guard = 8;
4031*4882a593Smuzhiyun break;
4032*4882a593Smuzhiyun case GUARD_INTERVAL_1_16:
4033*4882a593Smuzhiyun guard = 16;
4034*4882a593Smuzhiyun break;
4035*4882a593Smuzhiyun default:
4036*4882a593Smuzhiyun case GUARD_INTERVAL_1_32:
4037*4882a593Smuzhiyun guard = 32;
4038*4882a593Smuzhiyun break;
4039*4882a593Smuzhiyun }
4040*4882a593Smuzhiyun
4041*4882a593Smuzhiyun switch (c->transmission_mode) {
4042*4882a593Smuzhiyun case TRANSMISSION_MODE_2K:
4043*4882a593Smuzhiyun fft_div = 4;
4044*4882a593Smuzhiyun break;
4045*4882a593Smuzhiyun case TRANSMISSION_MODE_4K:
4046*4882a593Smuzhiyun fft_div = 2;
4047*4882a593Smuzhiyun break;
4048*4882a593Smuzhiyun default:
4049*4882a593Smuzhiyun case TRANSMISSION_MODE_8K:
4050*4882a593Smuzhiyun fft_div = 1;
4051*4882a593Smuzhiyun break;
4052*4882a593Smuzhiyun }
4053*4882a593Smuzhiyun
4054*4882a593Smuzhiyun denom = 0;
4055*4882a593Smuzhiyun for (i = ini_layer; i < end_layer; i++) {
4056*4882a593Smuzhiyun nsegs = c->layer[i].segment_count;
4057*4882a593Smuzhiyun if (nsegs == 0 || nsegs > 13)
4058*4882a593Smuzhiyun continue;
4059*4882a593Smuzhiyun
4060*4882a593Smuzhiyun switch (c->layer[i].modulation) {
4061*4882a593Smuzhiyun case DQPSK:
4062*4882a593Smuzhiyun case QPSK:
4063*4882a593Smuzhiyun bits_per_symbol = 2;
4064*4882a593Smuzhiyun break;
4065*4882a593Smuzhiyun case QAM_16:
4066*4882a593Smuzhiyun bits_per_symbol = 4;
4067*4882a593Smuzhiyun break;
4068*4882a593Smuzhiyun default:
4069*4882a593Smuzhiyun case QAM_64:
4070*4882a593Smuzhiyun bits_per_symbol = 6;
4071*4882a593Smuzhiyun break;
4072*4882a593Smuzhiyun }
4073*4882a593Smuzhiyun
4074*4882a593Smuzhiyun switch (c->layer[i].fec) {
4075*4882a593Smuzhiyun case FEC_1_2:
4076*4882a593Smuzhiyun rate_num = 1;
4077*4882a593Smuzhiyun rate_denum = 2;
4078*4882a593Smuzhiyun break;
4079*4882a593Smuzhiyun case FEC_2_3:
4080*4882a593Smuzhiyun rate_num = 2;
4081*4882a593Smuzhiyun rate_denum = 3;
4082*4882a593Smuzhiyun break;
4083*4882a593Smuzhiyun case FEC_3_4:
4084*4882a593Smuzhiyun rate_num = 3;
4085*4882a593Smuzhiyun rate_denum = 4;
4086*4882a593Smuzhiyun break;
4087*4882a593Smuzhiyun case FEC_5_6:
4088*4882a593Smuzhiyun rate_num = 5;
4089*4882a593Smuzhiyun rate_denum = 6;
4090*4882a593Smuzhiyun break;
4091*4882a593Smuzhiyun default:
4092*4882a593Smuzhiyun case FEC_7_8:
4093*4882a593Smuzhiyun rate_num = 7;
4094*4882a593Smuzhiyun rate_denum = 8;
4095*4882a593Smuzhiyun break;
4096*4882a593Smuzhiyun }
4097*4882a593Smuzhiyun
4098*4882a593Smuzhiyun interleaving = c->layer[i].interleaving;
4099*4882a593Smuzhiyun
4100*4882a593Smuzhiyun denom += bits_per_symbol * rate_num * fft_div * nsegs * 384;
4101*4882a593Smuzhiyun }
4102*4882a593Smuzhiyun
4103*4882a593Smuzhiyun /* If all goes wrong, wait for 1s for the next stats */
4104*4882a593Smuzhiyun if (!denom)
4105*4882a593Smuzhiyun return 0;
4106*4882a593Smuzhiyun
4107*4882a593Smuzhiyun /* Estimate the period for the total bit rate */
4108*4882a593Smuzhiyun time_us = rate_denum * (1008 * 1562500L);
4109*4882a593Smuzhiyun tmp64 = time_us;
4110*4882a593Smuzhiyun do_div(tmp64, guard);
4111*4882a593Smuzhiyun time_us = time_us + tmp64;
4112*4882a593Smuzhiyun time_us += denom / 2;
4113*4882a593Smuzhiyun do_div(time_us, denom);
4114*4882a593Smuzhiyun
4115*4882a593Smuzhiyun tmp = 1008 * 96 * interleaving;
4116*4882a593Smuzhiyun time_us += tmp + tmp / guard;
4117*4882a593Smuzhiyun
4118*4882a593Smuzhiyun return time_us;
4119*4882a593Smuzhiyun }
4120*4882a593Smuzhiyun
dib8000_get_stats(struct dvb_frontend * fe,enum fe_status stat)4121*4882a593Smuzhiyun static int dib8000_get_stats(struct dvb_frontend *fe, enum fe_status stat)
4122*4882a593Smuzhiyun {
4123*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
4124*4882a593Smuzhiyun struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
4125*4882a593Smuzhiyun int i;
4126*4882a593Smuzhiyun int show_per_stats = 0;
4127*4882a593Smuzhiyun u32 time_us = 0, snr, val;
4128*4882a593Smuzhiyun u64 blocks;
4129*4882a593Smuzhiyun s32 db;
4130*4882a593Smuzhiyun u16 strength;
4131*4882a593Smuzhiyun
4132*4882a593Smuzhiyun /* Get Signal strength */
4133*4882a593Smuzhiyun dib8000_read_signal_strength(fe, &strength);
4134*4882a593Smuzhiyun val = strength;
4135*4882a593Smuzhiyun db = interpolate_value(val,
4136*4882a593Smuzhiyun strength_to_db_table,
4137*4882a593Smuzhiyun ARRAY_SIZE(strength_to_db_table)) - 131000;
4138*4882a593Smuzhiyun c->strength.stat[0].svalue = db;
4139*4882a593Smuzhiyun
4140*4882a593Smuzhiyun /* UCB/BER/CNR measures require lock */
4141*4882a593Smuzhiyun if (!(stat & FE_HAS_LOCK)) {
4142*4882a593Smuzhiyun c->cnr.len = 1;
4143*4882a593Smuzhiyun c->block_count.len = 1;
4144*4882a593Smuzhiyun c->block_error.len = 1;
4145*4882a593Smuzhiyun c->post_bit_error.len = 1;
4146*4882a593Smuzhiyun c->post_bit_count.len = 1;
4147*4882a593Smuzhiyun c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
4148*4882a593Smuzhiyun c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
4149*4882a593Smuzhiyun c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
4150*4882a593Smuzhiyun c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
4151*4882a593Smuzhiyun c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
4152*4882a593Smuzhiyun return 0;
4153*4882a593Smuzhiyun }
4154*4882a593Smuzhiyun
4155*4882a593Smuzhiyun /* Check if time for stats was elapsed */
4156*4882a593Smuzhiyun if (time_after(jiffies, state->per_jiffies_stats)) {
4157*4882a593Smuzhiyun state->per_jiffies_stats = jiffies + msecs_to_jiffies(1000);
4158*4882a593Smuzhiyun
4159*4882a593Smuzhiyun /* Get SNR */
4160*4882a593Smuzhiyun snr = dib8000_get_snr(fe);
4161*4882a593Smuzhiyun for (i = 1; i < MAX_NUMBER_OF_FRONTENDS; i++) {
4162*4882a593Smuzhiyun if (state->fe[i])
4163*4882a593Smuzhiyun snr += dib8000_get_snr(state->fe[i]);
4164*4882a593Smuzhiyun }
4165*4882a593Smuzhiyun snr = snr >> 16;
4166*4882a593Smuzhiyun
4167*4882a593Smuzhiyun if (snr) {
4168*4882a593Smuzhiyun snr = 10 * intlog10(snr);
4169*4882a593Smuzhiyun snr = (1000L * snr) >> 24;
4170*4882a593Smuzhiyun } else {
4171*4882a593Smuzhiyun snr = 0;
4172*4882a593Smuzhiyun }
4173*4882a593Smuzhiyun c->cnr.stat[0].svalue = snr;
4174*4882a593Smuzhiyun c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
4175*4882a593Smuzhiyun
4176*4882a593Smuzhiyun /* Get UCB measures */
4177*4882a593Smuzhiyun dib8000_read_unc_blocks(fe, &val);
4178*4882a593Smuzhiyun if (val < state->init_ucb)
4179*4882a593Smuzhiyun state->init_ucb += 0x100000000LL;
4180*4882a593Smuzhiyun
4181*4882a593Smuzhiyun c->block_error.stat[0].scale = FE_SCALE_COUNTER;
4182*4882a593Smuzhiyun c->block_error.stat[0].uvalue = val + state->init_ucb;
4183*4882a593Smuzhiyun
4184*4882a593Smuzhiyun /* Estimate the number of packets based on bitrate */
4185*4882a593Smuzhiyun if (!time_us)
4186*4882a593Smuzhiyun time_us = dib8000_get_time_us(fe, -1);
4187*4882a593Smuzhiyun
4188*4882a593Smuzhiyun if (time_us) {
4189*4882a593Smuzhiyun blocks = 1250000ULL * 1000000ULL;
4190*4882a593Smuzhiyun do_div(blocks, time_us * 8 * 204);
4191*4882a593Smuzhiyun c->block_count.stat[0].scale = FE_SCALE_COUNTER;
4192*4882a593Smuzhiyun c->block_count.stat[0].uvalue += blocks;
4193*4882a593Smuzhiyun }
4194*4882a593Smuzhiyun
4195*4882a593Smuzhiyun show_per_stats = 1;
4196*4882a593Smuzhiyun }
4197*4882a593Smuzhiyun
4198*4882a593Smuzhiyun /* Get post-BER measures */
4199*4882a593Smuzhiyun if (time_after(jiffies, state->ber_jiffies_stats)) {
4200*4882a593Smuzhiyun time_us = dib8000_get_time_us(fe, -1);
4201*4882a593Smuzhiyun state->ber_jiffies_stats = jiffies + msecs_to_jiffies((time_us + 500) / 1000);
4202*4882a593Smuzhiyun
4203*4882a593Smuzhiyun dprintk("Next all layers stats available in %u us.\n", time_us);
4204*4882a593Smuzhiyun
4205*4882a593Smuzhiyun dib8000_read_ber(fe, &val);
4206*4882a593Smuzhiyun c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
4207*4882a593Smuzhiyun c->post_bit_error.stat[0].uvalue += val;
4208*4882a593Smuzhiyun
4209*4882a593Smuzhiyun c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
4210*4882a593Smuzhiyun c->post_bit_count.stat[0].uvalue += 100000000;
4211*4882a593Smuzhiyun }
4212*4882a593Smuzhiyun
4213*4882a593Smuzhiyun if (state->revision < 0x8002)
4214*4882a593Smuzhiyun return 0;
4215*4882a593Smuzhiyun
4216*4882a593Smuzhiyun c->block_error.len = 4;
4217*4882a593Smuzhiyun c->post_bit_error.len = 4;
4218*4882a593Smuzhiyun c->post_bit_count.len = 4;
4219*4882a593Smuzhiyun
4220*4882a593Smuzhiyun for (i = 0; i < 3; i++) {
4221*4882a593Smuzhiyun unsigned nsegs = c->layer[i].segment_count;
4222*4882a593Smuzhiyun
4223*4882a593Smuzhiyun if (nsegs == 0 || nsegs > 13)
4224*4882a593Smuzhiyun continue;
4225*4882a593Smuzhiyun
4226*4882a593Smuzhiyun time_us = 0;
4227*4882a593Smuzhiyun
4228*4882a593Smuzhiyun if (time_after(jiffies, state->ber_jiffies_stats_layer[i])) {
4229*4882a593Smuzhiyun time_us = dib8000_get_time_us(fe, i);
4230*4882a593Smuzhiyun
4231*4882a593Smuzhiyun state->ber_jiffies_stats_layer[i] = jiffies + msecs_to_jiffies((time_us + 500) / 1000);
4232*4882a593Smuzhiyun dprintk("Next layer %c stats will be available in %u us\n",
4233*4882a593Smuzhiyun 'A' + i, time_us);
4234*4882a593Smuzhiyun
4235*4882a593Smuzhiyun val = dib8000_read_word(state, per_layer_regs[i].ber);
4236*4882a593Smuzhiyun c->post_bit_error.stat[1 + i].scale = FE_SCALE_COUNTER;
4237*4882a593Smuzhiyun c->post_bit_error.stat[1 + i].uvalue += val;
4238*4882a593Smuzhiyun
4239*4882a593Smuzhiyun c->post_bit_count.stat[1 + i].scale = FE_SCALE_COUNTER;
4240*4882a593Smuzhiyun c->post_bit_count.stat[1 + i].uvalue += 100000000;
4241*4882a593Smuzhiyun }
4242*4882a593Smuzhiyun
4243*4882a593Smuzhiyun if (show_per_stats) {
4244*4882a593Smuzhiyun val = dib8000_read_word(state, per_layer_regs[i].per);
4245*4882a593Smuzhiyun
4246*4882a593Smuzhiyun c->block_error.stat[1 + i].scale = FE_SCALE_COUNTER;
4247*4882a593Smuzhiyun c->block_error.stat[1 + i].uvalue += val;
4248*4882a593Smuzhiyun
4249*4882a593Smuzhiyun if (!time_us)
4250*4882a593Smuzhiyun time_us = dib8000_get_time_us(fe, i);
4251*4882a593Smuzhiyun if (time_us) {
4252*4882a593Smuzhiyun blocks = 1250000ULL * 1000000ULL;
4253*4882a593Smuzhiyun do_div(blocks, time_us * 8 * 204);
4254*4882a593Smuzhiyun c->block_count.stat[0].scale = FE_SCALE_COUNTER;
4255*4882a593Smuzhiyun c->block_count.stat[0].uvalue += blocks;
4256*4882a593Smuzhiyun }
4257*4882a593Smuzhiyun }
4258*4882a593Smuzhiyun }
4259*4882a593Smuzhiyun return 0;
4260*4882a593Smuzhiyun }
4261*4882a593Smuzhiyun
dib8000_set_slave_frontend(struct dvb_frontend * fe,struct dvb_frontend * fe_slave)4262*4882a593Smuzhiyun static int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
4263*4882a593Smuzhiyun {
4264*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
4265*4882a593Smuzhiyun u8 index_frontend = 1;
4266*4882a593Smuzhiyun
4267*4882a593Smuzhiyun while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
4268*4882a593Smuzhiyun index_frontend++;
4269*4882a593Smuzhiyun if (index_frontend < MAX_NUMBER_OF_FRONTENDS) {
4270*4882a593Smuzhiyun dprintk("set slave fe %p to index %i\n", fe_slave, index_frontend);
4271*4882a593Smuzhiyun state->fe[index_frontend] = fe_slave;
4272*4882a593Smuzhiyun return 0;
4273*4882a593Smuzhiyun }
4274*4882a593Smuzhiyun
4275*4882a593Smuzhiyun dprintk("too many slave frontend\n");
4276*4882a593Smuzhiyun return -ENOMEM;
4277*4882a593Smuzhiyun }
4278*4882a593Smuzhiyun
dib8000_get_slave_frontend(struct dvb_frontend * fe,int slave_index)4279*4882a593Smuzhiyun static struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
4280*4882a593Smuzhiyun {
4281*4882a593Smuzhiyun struct dib8000_state *state = fe->demodulator_priv;
4282*4882a593Smuzhiyun
4283*4882a593Smuzhiyun if (slave_index >= MAX_NUMBER_OF_FRONTENDS)
4284*4882a593Smuzhiyun return NULL;
4285*4882a593Smuzhiyun return state->fe[slave_index];
4286*4882a593Smuzhiyun }
4287*4882a593Smuzhiyun
dib8000_i2c_enumeration(struct i2c_adapter * host,int no_of_demods,u8 default_addr,u8 first_addr,u8 is_dib8096p)4288*4882a593Smuzhiyun static int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
4289*4882a593Smuzhiyun u8 default_addr, u8 first_addr, u8 is_dib8096p)
4290*4882a593Smuzhiyun {
4291*4882a593Smuzhiyun int k = 0, ret = 0;
4292*4882a593Smuzhiyun u8 new_addr = 0;
4293*4882a593Smuzhiyun struct i2c_device client = {.adap = host };
4294*4882a593Smuzhiyun
4295*4882a593Smuzhiyun client.i2c_write_buffer = kzalloc(4, GFP_KERNEL);
4296*4882a593Smuzhiyun if (!client.i2c_write_buffer) {
4297*4882a593Smuzhiyun dprintk("%s: not enough memory\n", __func__);
4298*4882a593Smuzhiyun return -ENOMEM;
4299*4882a593Smuzhiyun }
4300*4882a593Smuzhiyun client.i2c_read_buffer = kzalloc(4, GFP_KERNEL);
4301*4882a593Smuzhiyun if (!client.i2c_read_buffer) {
4302*4882a593Smuzhiyun dprintk("%s: not enough memory\n", __func__);
4303*4882a593Smuzhiyun ret = -ENOMEM;
4304*4882a593Smuzhiyun goto error_memory_read;
4305*4882a593Smuzhiyun }
4306*4882a593Smuzhiyun client.i2c_buffer_lock = kzalloc(sizeof(struct mutex), GFP_KERNEL);
4307*4882a593Smuzhiyun if (!client.i2c_buffer_lock) {
4308*4882a593Smuzhiyun dprintk("%s: not enough memory\n", __func__);
4309*4882a593Smuzhiyun ret = -ENOMEM;
4310*4882a593Smuzhiyun goto error_memory_lock;
4311*4882a593Smuzhiyun }
4312*4882a593Smuzhiyun mutex_init(client.i2c_buffer_lock);
4313*4882a593Smuzhiyun
4314*4882a593Smuzhiyun for (k = no_of_demods - 1; k >= 0; k--) {
4315*4882a593Smuzhiyun /* designated i2c address */
4316*4882a593Smuzhiyun new_addr = first_addr + (k << 1);
4317*4882a593Smuzhiyun
4318*4882a593Smuzhiyun client.addr = new_addr;
4319*4882a593Smuzhiyun if (!is_dib8096p)
4320*4882a593Smuzhiyun dib8000_i2c_write16(&client, 1287, 0x0003); /* sram lead in, rdy */
4321*4882a593Smuzhiyun if (dib8000_identify(&client) == 0) {
4322*4882a593Smuzhiyun /* sram lead in, rdy */
4323*4882a593Smuzhiyun if (!is_dib8096p)
4324*4882a593Smuzhiyun dib8000_i2c_write16(&client, 1287, 0x0003);
4325*4882a593Smuzhiyun client.addr = default_addr;
4326*4882a593Smuzhiyun if (dib8000_identify(&client) == 0) {
4327*4882a593Smuzhiyun dprintk("#%d: not identified\n", k);
4328*4882a593Smuzhiyun ret = -EINVAL;
4329*4882a593Smuzhiyun goto error;
4330*4882a593Smuzhiyun }
4331*4882a593Smuzhiyun }
4332*4882a593Smuzhiyun
4333*4882a593Smuzhiyun /* start diversity to pull_down div_str - just for i2c-enumeration */
4334*4882a593Smuzhiyun dib8000_i2c_write16(&client, 1286, (1 << 10) | (4 << 6));
4335*4882a593Smuzhiyun
4336*4882a593Smuzhiyun /* set new i2c address and force divstart */
4337*4882a593Smuzhiyun dib8000_i2c_write16(&client, 1285, (new_addr << 2) | 0x2);
4338*4882a593Smuzhiyun client.addr = new_addr;
4339*4882a593Smuzhiyun dib8000_identify(&client);
4340*4882a593Smuzhiyun
4341*4882a593Smuzhiyun dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr);
4342*4882a593Smuzhiyun }
4343*4882a593Smuzhiyun
4344*4882a593Smuzhiyun for (k = 0; k < no_of_demods; k++) {
4345*4882a593Smuzhiyun new_addr = first_addr | (k << 1);
4346*4882a593Smuzhiyun client.addr = new_addr;
4347*4882a593Smuzhiyun
4348*4882a593Smuzhiyun // unforce divstr
4349*4882a593Smuzhiyun dib8000_i2c_write16(&client, 1285, new_addr << 2);
4350*4882a593Smuzhiyun
4351*4882a593Smuzhiyun /* deactivate div - it was just for i2c-enumeration */
4352*4882a593Smuzhiyun dib8000_i2c_write16(&client, 1286, 0);
4353*4882a593Smuzhiyun }
4354*4882a593Smuzhiyun
4355*4882a593Smuzhiyun error:
4356*4882a593Smuzhiyun kfree(client.i2c_buffer_lock);
4357*4882a593Smuzhiyun error_memory_lock:
4358*4882a593Smuzhiyun kfree(client.i2c_read_buffer);
4359*4882a593Smuzhiyun error_memory_read:
4360*4882a593Smuzhiyun kfree(client.i2c_write_buffer);
4361*4882a593Smuzhiyun
4362*4882a593Smuzhiyun return ret;
4363*4882a593Smuzhiyun }
4364*4882a593Smuzhiyun
dib8000_fe_get_tune_settings(struct dvb_frontend * fe,struct dvb_frontend_tune_settings * tune)4365*4882a593Smuzhiyun static int dib8000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
4366*4882a593Smuzhiyun {
4367*4882a593Smuzhiyun tune->min_delay_ms = 1000;
4368*4882a593Smuzhiyun tune->step_size = 0;
4369*4882a593Smuzhiyun tune->max_drift = 0;
4370*4882a593Smuzhiyun return 0;
4371*4882a593Smuzhiyun }
4372*4882a593Smuzhiyun
dib8000_release(struct dvb_frontend * fe)4373*4882a593Smuzhiyun static void dib8000_release(struct dvb_frontend *fe)
4374*4882a593Smuzhiyun {
4375*4882a593Smuzhiyun struct dib8000_state *st = fe->demodulator_priv;
4376*4882a593Smuzhiyun u8 index_frontend;
4377*4882a593Smuzhiyun
4378*4882a593Smuzhiyun for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (st->fe[index_frontend] != NULL); index_frontend++)
4379*4882a593Smuzhiyun dvb_frontend_detach(st->fe[index_frontend]);
4380*4882a593Smuzhiyun
4381*4882a593Smuzhiyun dibx000_exit_i2c_master(&st->i2c_master);
4382*4882a593Smuzhiyun i2c_del_adapter(&st->dib8096p_tuner_adap);
4383*4882a593Smuzhiyun kfree(st->fe[0]);
4384*4882a593Smuzhiyun kfree(st);
4385*4882a593Smuzhiyun }
4386*4882a593Smuzhiyun
dib8000_get_i2c_master(struct dvb_frontend * fe,enum dibx000_i2c_interface intf,int gating)4387*4882a593Smuzhiyun static struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating)
4388*4882a593Smuzhiyun {
4389*4882a593Smuzhiyun struct dib8000_state *st = fe->demodulator_priv;
4390*4882a593Smuzhiyun return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
4391*4882a593Smuzhiyun }
4392*4882a593Smuzhiyun
dib8000_pid_filter_ctrl(struct dvb_frontend * fe,u8 onoff)4393*4882a593Smuzhiyun static int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
4394*4882a593Smuzhiyun {
4395*4882a593Smuzhiyun struct dib8000_state *st = fe->demodulator_priv;
4396*4882a593Smuzhiyun u16 val = dib8000_read_word(st, 299) & 0xffef;
4397*4882a593Smuzhiyun val |= (onoff & 0x1) << 4;
4398*4882a593Smuzhiyun
4399*4882a593Smuzhiyun dprintk("pid filter enabled %d\n", onoff);
4400*4882a593Smuzhiyun return dib8000_write_word(st, 299, val);
4401*4882a593Smuzhiyun }
4402*4882a593Smuzhiyun
dib8000_pid_filter(struct dvb_frontend * fe,u8 id,u16 pid,u8 onoff)4403*4882a593Smuzhiyun static int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
4404*4882a593Smuzhiyun {
4405*4882a593Smuzhiyun struct dib8000_state *st = fe->demodulator_priv;
4406*4882a593Smuzhiyun dprintk("Index %x, PID %d, OnOff %d\n", id, pid, onoff);
4407*4882a593Smuzhiyun return dib8000_write_word(st, 305 + id, onoff ? (1 << 13) | pid : 0);
4408*4882a593Smuzhiyun }
4409*4882a593Smuzhiyun
4410*4882a593Smuzhiyun static const struct dvb_frontend_ops dib8000_ops = {
4411*4882a593Smuzhiyun .delsys = { SYS_ISDBT },
4412*4882a593Smuzhiyun .info = {
4413*4882a593Smuzhiyun .name = "DiBcom 8000 ISDB-T",
4414*4882a593Smuzhiyun .frequency_min_hz = 44250 * kHz,
4415*4882a593Smuzhiyun .frequency_max_hz = 867250 * kHz,
4416*4882a593Smuzhiyun .frequency_stepsize_hz = 62500,
4417*4882a593Smuzhiyun .caps = FE_CAN_INVERSION_AUTO |
4418*4882a593Smuzhiyun FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
4419*4882a593Smuzhiyun FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
4420*4882a593Smuzhiyun FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
4421*4882a593Smuzhiyun FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO,
4422*4882a593Smuzhiyun },
4423*4882a593Smuzhiyun
4424*4882a593Smuzhiyun .release = dib8000_release,
4425*4882a593Smuzhiyun
4426*4882a593Smuzhiyun .init = dib8000_wakeup,
4427*4882a593Smuzhiyun .sleep = dib8000_sleep,
4428*4882a593Smuzhiyun
4429*4882a593Smuzhiyun .set_frontend = dib8000_set_frontend,
4430*4882a593Smuzhiyun .get_tune_settings = dib8000_fe_get_tune_settings,
4431*4882a593Smuzhiyun .get_frontend = dib8000_get_frontend,
4432*4882a593Smuzhiyun
4433*4882a593Smuzhiyun .read_status = dib8000_read_status,
4434*4882a593Smuzhiyun .read_ber = dib8000_read_ber,
4435*4882a593Smuzhiyun .read_signal_strength = dib8000_read_signal_strength,
4436*4882a593Smuzhiyun .read_snr = dib8000_read_snr,
4437*4882a593Smuzhiyun .read_ucblocks = dib8000_read_unc_blocks,
4438*4882a593Smuzhiyun };
4439*4882a593Smuzhiyun
dib8000_init(struct i2c_adapter * i2c_adap,u8 i2c_addr,struct dib8000_config * cfg)4440*4882a593Smuzhiyun static struct dvb_frontend *dib8000_init(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
4441*4882a593Smuzhiyun {
4442*4882a593Smuzhiyun struct dvb_frontend *fe;
4443*4882a593Smuzhiyun struct dib8000_state *state;
4444*4882a593Smuzhiyun
4445*4882a593Smuzhiyun dprintk("dib8000_init\n");
4446*4882a593Smuzhiyun
4447*4882a593Smuzhiyun state = kzalloc(sizeof(struct dib8000_state), GFP_KERNEL);
4448*4882a593Smuzhiyun if (state == NULL)
4449*4882a593Smuzhiyun return NULL;
4450*4882a593Smuzhiyun fe = kzalloc(sizeof(struct dvb_frontend), GFP_KERNEL);
4451*4882a593Smuzhiyun if (fe == NULL)
4452*4882a593Smuzhiyun goto error;
4453*4882a593Smuzhiyun
4454*4882a593Smuzhiyun memcpy(&state->cfg, cfg, sizeof(struct dib8000_config));
4455*4882a593Smuzhiyun state->i2c.adap = i2c_adap;
4456*4882a593Smuzhiyun state->i2c.addr = i2c_addr;
4457*4882a593Smuzhiyun state->i2c.i2c_write_buffer = state->i2c_write_buffer;
4458*4882a593Smuzhiyun state->i2c.i2c_read_buffer = state->i2c_read_buffer;
4459*4882a593Smuzhiyun mutex_init(&state->i2c_buffer_lock);
4460*4882a593Smuzhiyun state->i2c.i2c_buffer_lock = &state->i2c_buffer_lock;
4461*4882a593Smuzhiyun state->gpio_val = cfg->gpio_val;
4462*4882a593Smuzhiyun state->gpio_dir = cfg->gpio_dir;
4463*4882a593Smuzhiyun
4464*4882a593Smuzhiyun /* Ensure the output mode remains at the previous default if it's
4465*4882a593Smuzhiyun * not specifically set by the caller.
4466*4882a593Smuzhiyun */
4467*4882a593Smuzhiyun if ((state->cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (state->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
4468*4882a593Smuzhiyun state->cfg.output_mode = OUTMODE_MPEG2_FIFO;
4469*4882a593Smuzhiyun
4470*4882a593Smuzhiyun state->fe[0] = fe;
4471*4882a593Smuzhiyun fe->demodulator_priv = state;
4472*4882a593Smuzhiyun memcpy(&state->fe[0]->ops, &dib8000_ops, sizeof(struct dvb_frontend_ops));
4473*4882a593Smuzhiyun
4474*4882a593Smuzhiyun state->timf_default = cfg->pll->timf;
4475*4882a593Smuzhiyun
4476*4882a593Smuzhiyun if (dib8000_identify(&state->i2c) == 0) {
4477*4882a593Smuzhiyun kfree(fe);
4478*4882a593Smuzhiyun goto error;
4479*4882a593Smuzhiyun }
4480*4882a593Smuzhiyun
4481*4882a593Smuzhiyun dibx000_init_i2c_master(&state->i2c_master, DIB8000, state->i2c.adap, state->i2c.addr);
4482*4882a593Smuzhiyun
4483*4882a593Smuzhiyun /* init 8096p tuner adapter */
4484*4882a593Smuzhiyun strscpy(state->dib8096p_tuner_adap.name, "DiB8096P tuner interface",
4485*4882a593Smuzhiyun sizeof(state->dib8096p_tuner_adap.name));
4486*4882a593Smuzhiyun state->dib8096p_tuner_adap.algo = &dib8096p_tuner_xfer_algo;
4487*4882a593Smuzhiyun state->dib8096p_tuner_adap.algo_data = NULL;
4488*4882a593Smuzhiyun state->dib8096p_tuner_adap.dev.parent = state->i2c.adap->dev.parent;
4489*4882a593Smuzhiyun i2c_set_adapdata(&state->dib8096p_tuner_adap, state);
4490*4882a593Smuzhiyun i2c_add_adapter(&state->dib8096p_tuner_adap);
4491*4882a593Smuzhiyun
4492*4882a593Smuzhiyun dib8000_reset(fe);
4493*4882a593Smuzhiyun
4494*4882a593Smuzhiyun dib8000_write_word(state, 285, (dib8000_read_word(state, 285) & ~0x60) | (3 << 5)); /* ber_rs_len = 3 */
4495*4882a593Smuzhiyun state->current_demod_bw = 6000;
4496*4882a593Smuzhiyun
4497*4882a593Smuzhiyun return fe;
4498*4882a593Smuzhiyun
4499*4882a593Smuzhiyun error:
4500*4882a593Smuzhiyun kfree(state);
4501*4882a593Smuzhiyun return NULL;
4502*4882a593Smuzhiyun }
4503*4882a593Smuzhiyun
dib8000_attach(struct dib8000_ops * ops)4504*4882a593Smuzhiyun void *dib8000_attach(struct dib8000_ops *ops)
4505*4882a593Smuzhiyun {
4506*4882a593Smuzhiyun if (!ops)
4507*4882a593Smuzhiyun return NULL;
4508*4882a593Smuzhiyun
4509*4882a593Smuzhiyun ops->pwm_agc_reset = dib8000_pwm_agc_reset;
4510*4882a593Smuzhiyun ops->get_dc_power = dib8090p_get_dc_power;
4511*4882a593Smuzhiyun ops->set_gpio = dib8000_set_gpio;
4512*4882a593Smuzhiyun ops->get_slave_frontend = dib8000_get_slave_frontend;
4513*4882a593Smuzhiyun ops->set_tune_state = dib8000_set_tune_state;
4514*4882a593Smuzhiyun ops->pid_filter_ctrl = dib8000_pid_filter_ctrl;
4515*4882a593Smuzhiyun ops->get_adc_power = dib8000_get_adc_power;
4516*4882a593Smuzhiyun ops->update_pll = dib8000_update_pll;
4517*4882a593Smuzhiyun ops->tuner_sleep = dib8096p_tuner_sleep;
4518*4882a593Smuzhiyun ops->get_tune_state = dib8000_get_tune_state;
4519*4882a593Smuzhiyun ops->get_i2c_tuner = dib8096p_get_i2c_tuner;
4520*4882a593Smuzhiyun ops->set_slave_frontend = dib8000_set_slave_frontend;
4521*4882a593Smuzhiyun ops->pid_filter = dib8000_pid_filter;
4522*4882a593Smuzhiyun ops->ctrl_timf = dib8000_ctrl_timf;
4523*4882a593Smuzhiyun ops->init = dib8000_init;
4524*4882a593Smuzhiyun ops->get_i2c_master = dib8000_get_i2c_master;
4525*4882a593Smuzhiyun ops->i2c_enumeration = dib8000_i2c_enumeration;
4526*4882a593Smuzhiyun ops->set_wbd_ref = dib8000_set_wbd_ref;
4527*4882a593Smuzhiyun
4528*4882a593Smuzhiyun return ops;
4529*4882a593Smuzhiyun }
4530*4882a593Smuzhiyun EXPORT_SYMBOL(dib8000_attach);
4531*4882a593Smuzhiyun
4532*4882a593Smuzhiyun MODULE_AUTHOR("Olivier Grenie <Olivier.Grenie@parrot.com, Patrick Boettcher <patrick.boettcher@posteo.de>");
4533*4882a593Smuzhiyun MODULE_DESCRIPTION("Driver for the DiBcom 8000 ISDB-T demodulator");
4534*4882a593Smuzhiyun MODULE_LICENSE("GPL");
4535