blob: d36fa0d742598d2556a6b197dfdef2ebd5a67f23 [file] [log] [blame]
Patrick Boettchera75763f2006-10-18 08:34:16 -03001/*
2 * Linux-DVB Driver for DiBcom's second generation DiB7000P (PC).
3 *
Patrick Boettcherb6884a12007-07-27 10:08:51 -03004 * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
Patrick Boettchera75763f2006-10-18 08:34:16 -03005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, version 2.
9 */
10#include <linux/kernel.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090011#include <linux/slab.h>
Patrick Boettchera75763f2006-10-18 08:34:16 -030012#include <linux/i2c.h>
Patrick Boettcher79fcce32011-08-03 12:08:21 -030013#include <linux/mutex.h>
Patrick Boettchera75763f2006-10-18 08:34:16 -030014
Olivier Grenieef801962009-09-15 06:46:52 -030015#include "dvb_math.h"
Patrick Boettchera75763f2006-10-18 08:34:16 -030016#include "dvb_frontend.h"
17
18#include "dib7000p.h"
19
20static int debug;
21module_param(debug, int, 0644);
22MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
23
Matt Doran8f6956c2007-07-31 07:09:30 -030024static int buggy_sfn_workaround;
25module_param(buggy_sfn_workaround, int, 0644);
Patrick Boettcher8d999962007-07-31 10:36:06 -030026MODULE_PARM_DESC(buggy_sfn_workaround, "Enable work-around for buggy SFNs (default: 0)");
Matt Doran8f6956c2007-07-31 07:09:30 -030027
Patrick Boettcherb6884a12007-07-27 10:08:51 -030028#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P: "); printk(args); printk("\n"); } } while (0)
Patrick Boettchera75763f2006-10-18 08:34:16 -030029
Olivier Grenie713d54a2011-01-04 04:54:31 -030030struct i2c_device {
31 struct i2c_adapter *i2c_adap;
32 u8 i2c_addr;
33};
34
Patrick Boettchera75763f2006-10-18 08:34:16 -030035struct dib7000p_state {
36 struct dvb_frontend demod;
Olivier Grenie713d54a2011-01-04 04:54:31 -030037 struct dib7000p_config cfg;
Patrick Boettchera75763f2006-10-18 08:34:16 -030038
39 u8 i2c_addr;
Olivier Grenie713d54a2011-01-04 04:54:31 -030040 struct i2c_adapter *i2c_adap;
Patrick Boettchera75763f2006-10-18 08:34:16 -030041
42 struct dibx000_i2c_master i2c_master;
43
44 u16 wbd_ref;
45
Olivier Grenie713d54a2011-01-04 04:54:31 -030046 u8 current_band;
Patrick Boettcher904a82e2008-01-25 07:31:58 -030047 u32 current_bandwidth;
Patrick Boettchera75763f2006-10-18 08:34:16 -030048 struct dibx000_agc_config *current_agc;
49 u32 timf;
50
Olivier Grenie713d54a2011-01-04 04:54:31 -030051 u8 div_force_off:1;
52 u8 div_state:1;
Patrick Boettcher01373a52007-07-30 12:49:04 -030053 u16 div_sync_wait;
Patrick Boettcherb6884a12007-07-27 10:08:51 -030054
55 u8 agc_state;
56
Patrick Boettchera75763f2006-10-18 08:34:16 -030057 u16 gpio_dir;
58 u16 gpio_val;
Matt Doran8f6956c2007-07-31 07:09:30 -030059
Olivier Grenie713d54a2011-01-04 04:54:31 -030060 u8 sfn_workaround_active:1;
61
62#define SOC7090 0x7090
63 u16 version;
64
65 u16 tuner_enable;
66 struct i2c_adapter dib7090_tuner_adap;
Olivier Grenie5a0deee2011-05-03 12:27:33 -030067
68 /* for the I2C transfer */
69 struct i2c_msg msg[2];
70 u8 i2c_write_buffer[4];
71 u8 i2c_read_buffer[2];
Patrick Boettcher79fcce32011-08-03 12:08:21 -030072 struct mutex i2c_buffer_lock;
Olivier Grenie2e802862011-08-05 10:39:15 -030073
74 u8 input_mode_mpeg;
Patrick Boettchera75763f2006-10-18 08:34:16 -030075};
76
77enum dib7000p_power_mode {
78 DIB7000P_POWER_ALL = 0,
Patrick Boettcherb6884a12007-07-27 10:08:51 -030079 DIB7000P_POWER_ANALOG_ADC,
Patrick Boettchera75763f2006-10-18 08:34:16 -030080 DIB7000P_POWER_INTERFACE_ONLY,
81};
82
Olivier Grenie2e802862011-08-05 10:39:15 -030083/* dib7090 specific fonctions */
Olivier Grenie713d54a2011-01-04 04:54:31 -030084static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode);
85static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff);
Olivier Grenie2e802862011-08-05 10:39:15 -030086static void dib7090_setDibTxMux(struct dib7000p_state *state, int mode);
87static void dib7090_setHostBusMux(struct dib7000p_state *state, int mode);
Olivier Grenie713d54a2011-01-04 04:54:31 -030088
Patrick Boettchera75763f2006-10-18 08:34:16 -030089static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
90{
Patrick Boettcher79fcce32011-08-03 12:08:21 -030091 u16 ret;
92
93 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
94 dprintk("could not acquire lock");
95 return 0;
96 }
97
Olivier Grenie5a0deee2011-05-03 12:27:33 -030098 state->i2c_write_buffer[0] = reg >> 8;
99 state->i2c_write_buffer[1] = reg & 0xff;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300100
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300101 memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
102 state->msg[0].addr = state->i2c_addr >> 1;
103 state->msg[0].flags = 0;
104 state->msg[0].buf = state->i2c_write_buffer;
105 state->msg[0].len = 2;
106 state->msg[1].addr = state->i2c_addr >> 1;
107 state->msg[1].flags = I2C_M_RD;
108 state->msg[1].buf = state->i2c_read_buffer;
109 state->msg[1].len = 2;
110
111 if (i2c_transfer(state->i2c_adap, state->msg, 2) != 2)
Olivier Grenie713d54a2011-01-04 04:54:31 -0300112 dprintk("i2c read error on %d", reg);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300113
Patrick Boettcher79fcce32011-08-03 12:08:21 -0300114 ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1];
115 mutex_unlock(&state->i2c_buffer_lock);
116 return ret;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300117}
118
119static int dib7000p_write_word(struct dib7000p_state *state, u16 reg, u16 val)
120{
Patrick Boettcher79fcce32011-08-03 12:08:21 -0300121 int ret;
122
123 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
124 dprintk("could not acquire lock");
125 return -EINVAL;
126 }
127
Olivier Grenie5a0deee2011-05-03 12:27:33 -0300128 state->i2c_write_buffer[0] = (reg >> 8) & 0xff;
129 state->i2c_write_buffer[1] = reg & 0xff;
130 state->i2c_write_buffer[2] = (val >> 8) & 0xff;
131 state->i2c_write_buffer[3] = val & 0xff;
132
133 memset(&state->msg[0], 0, sizeof(struct i2c_msg));
134 state->msg[0].addr = state->i2c_addr >> 1;
135 state->msg[0].flags = 0;
136 state->msg[0].buf = state->i2c_write_buffer;
137 state->msg[0].len = 4;
138
Patrick Boettcher79fcce32011-08-03 12:08:21 -0300139 ret = (i2c_transfer(state->i2c_adap, state->msg, 1) != 1 ?
140 -EREMOTEIO : 0);
141 mutex_unlock(&state->i2c_buffer_lock);
142 return ret;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300143}
Olivier Grenie713d54a2011-01-04 04:54:31 -0300144
145static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf)
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300146{
147 u16 l = 0, r, *n;
148 n = buf;
149 l = *n++;
150 while (l) {
151 r = *n++;
152
153 do {
154 dib7000p_write_word(state, r, *n++);
155 r++;
156 } while (--l);
157 l = *n++;
158 }
159}
160
Patrick Boettchera75763f2006-10-18 08:34:16 -0300161static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode)
162{
Olivier Grenie713d54a2011-01-04 04:54:31 -0300163 int ret = 0;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300164 u16 outreg, fifo_threshold, smo_mode;
165
166 outreg = 0;
167 fifo_threshold = 1792;
Olivier Grenieeac1fe12009-09-23 13:41:27 -0300168 smo_mode = (dib7000p_read_word(state, 235) & 0x0050) | (1 << 1);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300169
Olivier Grenie713d54a2011-01-04 04:54:31 -0300170 dprintk("setting output mode for demod %p to %d", &state->demod, mode);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300171
172 switch (mode) {
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300173 case OUTMODE_MPEG2_PAR_GATED_CLK:
Olivier Grenie713d54a2011-01-04 04:54:31 -0300174 outreg = (1 << 10); /* 0x0400 */
175 break;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300176 case OUTMODE_MPEG2_PAR_CONT_CLK:
Olivier Grenie713d54a2011-01-04 04:54:31 -0300177 outreg = (1 << 10) | (1 << 6); /* 0x0440 */
178 break;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300179 case OUTMODE_MPEG2_SERIAL:
Olivier Grenie713d54a2011-01-04 04:54:31 -0300180 outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0480 */
181 break;
182 case OUTMODE_DIVERSITY:
183 if (state->cfg.hostbus_diversity)
184 outreg = (1 << 10) | (4 << 6); /* 0x0500 */
185 else
186 outreg = (1 << 11);
187 break;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300188 case OUTMODE_MPEG2_FIFO:
Olivier Grenie713d54a2011-01-04 04:54:31 -0300189 smo_mode |= (3 << 1);
190 fifo_threshold = 512;
191 outreg = (1 << 10) | (5 << 6);
192 break;
193 case OUTMODE_ANALOG_ADC:
194 outreg = (1 << 10) | (3 << 6);
195 break;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300196 case OUTMODE_HIGH_Z:
Olivier Grenie713d54a2011-01-04 04:54:31 -0300197 outreg = 0;
198 break;
199 default:
200 dprintk("Unhandled output_mode passed to be set for demod %p", &state->demod);
201 break;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300202 }
203
204 if (state->cfg.output_mpeg2_in_188_bytes)
Olivier Grenie713d54a2011-01-04 04:54:31 -0300205 smo_mode |= (1 << 5);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300206
Olivier Grenie713d54a2011-01-04 04:54:31 -0300207 ret |= dib7000p_write_word(state, 235, smo_mode);
208 ret |= dib7000p_write_word(state, 236, fifo_threshold); /* synchronous fread */
209 if (state->version != SOC7090)
210 ret |= dib7000p_write_word(state, 1286, outreg); /* P_Div_active */
Patrick Boettchera75763f2006-10-18 08:34:16 -0300211
212 return ret;
213}
214
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300215static int dib7000p_set_diversity_in(struct dvb_frontend *demod, int onoff)
216{
217 struct dib7000p_state *state = demod->demodulator_priv;
218
219 if (state->div_force_off) {
Olivier Grenie713d54a2011-01-04 04:54:31 -0300220 dprintk("diversity combination deactivated - forced by COFDM parameters");
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300221 onoff = 0;
Olivier Grenieeac1fe12009-09-23 13:41:27 -0300222 dib7000p_write_word(state, 207, 0);
223 } else
224 dib7000p_write_word(state, 207, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0));
225
Olivier Grenie713d54a2011-01-04 04:54:31 -0300226 state->div_state = (u8) onoff;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300227
228 if (onoff) {
229 dib7000p_write_word(state, 204, 6);
230 dib7000p_write_word(state, 205, 16);
231 /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300232 } else {
233 dib7000p_write_word(state, 204, 1);
234 dib7000p_write_word(state, 205, 0);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300235 }
236
237 return 0;
238}
239
Patrick Boettchera75763f2006-10-18 08:34:16 -0300240static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_power_mode mode)
241{
242 /* by default everything is powered off */
Olivier Grenie713d54a2011-01-04 04:54:31 -0300243 u16 reg_774 = 0x3fff, reg_775 = 0xffff, reg_776 = 0x0007, reg_899 = 0x0003, reg_1280 = (0xfe00) | (dib7000p_read_word(state, 1280) & 0x01ff);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300244
245 /* now, depending on the requested mode, we power on */
246 switch (mode) {
247 /* power up everything in the demod */
Olivier Grenie713d54a2011-01-04 04:54:31 -0300248 case DIB7000P_POWER_ALL:
249 reg_774 = 0x0000;
250 reg_775 = 0x0000;
251 reg_776 = 0x0;
252 reg_899 = 0x0;
253 if (state->version == SOC7090)
254 reg_1280 &= 0x001f;
255 else
256 reg_1280 &= 0x01ff;
257 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300258
Olivier Grenie713d54a2011-01-04 04:54:31 -0300259 case DIB7000P_POWER_ANALOG_ADC:
260 /* dem, cfg, iqc, sad, agc */
261 reg_774 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10) | (1 << 9));
262 /* nud */
263 reg_776 &= ~((1 << 0));
264 /* Dout */
265 if (state->version != SOC7090)
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300266 reg_1280 &= ~((1 << 11));
Olivier Grenie713d54a2011-01-04 04:54:31 -0300267 reg_1280 &= ~(1 << 6);
268 /* fall through wanted to enable the interfaces */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300269
Patrick Boettchera75763f2006-10-18 08:34:16 -0300270 /* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */
Olivier Grenie713d54a2011-01-04 04:54:31 -0300271 case DIB7000P_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C */
272 if (state->version == SOC7090)
273 reg_1280 &= ~((1 << 7) | (1 << 5));
274 else
Patrick Boettchera75763f2006-10-18 08:34:16 -0300275 reg_1280 &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 10));
Olivier Grenie713d54a2011-01-04 04:54:31 -0300276 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300277
Patrick Boettchera75763f2006-10-18 08:34:16 -0300278/* TODO following stuff is just converted from the dib7000-driver - check when is used what */
279 }
280
Olivier Grenie713d54a2011-01-04 04:54:31 -0300281 dib7000p_write_word(state, 774, reg_774);
282 dib7000p_write_word(state, 775, reg_775);
283 dib7000p_write_word(state, 776, reg_776);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300284 dib7000p_write_word(state, 1280, reg_1280);
Olivier Grenie2e802862011-08-05 10:39:15 -0300285 if (state->version != SOC7090)
286 dib7000p_write_word(state, 899, reg_899);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300287
288 return 0;
289}
290
291static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_adc_states no)
292{
Olivier Grenie2e802862011-08-05 10:39:15 -0300293 u16 reg_908 = 0, reg_909 = 0;
Olivier Grenie713d54a2011-01-04 04:54:31 -0300294 u16 reg;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300295
Olivier Grenie2e802862011-08-05 10:39:15 -0300296 if (state->version != SOC7090) {
297 reg_908 = dib7000p_read_word(state, 908);
298 reg_909 = dib7000p_read_word(state, 909);
299 }
300
Patrick Boettchera75763f2006-10-18 08:34:16 -0300301 switch (no) {
Olivier Grenie713d54a2011-01-04 04:54:31 -0300302 case DIBX000_SLOW_ADC_ON:
303 if (state->version == SOC7090) {
304 reg = dib7000p_read_word(state, 1925);
305
306 dib7000p_write_word(state, 1925, reg | (1 << 4) | (1 << 2)); /* en_slowAdc = 1 & reset_sladc = 1 */
307
308 reg = dib7000p_read_word(state, 1925); /* read acces to make it works... strange ... */
309 msleep(200);
310 dib7000p_write_word(state, 1925, reg & ~(1 << 4)); /* en_slowAdc = 1 & reset_sladc = 0 */
311
312 reg = dib7000p_read_word(state, 72) & ~((0x3 << 14) | (0x3 << 12));
313 dib7000p_write_word(state, 72, reg | (1 << 14) | (3 << 12) | 524); /* ref = Vin1 => Vbg ; sel = Vin0 or Vin3 ; (Vin2 = Vcm) */
314 } else {
Patrick Boettchera75763f2006-10-18 08:34:16 -0300315 reg_909 |= (1 << 1) | (1 << 0);
316 dib7000p_write_word(state, 909, reg_909);
317 reg_909 &= ~(1 << 1);
Olivier Grenie713d54a2011-01-04 04:54:31 -0300318 }
319 break;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300320
Olivier Grenie713d54a2011-01-04 04:54:31 -0300321 case DIBX000_SLOW_ADC_OFF:
322 if (state->version == SOC7090) {
323 reg = dib7000p_read_word(state, 1925);
324 dib7000p_write_word(state, 1925, (reg & ~(1 << 2)) | (1 << 4)); /* reset_sladc = 1 en_slowAdc = 0 */
325 } else
326 reg_909 |= (1 << 1) | (1 << 0);
327 break;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300328
Olivier Grenie713d54a2011-01-04 04:54:31 -0300329 case DIBX000_ADC_ON:
330 reg_908 &= 0x0fff;
331 reg_909 &= 0x0003;
332 break;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300333
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300334 case DIBX000_ADC_OFF:
Olivier Grenie713d54a2011-01-04 04:54:31 -0300335 reg_908 |= (1 << 14) | (1 << 13) | (1 << 12);
336 reg_909 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
337 break;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300338
Olivier Grenie713d54a2011-01-04 04:54:31 -0300339 case DIBX000_VBG_ENABLE:
340 reg_908 &= ~(1 << 15);
341 break;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300342
Olivier Grenie713d54a2011-01-04 04:54:31 -0300343 case DIBX000_VBG_DISABLE:
344 reg_908 |= (1 << 15);
345 break;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300346
Olivier Grenie713d54a2011-01-04 04:54:31 -0300347 default:
348 break;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300349 }
350
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300351// dprintk( "908: %x, 909: %x\n", reg_908, reg_909);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300352
Olivier Grenie970d14c2010-09-07 12:50:46 -0300353 reg_909 |= (state->cfg.disable_sample_and_hold & 1) << 4;
Olivier Grenie90e12ce2010-09-07 12:50:45 -0300354 reg_908 |= (state->cfg.enable_current_mirror & 1) << 7;
355
Olivier Grenie2e802862011-08-05 10:39:15 -0300356 if (state->version != SOC7090) {
357 dib7000p_write_word(state, 908, reg_908);
358 dib7000p_write_word(state, 909, reg_909);
359 }
Patrick Boettchera75763f2006-10-18 08:34:16 -0300360}
361
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300362static int dib7000p_set_bandwidth(struct dib7000p_state *state, u32 bw)
Patrick Boettchera75763f2006-10-18 08:34:16 -0300363{
Patrick Boettchera75763f2006-10-18 08:34:16 -0300364 u32 timf;
365
366 // store the current bandwidth for later use
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300367 state->current_bandwidth = bw;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300368
369 if (state->timf == 0) {
Olivier Grenie713d54a2011-01-04 04:54:31 -0300370 dprintk("using default timf");
Patrick Boettchera75763f2006-10-18 08:34:16 -0300371 timf = state->cfg.bw->timf;
372 } else {
Olivier Grenie713d54a2011-01-04 04:54:31 -0300373 dprintk("using updated timf");
Patrick Boettchera75763f2006-10-18 08:34:16 -0300374 timf = state->timf;
375 }
376
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300377 timf = timf * (bw / 50) / 160;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300378
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300379 dib7000p_write_word(state, 23, (u16) ((timf >> 16) & 0xffff));
Olivier Grenie713d54a2011-01-04 04:54:31 -0300380 dib7000p_write_word(state, 24, (u16) ((timf) & 0xffff));
Patrick Boettchera75763f2006-10-18 08:34:16 -0300381
382 return 0;
383}
384
385static int dib7000p_sad_calib(struct dib7000p_state *state)
386{
387/* internal */
Patrick Boettchera75763f2006-10-18 08:34:16 -0300388 dib7000p_write_word(state, 73, (0 << 1) | (0 << 0));
Olivier Grenie713d54a2011-01-04 04:54:31 -0300389
390 if (state->version == SOC7090)
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300391 dib7000p_write_word(state, 74, 2048);
Olivier Grenie713d54a2011-01-04 04:54:31 -0300392 else
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300393 dib7000p_write_word(state, 74, 776);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300394
395 /* do the calibration */
396 dib7000p_write_word(state, 73, (1 << 0));
397 dib7000p_write_word(state, 73, (0 << 0));
398
399 msleep(1);
400
401 return 0;
402}
403
Mauro Carvalho Chehab8abe4a02014-05-29 09:20:15 -0300404static int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
Patrick Boettcher01373a52007-07-30 12:49:04 -0300405{
406 struct dib7000p_state *state = demod->demodulator_priv;
407 if (value > 4095)
408 value = 4095;
409 state->wbd_ref = value;
410 return dib7000p_write_word(state, 105, (dib7000p_read_word(state, 105) & 0xf000) | value);
411}
Olivier Grenie713d54a2011-01-04 04:54:31 -0300412
Mauro Carvalho Chehab8abe4a02014-05-29 09:20:15 -0300413static int dib7000p_get_agc_values(struct dvb_frontend *fe,
Olivier Grenie6724a2f2011-08-05 13:49:33 -0300414 u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
415{
416 struct dib7000p_state *state = fe->demodulator_priv;
417
418 if (agc_global != NULL)
419 *agc_global = dib7000p_read_word(state, 394);
420 if (agc1 != NULL)
421 *agc1 = dib7000p_read_word(state, 392);
422 if (agc2 != NULL)
423 *agc2 = dib7000p_read_word(state, 393);
424 if (wbd != NULL)
425 *wbd = dib7000p_read_word(state, 397);
426
427 return 0;
428}
Olivier Grenie6724a2f2011-08-05 13:49:33 -0300429
Mauro Carvalho Chehab8abe4a02014-05-29 09:20:15 -0300430static int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
Olivier Grenie6fe10992012-12-31 09:23:26 -0300431{
432 struct dib7000p_state *state = fe->demodulator_priv;
433 return dib7000p_write_word(state, 108, v);
434}
Olivier Grenie6fe10992012-12-31 09:23:26 -0300435
Patrick Boettchera75763f2006-10-18 08:34:16 -0300436static void dib7000p_reset_pll(struct dib7000p_state *state)
437{
438 struct dibx000_bandwidth_config *bw = &state->cfg.bw[0];
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300439 u16 clk_cfg0;
Patrick Boettchera75763f2006-10-18 08:34:16 -0300440
Olivier Grenie713d54a2011-01-04 04:54:31 -0300441 if (state->version == SOC7090) {
442 dib7000p_write_word(state, 1856, (!bw->pll_reset << 13) | (bw->pll_range << 12) | (bw->pll_ratio << 6) | (bw->pll_prediv));
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300443
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300444 while (((dib7000p_read_word(state, 1856) >> 15) & 0x1) != 1)
445 ;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300446
Olivier Grenie713d54a2011-01-04 04:54:31 -0300447 dib7000p_write_word(state, 1857, dib7000p_read_word(state, 1857) | (!bw->pll_bypass << 15));
448 } else {
449 /* force PLL bypass */
450 clk_cfg0 = (1 << 15) | ((bw->pll_ratio & 0x3f) << 9) |
451 (bw->modulo << 7) | (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300452
Olivier Grenie713d54a2011-01-04 04:54:31 -0300453 dib7000p_write_word(state, 900, clk_cfg0);
454
455 /* P_pll_cfg */
456 dib7000p_write_word(state, 903, (bw->pll_prediv << 5) | (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset);
457 clk_cfg0 = (bw->pll_bypass << 15) | (clk_cfg0 & 0x7fff);
458 dib7000p_write_word(state, 900, clk_cfg0);
459 }
460
461 dib7000p_write_word(state, 18, (u16) (((bw->internal * 1000) >> 16) & 0xffff));
462 dib7000p_write_word(state, 19, (u16) ((bw->internal * 1000) & 0xffff));
463 dib7000p_write_word(state, 21, (u16) ((bw->ifreq >> 16) & 0xffff));
464 dib7000p_write_word(state, 22, (u16) ((bw->ifreq) & 0xffff));
Patrick Boettchera75763f2006-10-18 08:34:16 -0300465
466 dib7000p_write_word(state, 72, bw->sad_cfg);
467}
468
Olivier Grenie713d54a2011-01-04 04:54:31 -0300469static u32 dib7000p_get_internal_freq(struct dib7000p_state *state)
470{
471 u32 internal = (u32) dib7000p_read_word(state, 18) << 16;
472 internal |= (u32) dib7000p_read_word(state, 19);
473 internal /= 1000;
474
475 return internal;
476}
477
Mauro Carvalho Chehab8abe4a02014-05-29 09:20:15 -0300478static int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
Olivier Grenie713d54a2011-01-04 04:54:31 -0300479{
480 struct dib7000p_state *state = fe->demodulator_priv;
481 u16 reg_1857, reg_1856 = dib7000p_read_word(state, 1856);
482 u8 loopdiv, prediv;
483 u32 internal, xtal;
484
485 /* get back old values */
486 prediv = reg_1856 & 0x3f;
487 loopdiv = (reg_1856 >> 6) & 0x3f;
488
489 if ((bw != NULL) && (bw->pll_prediv != prediv || bw->pll_ratio != loopdiv)) {
490 dprintk("Updating pll (prediv: old = %d new = %d ; loopdiv : old = %d new = %d)", prediv, bw->pll_prediv, loopdiv, bw->pll_ratio);
491 reg_1856 &= 0xf000;
492 reg_1857 = dib7000p_read_word(state, 1857);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300493 dib7000p_write_word(state, 1857, reg_1857 & ~(1 << 15));
Olivier Grenie713d54a2011-01-04 04:54:31 -0300494
495 dib7000p_write_word(state, 1856, reg_1856 | ((bw->pll_ratio & 0x3f) << 6) | (bw->pll_prediv & 0x3f));
496
497 /* write new system clk into P_sec_len */
498 internal = dib7000p_get_internal_freq(state);
499 xtal = (internal / loopdiv) * prediv;
500 internal = 1000 * (xtal / bw->pll_prediv) * bw->pll_ratio; /* new internal */
501 dib7000p_write_word(state, 18, (u16) ((internal >> 16) & 0xffff));
502 dib7000p_write_word(state, 19, (u16) (internal & 0xffff));
503
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300504 dib7000p_write_word(state, 1857, reg_1857 | (1 << 15));
Olivier Grenie713d54a2011-01-04 04:54:31 -0300505
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300506 while (((dib7000p_read_word(state, 1856) >> 15) & 0x1) != 1)
Olivier Grenie713d54a2011-01-04 04:54:31 -0300507 dprintk("Waiting for PLL to lock");
Olivier Grenie713d54a2011-01-04 04:54:31 -0300508
509 return 0;
510 }
511 return -EIO;
512}
Olivier Grenie713d54a2011-01-04 04:54:31 -0300513
Patrick Boettchera75763f2006-10-18 08:34:16 -0300514static int dib7000p_reset_gpio(struct dib7000p_state *st)
515{
516 /* reset the GPIOs */
Olivier Grenie713d54a2011-01-04 04:54:31 -0300517 dprintk("gpio dir: %x: val: %x, pwm_pos: %x", st->gpio_dir, st->gpio_val, st->cfg.gpio_pwm_pos);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300518
519 dib7000p_write_word(st, 1029, st->gpio_dir);
520 dib7000p_write_word(st, 1030, st->gpio_val);
521
522 /* TODO 1031 is P_gpio_od */
523
524 dib7000p_write_word(st, 1032, st->cfg.gpio_pwm_pos);
525
526 dib7000p_write_word(st, 1037, st->cfg.pwm_freq_div);
527 return 0;
528}
529
Patrick Boettcher01373a52007-07-30 12:49:04 -0300530static int dib7000p_cfg_gpio(struct dib7000p_state *st, u8 num, u8 dir, u8 val)
531{
532 st->gpio_dir = dib7000p_read_word(st, 1029);
Olivier Grenie713d54a2011-01-04 04:54:31 -0300533 st->gpio_dir &= ~(1 << num); /* reset the direction bit */
534 st->gpio_dir |= (dir & 0x1) << num; /* set the new direction */
Patrick Boettcher01373a52007-07-30 12:49:04 -0300535 dib7000p_write_word(st, 1029, st->gpio_dir);
536
537 st->gpio_val = dib7000p_read_word(st, 1030);
Olivier Grenie713d54a2011-01-04 04:54:31 -0300538 st->gpio_val &= ~(1 << num); /* reset the direction bit */
539 st->gpio_val |= (val & 0x01) << num; /* set the new value */
Patrick Boettcher01373a52007-07-30 12:49:04 -0300540 dib7000p_write_word(st, 1030, st->gpio_val);
541
542 return 0;
543}
544
Mauro Carvalho Chehab8abe4a02014-05-29 09:20:15 -0300545static int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
Patrick Boettcher01373a52007-07-30 12:49:04 -0300546{
547 struct dib7000p_state *state = demod->demodulator_priv;
548 return dib7000p_cfg_gpio(state, num, dir, val);
549}
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300550
Olivier Grenie713d54a2011-01-04 04:54:31 -0300551static u16 dib7000p_defaults[] = {
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300552 // auto search configuration
553 3, 2,
Olivier Grenie713d54a2011-01-04 04:54:31 -0300554 0x0004,
Olivier Grenie2e802862011-08-05 10:39:15 -0300555 (1<<3)|(1<<11)|(1<<12)|(1<<13),
Olivier Grenie713d54a2011-01-04 04:54:31 -0300556 0x0814, /* Equal Lock */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300557
558 12, 6,
Olivier Grenie713d54a2011-01-04 04:54:31 -0300559 0x001b,
560 0x7740,
561 0x005b,
562 0x8d80,
563 0x01c9,
564 0xc380,
565 0x0000,
566 0x0080,
567 0x0000,
568 0x0090,
569 0x0001,
570 0xd4c0,
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300571
572 1, 26,
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300573 0x6680,
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300574
575 /* set ADC level to -16 */
576 11, 79,
Olivier Grenie713d54a2011-01-04 04:54:31 -0300577 (1 << 13) - 825 - 117,
578 (1 << 13) - 837 - 117,
579 (1 << 13) - 811 - 117,
580 (1 << 13) - 766 - 117,
581 (1 << 13) - 737 - 117,
582 (1 << 13) - 693 - 117,
583 (1 << 13) - 648 - 117,
584 (1 << 13) - 619 - 117,
585 (1 << 13) - 575 - 117,
586 (1 << 13) - 531 - 117,
587 (1 << 13) - 501 - 117,
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300588
589 1, 142,
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300590 0x0410,
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300591
592 /* disable power smoothing */
593 8, 145,
Olivier Grenie713d54a2011-01-04 04:54:31 -0300594 0,
595 0,
596 0,
597 0,
598 0,
599 0,
600 0,
601 0,
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300602
603 1, 154,
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300604 1 << 13,
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300605
606 1, 168,
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300607 0x0ccd,
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300608
609 1, 183,
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300610 0x200f,
Olivier Grenie713d54a2011-01-04 04:54:31 -0300611
612 1, 212,
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300613 0x169,
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300614
615 5, 187,
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300616 0x023d,
617 0x00a4,
618 0x00a4,
619 0x7ff0,
620 0x3ccc,
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300621
622 1, 198,
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300623 0x800,
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300624
625 1, 222,
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300626 0x0010,
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300627
628 1, 235,
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300629 0x0062,
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300630
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300631 0,
632};
633
Patrick Boettchera75763f2006-10-18 08:34:16 -0300634static int dib7000p_demod_reset(struct dib7000p_state *state)
635{
636 dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
637
Olivier Grenie713d54a2011-01-04 04:54:31 -0300638 if (state->version == SOC7090)
639 dibx000_reset_i2c_master(&state->i2c_master);
640
Patrick Boettchera75763f2006-10-18 08:34:16 -0300641 dib7000p_set_adc_state(state, DIBX000_VBG_ENABLE);
642
643 /* restart all parts */
Olivier Grenie713d54a2011-01-04 04:54:31 -0300644 dib7000p_write_word(state, 770, 0xffff);
645 dib7000p_write_word(state, 771, 0xffff);
646 dib7000p_write_word(state, 772, 0x001f);
Olivier Grenie713d54a2011-01-04 04:54:31 -0300647 dib7000p_write_word(state, 1280, 0x001f - ((1 << 4) | (1 << 3)));
Patrick Boettchera75763f2006-10-18 08:34:16 -0300648
Olivier Grenie713d54a2011-01-04 04:54:31 -0300649 dib7000p_write_word(state, 770, 0);
650 dib7000p_write_word(state, 771, 0);
651 dib7000p_write_word(state, 772, 0);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300652 dib7000p_write_word(state, 1280, 0);
653
Olivier Grenie2e802862011-08-05 10:39:15 -0300654 if (state->version != SOC7090) {
655 dib7000p_write_word(state, 898, 0x0003);
656 dib7000p_write_word(state, 898, 0);
657 }
658
Patrick Boettchera75763f2006-10-18 08:34:16 -0300659 /* default */
660 dib7000p_reset_pll(state);
661
662 if (dib7000p_reset_gpio(state) != 0)
Olivier Grenie713d54a2011-01-04 04:54:31 -0300663 dprintk("GPIO reset was not successful.");
Patrick Boettchera75763f2006-10-18 08:34:16 -0300664
Olivier Grenie713d54a2011-01-04 04:54:31 -0300665 if (state->version == SOC7090) {
666 dib7000p_write_word(state, 899, 0);
667
668 /* impulse noise */
669 dib7000p_write_word(state, 42, (1<<5) | 3); /* P_iqc_thsat_ipc = 1 ; P_iqc_win2 = 3 */
670 dib7000p_write_word(state, 43, 0x2d4); /*-300 fag P_iqc_dect_min = -280 */
671 dib7000p_write_word(state, 44, 300); /* 300 fag P_iqc_dect_min = +280 */
Olivier Grenie2e802862011-08-05 10:39:15 -0300672 dib7000p_write_word(state, 273, (0<<6) | 30);
Olivier Grenie713d54a2011-01-04 04:54:31 -0300673 }
Patrick Boettchera75763f2006-10-18 08:34:16 -0300674 if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
Olivier Grenie713d54a2011-01-04 04:54:31 -0300675 dprintk("OUTPUT_MODE could not be reset.");
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300676
677 dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
678 dib7000p_sad_calib(state);
679 dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
680
Olivier Grenie713d54a2011-01-04 04:54:31 -0300681 /* unforce divstr regardless whether i2c enumeration was done or not */
682 dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1));
683
684 dib7000p_set_bandwidth(state, 8000);
685
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300686 if (state->version == SOC7090) {
Olivier Grenie2e802862011-08-05 10:39:15 -0300687 dib7000p_write_word(state, 36, 0x0755);/* P_iqc_impnc_on =1 & P_iqc_corr_inh = 1 for impulsive noise */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300688 } else {
Olivier Grenie713d54a2011-01-04 04:54:31 -0300689 if (state->cfg.tuner_is_baseband)
690 dib7000p_write_word(state, 36, 0x0755);
691 else
692 dib7000p_write_word(state, 36, 0x1f55);
693 }
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300694
695 dib7000p_write_tab(state, dib7000p_defaults);
Olivier Grenie2e802862011-08-05 10:39:15 -0300696 if (state->version != SOC7090) {
697 dib7000p_write_word(state, 901, 0x0006);
698 dib7000p_write_word(state, 902, (3 << 10) | (1 << 6));
699 dib7000p_write_word(state, 905, 0x2c8e);
700 }
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300701
Patrick Boettchera75763f2006-10-18 08:34:16 -0300702 dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
703
704 return 0;
705}
706
Patrick Boettchera75763f2006-10-18 08:34:16 -0300707static void dib7000p_pll_clk_cfg(struct dib7000p_state *state)
708{
709 u16 tmp = 0;
710 tmp = dib7000p_read_word(state, 903);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300711 dib7000p_write_word(state, 903, (tmp | 0x1));
Patrick Boettchera75763f2006-10-18 08:34:16 -0300712 tmp = dib7000p_read_word(state, 900);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300713 dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6));
Patrick Boettchera75763f2006-10-18 08:34:16 -0300714}
715
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300716static void dib7000p_restart_agc(struct dib7000p_state *state)
Patrick Boettchera75763f2006-10-18 08:34:16 -0300717{
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300718 // P_restart_iqc & P_restart_agc
719 dib7000p_write_word(state, 770, (1 << 11) | (1 << 9));
720 dib7000p_write_word(state, 770, 0x0000);
Patrick Boettchera75763f2006-10-18 08:34:16 -0300721}
722
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300723static int dib7000p_update_lna(struct dib7000p_state *state)
Patrick Boettchera75763f2006-10-18 08:34:16 -0300724{
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300725 u16 dyn_gain;
726
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300727 if (state->cfg.update_lna) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300728 dyn_gain = dib7000p_read_word(state, 394);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300729 if (state->cfg.update_lna(&state->demod, dyn_gain)) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300730 dib7000p_restart_agc(state);
731 return 1;
732 }
733 }
734
735 return 0;
736}
737
738static int dib7000p_set_agc_config(struct dib7000p_state *state, u8 band)
739{
740 struct dibx000_agc_config *agc = NULL;
741 int i;
742 if (state->current_band == band && state->current_agc != NULL)
743 return 0;
744 state->current_band = band;
745
746 for (i = 0; i < state->cfg.agc_config_count; i++)
747 if (state->cfg.agc[i].band_caps & band) {
748 agc = &state->cfg.agc[i];
749 break;
750 }
751
752 if (agc == NULL) {
Olivier Grenie713d54a2011-01-04 04:54:31 -0300753 dprintk("no valid AGC configuration found for band 0x%02x", band);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300754 return -EINVAL;
755 }
756
757 state->current_agc = agc;
758
759 /* AGC */
Olivier Grenie713d54a2011-01-04 04:54:31 -0300760 dib7000p_write_word(state, 75, agc->setup);
761 dib7000p_write_word(state, 76, agc->inv_gain);
762 dib7000p_write_word(state, 77, agc->time_stabiliz);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300763 dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock);
764
765 // Demod AGC loop configuration
766 dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp);
Olivier Grenie713d54a2011-01-04 04:54:31 -0300767 dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300768
769 /* AGC continued */
Olivier Grenie713d54a2011-01-04 04:54:31 -0300770 dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d",
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300771 state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
772
773 if (state->wbd_ref != 0)
774 dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | state->wbd_ref);
775 else
776 dib7000p_write_word(state, 105, (agc->wbd_inv << 12) | agc->wbd_ref);
777
778 dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8));
779
Olivier Grenie713d54a2011-01-04 04:54:31 -0300780 dib7000p_write_word(state, 107, agc->agc1_max);
781 dib7000p_write_word(state, 108, agc->agc1_min);
782 dib7000p_write_word(state, 109, agc->agc2_max);
783 dib7000p_write_word(state, 110, agc->agc2_min);
784 dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
785 dib7000p_write_word(state, 112, agc->agc1_pt3);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300786 dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
Olivier Grenie713d54a2011-01-04 04:54:31 -0300787 dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300788 dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
789 return 0;
790}
791
Olivier Grenie713d54a2011-01-04 04:54:31 -0300792static void dib7000p_set_dds(struct dib7000p_state *state, s32 offset_khz)
793{
794 u32 internal = dib7000p_get_internal_freq(state);
795 s32 unit_khz_dds_val = 67108864 / (internal); /* 2**26 / Fsampling is the unit 1KHz offset */
796 u32 abs_offset_khz = ABS(offset_khz);
797 u32 dds = state->cfg.bw->ifreq & 0x1ffffff;
798 u8 invert = !!(state->cfg.bw->ifreq & (1 << 25));
799
800 dprintk("setting a frequency offset of %dkHz internal freq = %d invert = %d", offset_khz, internal, invert);
801
802 if (offset_khz < 0)
803 unit_khz_dds_val *= -1;
804
805 /* IF tuner */
806 if (invert)
807 dds -= (abs_offset_khz * unit_khz_dds_val); /* /100 because of /100 on the unit_khz_dds_val line calc for better accuracy */
808 else
809 dds += (abs_offset_khz * unit_khz_dds_val);
810
811 if (abs_offset_khz <= (internal / 2)) { /* Max dds offset is the half of the demod freq */
812 dib7000p_write_word(state, 21, (u16) (((dds >> 16) & 0x1ff) | (0 << 10) | (invert << 9)));
813 dib7000p_write_word(state, 22, (u16) (dds & 0xffff));
814 }
815}
816
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -0300817static int dib7000p_agc_startup(struct dvb_frontend *demod)
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300818{
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -0300819 struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300820 struct dib7000p_state *state = demod->demodulator_priv;
821 int ret = -1;
822 u8 *agc_state = &state->agc_state;
823 u8 agc_split;
Olivier Grenie713d54a2011-01-04 04:54:31 -0300824 u16 reg;
825 u32 upd_demod_gain_period = 0x1000;
Olivier Grenie6fe10992012-12-31 09:23:26 -0300826 s32 frequency_offset = 0;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300827
828 switch (state->agc_state) {
Olivier Grenie713d54a2011-01-04 04:54:31 -0300829 case 0:
Olivier Grenie713d54a2011-01-04 04:54:31 -0300830 dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
831 if (state->version == SOC7090) {
832 reg = dib7000p_read_word(state, 0x79b) & 0xff00;
833 dib7000p_write_word(state, 0x79a, upd_demod_gain_period & 0xFFFF); /* lsb */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300834 dib7000p_write_word(state, 0x79b, reg | (1 << 14) | ((upd_demod_gain_period >> 16) & 0xFF));
Olivier Grenie713d54a2011-01-04 04:54:31 -0300835
836 /* enable adc i & q */
837 reg = dib7000p_read_word(state, 0x780);
838 dib7000p_write_word(state, 0x780, (reg | (0x3)) & (~(1 << 7)));
839 } else {
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300840 dib7000p_set_adc_state(state, DIBX000_ADC_ON);
841 dib7000p_pll_clk_cfg(state);
Olivier Grenie713d54a2011-01-04 04:54:31 -0300842 }
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300843
Olivier Grenie713d54a2011-01-04 04:54:31 -0300844 if (dib7000p_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency / 1000)) != 0)
845 return -1;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300846
Olivier Grenie6fe10992012-12-31 09:23:26 -0300847 if (demod->ops.tuner_ops.get_frequency) {
848 u32 frequency_tuner;
849
850 demod->ops.tuner_ops.get_frequency(demod, &frequency_tuner);
851 frequency_offset = (s32)frequency_tuner / 1000 - ch->frequency / 1000;
852 }
853
854 dib7000p_set_dds(state, frequency_offset);
Olivier Grenie713d54a2011-01-04 04:54:31 -0300855 ret = 7;
856 (*agc_state)++;
857 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300858
Olivier Grenie713d54a2011-01-04 04:54:31 -0300859 case 1:
Olivier Grenie713d54a2011-01-04 04:54:31 -0300860 if (state->cfg.agc_control)
861 state->cfg.agc_control(&state->demod, 1);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300862
Olivier Grenie713d54a2011-01-04 04:54:31 -0300863 dib7000p_write_word(state, 78, 32768);
864 if (!state->current_agc->perform_agc_softsplit) {
865 /* we are using the wbd - so slow AGC startup */
866 /* force 0 split on WBD and restart AGC */
867 dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | (1 << 8));
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300868 (*agc_state)++;
869 ret = 5;
Olivier Grenie713d54a2011-01-04 04:54:31 -0300870 } else {
871 /* default AGC startup */
872 (*agc_state) = 4;
873 /* wait AGC rough lock time */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300874 ret = 7;
Olivier Grenie713d54a2011-01-04 04:54:31 -0300875 }
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300876
Olivier Grenie713d54a2011-01-04 04:54:31 -0300877 dib7000p_restart_agc(state);
878 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300879
Olivier Grenie713d54a2011-01-04 04:54:31 -0300880 case 2: /* fast split search path after 5sec */
881 dib7000p_write_word(state, 75, state->current_agc->setup | (1 << 4)); /* freeze AGC loop */
882 dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (2 << 9) | (0 << 8)); /* fast split search 0.25kHz */
883 (*agc_state)++;
884 ret = 14;
885 break;
886
887 case 3: /* split search ended */
888 agc_split = (u8) dib7000p_read_word(state, 396); /* store the split value for the next time */
889 dib7000p_write_word(state, 78, dib7000p_read_word(state, 394)); /* set AGC gain start value */
890
891 dib7000p_write_word(state, 75, state->current_agc->setup); /* std AGC loop */
892 dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */
893
894 dib7000p_restart_agc(state);
895
896 dprintk("SPLIT %p: %hd", demod, agc_split);
897
898 (*agc_state)++;
899 ret = 5;
900 break;
901
902 case 4: /* LNA startup */
Olivier Grenie713d54a2011-01-04 04:54:31 -0300903 ret = 7;
904
905 if (dib7000p_update_lna(state))
Olivier Grenie713d54a2011-01-04 04:54:31 -0300906 ret = 5;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -0300907 else
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300908 (*agc_state)++;
Olivier Grenie713d54a2011-01-04 04:54:31 -0300909 break;
910
911 case 5:
912 if (state->cfg.agc_control)
913 state->cfg.agc_control(&state->demod, 0);
914 (*agc_state)++;
915 break;
916 default:
917 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300918 }
919 return ret;
920}
921
922static void dib7000p_update_timf(struct dib7000p_state *state)
923{
924 u32 timf = (dib7000p_read_word(state, 427) << 16) | dib7000p_read_word(state, 428);
925 state->timf = timf * 160 / (state->current_bandwidth / 50);
926 dib7000p_write_word(state, 23, (u16) (timf >> 16));
927 dib7000p_write_word(state, 24, (u16) (timf & 0xffff));
Olivier Grenie713d54a2011-01-04 04:54:31 -0300928 dprintk("updated timf_frequency: %d (default: %d)", state->timf, state->cfg.bw->timf);
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300929
930}
931
Mauro Carvalho Chehab8abe4a02014-05-29 09:20:15 -0300932static u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
Olivier Grenie713d54a2011-01-04 04:54:31 -0300933{
934 struct dib7000p_state *state = fe->demodulator_priv;
935 switch (op) {
936 case DEMOD_TIMF_SET:
937 state->timf = timf;
938 break;
939 case DEMOD_TIMF_UPDATE:
940 dib7000p_update_timf(state);
941 break;
942 case DEMOD_TIMF_GET:
943 break;
944 }
945 dib7000p_set_bandwidth(state, state->current_bandwidth);
946 return state->timf;
947}
Olivier Grenie713d54a2011-01-04 04:54:31 -0300948
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -0300949static void dib7000p_set_channel(struct dib7000p_state *state,
950 struct dtv_frontend_properties *ch, u8 seq)
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300951{
952 u16 value, est[4];
953
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -0300954 dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
Patrick Boettchera75763f2006-10-18 08:34:16 -0300955
956 /* nfft, guard, qam, alpha */
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300957 value = 0;
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -0300958 switch (ch->transmission_mode) {
Olivier Grenie713d54a2011-01-04 04:54:31 -0300959 case TRANSMISSION_MODE_2K:
960 value |= (0 << 7);
961 break;
Mauro Carvalho Chehab46f72962011-01-16 13:01:20 -0200962 case TRANSMISSION_MODE_4K:
Olivier Grenie713d54a2011-01-04 04:54:31 -0300963 value |= (2 << 7);
964 break;
965 default:
966 case TRANSMISSION_MODE_8K:
967 value |= (1 << 7);
968 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300969 }
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -0300970 switch (ch->guard_interval) {
Olivier Grenie713d54a2011-01-04 04:54:31 -0300971 case GUARD_INTERVAL_1_32:
972 value |= (0 << 5);
973 break;
974 case GUARD_INTERVAL_1_16:
975 value |= (1 << 5);
976 break;
977 case GUARD_INTERVAL_1_4:
978 value |= (3 << 5);
979 break;
980 default:
981 case GUARD_INTERVAL_1_8:
982 value |= (2 << 5);
983 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300984 }
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -0300985 switch (ch->modulation) {
Olivier Grenie713d54a2011-01-04 04:54:31 -0300986 case QPSK:
987 value |= (0 << 3);
988 break;
989 case QAM_16:
990 value |= (1 << 3);
991 break;
992 default:
993 case QAM_64:
994 value |= (2 << 3);
995 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -0300996 }
997 switch (HIERARCHY_1) {
Olivier Grenie713d54a2011-01-04 04:54:31 -0300998 case HIERARCHY_2:
999 value |= 2;
1000 break;
1001 case HIERARCHY_4:
1002 value |= 4;
1003 break;
1004 default:
1005 case HIERARCHY_1:
1006 value |= 1;
1007 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001008 }
1009 dib7000p_write_word(state, 0, value);
Olivier Grenie713d54a2011-01-04 04:54:31 -03001010 dib7000p_write_word(state, 5, (seq << 4) | 1); /* do not force tps, search list 0 */
Patrick Boettchera75763f2006-10-18 08:34:16 -03001011
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001012 /* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */
1013 value = 0;
1014 if (1 != 0)
1015 value |= (1 << 6);
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001016 if (ch->hierarchy == 1)
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001017 value |= (1 << 4);
1018 if (1 == 1)
1019 value |= 1;
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001020 switch ((ch->hierarchy == 0 || 1 == 1) ? ch->code_rate_HP : ch->code_rate_LP) {
Olivier Grenie713d54a2011-01-04 04:54:31 -03001021 case FEC_2_3:
1022 value |= (2 << 1);
1023 break;
1024 case FEC_3_4:
1025 value |= (3 << 1);
1026 break;
1027 case FEC_5_6:
1028 value |= (5 << 1);
1029 break;
1030 case FEC_7_8:
1031 value |= (7 << 1);
1032 break;
1033 default:
1034 case FEC_1_2:
1035 value |= (1 << 1);
1036 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001037 }
1038 dib7000p_write_word(state, 208, value);
1039
1040 /* offset loop parameters */
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001041 dib7000p_write_word(state, 26, 0x6680);
1042 dib7000p_write_word(state, 32, 0x0003);
1043 dib7000p_write_word(state, 29, 0x1273);
1044 dib7000p_write_word(state, 33, 0x0005);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001045
1046 /* P_dvsy_sync_wait */
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001047 switch (ch->transmission_mode) {
Olivier Grenie713d54a2011-01-04 04:54:31 -03001048 case TRANSMISSION_MODE_8K:
1049 value = 256;
1050 break;
1051 case TRANSMISSION_MODE_4K:
1052 value = 128;
1053 break;
1054 case TRANSMISSION_MODE_2K:
1055 default:
1056 value = 64;
1057 break;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001058 }
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001059 switch (ch->guard_interval) {
Olivier Grenie713d54a2011-01-04 04:54:31 -03001060 case GUARD_INTERVAL_1_16:
1061 value *= 2;
1062 break;
1063 case GUARD_INTERVAL_1_8:
1064 value *= 4;
1065 break;
1066 case GUARD_INTERVAL_1_4:
1067 value *= 8;
1068 break;
1069 default:
1070 case GUARD_INTERVAL_1_32:
1071 value *= 1;
1072 break;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001073 }
Olivier Grenie970d14c2010-09-07 12:50:46 -03001074 if (state->cfg.diversity_delay == 0)
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001075 state->div_sync_wait = (value * 3) / 2 + 48;
Olivier Grenie970d14c2010-09-07 12:50:46 -03001076 else
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001077 state->div_sync_wait = (value * 3) / 2 + state->cfg.diversity_delay;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001078
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001079 /* deactive the possibility of diversity reception if extended interleaver */
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001080 state->div_force_off = !1 && ch->transmission_mode != TRANSMISSION_MODE_8K;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001081 dib7000p_set_diversity_in(&state->demod, state->div_state);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001082
1083 /* channel estimation fine configuration */
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001084 switch (ch->modulation) {
Olivier Grenie713d54a2011-01-04 04:54:31 -03001085 case QAM_64:
1086 est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */
1087 est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */
1088 est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
1089 est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */
1090 break;
1091 case QAM_16:
1092 est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */
1093 est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */
1094 est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */
1095 est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */
1096 break;
1097 default:
1098 est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */
1099 est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */
1100 est[2] = 0x0333; /* P_adp_regul_ext 0.1 */
1101 est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */
1102 break;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001103 }
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001104 for (value = 0; value < 4; value++)
1105 dib7000p_write_word(state, 187 + value, est[value]);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001106}
1107
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001108static int dib7000p_autosearch_start(struct dvb_frontend *demod)
Patrick Boettchera75763f2006-10-18 08:34:16 -03001109{
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001110 struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001111 struct dib7000p_state *state = demod->demodulator_priv;
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001112 struct dtv_frontend_properties schan;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001113 u32 value, factor;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001114 u32 internal = dib7000p_get_internal_freq(state);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001115
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001116 schan = *ch;
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001117 schan.modulation = QAM_64;
1118 schan.guard_interval = GUARD_INTERVAL_1_32;
1119 schan.transmission_mode = TRANSMISSION_MODE_8K;
1120 schan.code_rate_HP = FEC_2_3;
1121 schan.code_rate_LP = FEC_3_4;
1122 schan.hierarchy = 0;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001123
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001124 dib7000p_set_channel(state, &schan, 7);
1125
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001126 factor = BANDWIDTH_TO_KHZ(ch->bandwidth_hz);
Olivier Grenie2e802862011-08-05 10:39:15 -03001127 if (factor >= 5000) {
1128 if (state->version == SOC7090)
1129 factor = 2;
1130 else
1131 factor = 1;
1132 } else
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001133 factor = 6;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001134
Olivier Grenie713d54a2011-01-04 04:54:31 -03001135 value = 30 * internal * factor;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001136 dib7000p_write_word(state, 6, (u16) ((value >> 16) & 0xffff));
1137 dib7000p_write_word(state, 7, (u16) (value & 0xffff));
Olivier Grenie713d54a2011-01-04 04:54:31 -03001138 value = 100 * internal * factor;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001139 dib7000p_write_word(state, 8, (u16) ((value >> 16) & 0xffff));
1140 dib7000p_write_word(state, 9, (u16) (value & 0xffff));
Olivier Grenie713d54a2011-01-04 04:54:31 -03001141 value = 500 * internal * factor;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001142 dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff));
1143 dib7000p_write_word(state, 11, (u16) (value & 0xffff));
Patrick Boettchera75763f2006-10-18 08:34:16 -03001144
1145 value = dib7000p_read_word(state, 0);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001146 dib7000p_write_word(state, 0, (u16) ((1 << 9) | value));
Patrick Boettchera75763f2006-10-18 08:34:16 -03001147 dib7000p_read_word(state, 1284);
1148 dib7000p_write_word(state, 0, (u16) value);
1149
1150 return 0;
1151}
1152
1153static int dib7000p_autosearch_is_irq(struct dvb_frontend *demod)
1154{
1155 struct dib7000p_state *state = demod->demodulator_priv;
1156 u16 irq_pending = dib7000p_read_word(state, 1284);
1157
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001158 if (irq_pending & 0x1)
Patrick Boettchera75763f2006-10-18 08:34:16 -03001159 return 1;
1160
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001161 if (irq_pending & 0x2)
Patrick Boettchera75763f2006-10-18 08:34:16 -03001162 return 2;
1163
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001164 return 0;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001165}
1166
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001167static void dib7000p_spur_protect(struct dib7000p_state *state, u32 rf_khz, u32 bw)
1168{
Olivier Grenie713d54a2011-01-04 04:54:31 -03001169 static s16 notch[] = { 16143, 14402, 12238, 9713, 6902, 3888, 759, -2392 };
1170 static u8 sine[] = { 0, 2, 3, 5, 6, 8, 9, 11, 13, 14, 16, 17, 19, 20, 22,
1171 24, 25, 27, 28, 30, 31, 33, 34, 36, 38, 39, 41, 42, 44, 45, 47, 48, 50, 51,
1172 53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 80,
1173 82, 83, 85, 86, 88, 89, 91, 92, 94, 95, 97, 98, 99, 101, 102, 104, 105,
1174 107, 108, 109, 111, 112, 114, 115, 117, 118, 119, 121, 122, 123, 125, 126,
1175 128, 129, 130, 132, 133, 134, 136, 137, 138, 140, 141, 142, 144, 145, 146,
1176 147, 149, 150, 151, 152, 154, 155, 156, 157, 159, 160, 161, 162, 164, 165,
1177 166, 167, 168, 170, 171, 172, 173, 174, 175, 177, 178, 179, 180, 181, 182,
1178 183, 184, 185, 186, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
1179 199, 200, 201, 202, 203, 204, 205, 206, 207, 207, 208, 209, 210, 211, 212,
1180 213, 214, 215, 215, 216, 217, 218, 219, 220, 220, 221, 222, 223, 224, 224,
1181 225, 226, 227, 227, 228, 229, 229, 230, 231, 231, 232, 233, 233, 234, 235,
1182 235, 236, 237, 237, 238, 238, 239, 239, 240, 241, 241, 242, 242, 243, 243,
1183 244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 248, 249, 249, 249,
1184 250, 250, 250, 251, 251, 251, 252, 252, 252, 252, 253, 253, 253, 253, 254,
1185 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
1186 255, 255, 255, 255, 255, 255
1187 };
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001188
1189 u32 xtal = state->cfg.bw->xtal_hz / 1000;
Julia Lawall75b697f2009-08-01 16:48:41 -03001190 int f_rel = DIV_ROUND_CLOSEST(rf_khz, xtal) * xtal - rf_khz;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001191 int k;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001192 int coef_re[8], coef_im[8];
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001193 int bw_khz = bw;
1194 u32 pha;
1195
Olivier Grenie713d54a2011-01-04 04:54:31 -03001196 dprintk("relative position of the Spur: %dk (RF: %dk, XTAL: %dk)", f_rel, rf_khz, xtal);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001197
Olivier Grenie713d54a2011-01-04 04:54:31 -03001198 if (f_rel < -bw_khz / 2 || f_rel > bw_khz / 2)
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001199 return;
1200
1201 bw_khz /= 100;
1202
Olivier Grenie713d54a2011-01-04 04:54:31 -03001203 dib7000p_write_word(state, 142, 0x0610);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001204
1205 for (k = 0; k < 8; k++) {
Olivier Grenie713d54a2011-01-04 04:54:31 -03001206 pha = ((f_rel * (k + 1) * 112 * 80 / bw_khz) / 1000) & 0x3ff;
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001207
Olivier Grenie713d54a2011-01-04 04:54:31 -03001208 if (pha == 0) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001209 coef_re[k] = 256;
1210 coef_im[k] = 0;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001211 } else if (pha < 256) {
1212 coef_re[k] = sine[256 - (pha & 0xff)];
1213 coef_im[k] = sine[pha & 0xff];
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001214 } else if (pha == 256) {
1215 coef_re[k] = 0;
1216 coef_im[k] = 256;
1217 } else if (pha < 512) {
Olivier Grenie713d54a2011-01-04 04:54:31 -03001218 coef_re[k] = -sine[pha & 0xff];
1219 coef_im[k] = sine[256 - (pha & 0xff)];
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001220 } else if (pha == 512) {
1221 coef_re[k] = -256;
1222 coef_im[k] = 0;
1223 } else if (pha < 768) {
Olivier Grenie713d54a2011-01-04 04:54:31 -03001224 coef_re[k] = -sine[256 - (pha & 0xff)];
1225 coef_im[k] = -sine[pha & 0xff];
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001226 } else if (pha == 768) {
1227 coef_re[k] = 0;
1228 coef_im[k] = -256;
1229 } else {
Olivier Grenie713d54a2011-01-04 04:54:31 -03001230 coef_re[k] = sine[pha & 0xff];
1231 coef_im[k] = -sine[256 - (pha & 0xff)];
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001232 }
1233
1234 coef_re[k] *= notch[k];
Olivier Grenie713d54a2011-01-04 04:54:31 -03001235 coef_re[k] += (1 << 14);
1236 if (coef_re[k] >= (1 << 24))
1237 coef_re[k] = (1 << 24) - 1;
1238 coef_re[k] /= (1 << 15);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001239
1240 coef_im[k] *= notch[k];
Olivier Grenie713d54a2011-01-04 04:54:31 -03001241 coef_im[k] += (1 << 14);
1242 if (coef_im[k] >= (1 << 24))
1243 coef_im[k] = (1 << 24) - 1;
1244 coef_im[k] /= (1 << 15);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001245
Olivier Grenie713d54a2011-01-04 04:54:31 -03001246 dprintk("PALF COEF: %d re: %d im: %d", k, coef_re[k], coef_im[k]);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001247
1248 dib7000p_write_word(state, 143, (0 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
1249 dib7000p_write_word(state, 144, coef_im[k] & 0x3ff);
1250 dib7000p_write_word(state, 143, (1 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
1251 }
Olivier Grenie713d54a2011-01-04 04:54:31 -03001252 dib7000p_write_word(state, 143, 0);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001253}
1254
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001255static int dib7000p_tune(struct dvb_frontend *demod)
Patrick Boettchera75763f2006-10-18 08:34:16 -03001256{
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001257 struct dtv_frontend_properties *ch = &demod->dtv_property_cache;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001258 struct dib7000p_state *state = demod->demodulator_priv;
1259 u16 tmp = 0;
1260
1261 if (ch != NULL)
1262 dib7000p_set_channel(state, ch, 0);
1263 else
1264 return -EINVAL;
1265
1266 // restart demod
1267 dib7000p_write_word(state, 770, 0x4000);
1268 dib7000p_write_word(state, 770, 0x0000);
1269 msleep(45);
1270
1271 /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
Matt Doran8f6956c2007-07-31 07:09:30 -03001272 tmp = (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3);
1273 if (state->sfn_workaround_active) {
Olivier Grenie713d54a2011-01-04 04:54:31 -03001274 dprintk("SFN workaround is active");
Matt Doran8f6956c2007-07-31 07:09:30 -03001275 tmp |= (1 << 9);
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001276 dib7000p_write_word(state, 166, 0x4000);
Matt Doran8f6956c2007-07-31 07:09:30 -03001277 } else {
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001278 dib7000p_write_word(state, 166, 0x0000);
Matt Doran8f6956c2007-07-31 07:09:30 -03001279 }
1280 dib7000p_write_word(state, 29, tmp);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001281
1282 // never achieved a lock with that bandwidth so far - wait for osc-freq to update
1283 if (state->timf == 0)
1284 msleep(200);
1285
1286 /* offset loop parameters */
1287
1288 /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
1289 tmp = (6 << 8) | 0x80;
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001290 switch (ch->transmission_mode) {
Olivier Grenie713d54a2011-01-04 04:54:31 -03001291 case TRANSMISSION_MODE_2K:
1292 tmp |= (2 << 12);
1293 break;
Mauro Carvalho Chehab46f72962011-01-16 13:01:20 -02001294 case TRANSMISSION_MODE_4K:
Olivier Grenie713d54a2011-01-04 04:54:31 -03001295 tmp |= (3 << 12);
1296 break;
1297 default:
1298 case TRANSMISSION_MODE_8K:
1299 tmp |= (4 << 12);
1300 break;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001301 }
Olivier Grenie713d54a2011-01-04 04:54:31 -03001302 dib7000p_write_word(state, 26, tmp); /* timf_a(6xxx) */
Patrick Boettchera75763f2006-10-18 08:34:16 -03001303
1304 /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
1305 tmp = (0 << 4);
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001306 switch (ch->transmission_mode) {
Olivier Grenie713d54a2011-01-04 04:54:31 -03001307 case TRANSMISSION_MODE_2K:
1308 tmp |= 0x6;
1309 break;
Mauro Carvalho Chehab46f72962011-01-16 13:01:20 -02001310 case TRANSMISSION_MODE_4K:
Olivier Grenie713d54a2011-01-04 04:54:31 -03001311 tmp |= 0x7;
1312 break;
1313 default:
1314 case TRANSMISSION_MODE_8K:
1315 tmp |= 0x8;
1316 break;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001317 }
Olivier Grenie713d54a2011-01-04 04:54:31 -03001318 dib7000p_write_word(state, 32, tmp);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001319
1320 /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
1321 tmp = (0 << 4);
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001322 switch (ch->transmission_mode) {
Olivier Grenie713d54a2011-01-04 04:54:31 -03001323 case TRANSMISSION_MODE_2K:
1324 tmp |= 0x6;
1325 break;
1326 case TRANSMISSION_MODE_4K:
1327 tmp |= 0x7;
1328 break;
1329 default:
1330 case TRANSMISSION_MODE_8K:
1331 tmp |= 0x8;
1332 break;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001333 }
Olivier Grenie713d54a2011-01-04 04:54:31 -03001334 dib7000p_write_word(state, 33, tmp);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001335
Olivier Grenie713d54a2011-01-04 04:54:31 -03001336 tmp = dib7000p_read_word(state, 509);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001337 if (!((tmp >> 6) & 0x1)) {
1338 /* restart the fec */
Olivier Grenie713d54a2011-01-04 04:54:31 -03001339 tmp = dib7000p_read_word(state, 771);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001340 dib7000p_write_word(state, 771, tmp | (1 << 1));
1341 dib7000p_write_word(state, 771, tmp);
Olivier Grenie713d54a2011-01-04 04:54:31 -03001342 msleep(40);
1343 tmp = dib7000p_read_word(state, 509);
1344 }
1345 // we achieved a lock - it's time to update the osc freq
1346 if ((tmp >> 6) & 0x1) {
1347 dib7000p_update_timf(state);
1348 /* P_timf_alpha += 2 */
1349 tmp = dib7000p_read_word(state, 26);
1350 dib7000p_write_word(state, 26, (tmp & ~(0xf << 12)) | ((((tmp >> 12) & 0xf) + 5) << 12));
Patrick Boettchera75763f2006-10-18 08:34:16 -03001351 }
1352
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001353 if (state->cfg.spur_protect)
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001354 dib7000p_spur_protect(state, ch->frequency / 1000, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001355
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001356 dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
Patrick Boettchera75763f2006-10-18 08:34:16 -03001357 return 0;
1358}
1359
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001360static int dib7000p_wakeup(struct dvb_frontend *demod)
Patrick Boettchera75763f2006-10-18 08:34:16 -03001361{
Patrick Boettchera75763f2006-10-18 08:34:16 -03001362 struct dib7000p_state *state = demod->demodulator_priv;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001363 dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
1364 dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
Olivier Grenie713d54a2011-01-04 04:54:31 -03001365 if (state->version == SOC7090)
1366 dib7000p_sad_calib(state);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001367 return 0;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001368}
1369
1370static int dib7000p_sleep(struct dvb_frontend *demod)
1371{
1372 struct dib7000p_state *state = demod->demodulator_priv;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001373 if (state->version == SOC7090)
Olivier Grenie2e802862011-08-05 10:39:15 -03001374 return dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001375 return dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
1376}
1377
1378static int dib7000p_identify(struct dib7000p_state *st)
1379{
1380 u16 value;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001381 dprintk("checking demod on I2C address: %d (%x)", st->i2c_addr, st->i2c_addr);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001382
1383 if ((value = dib7000p_read_word(st, 768)) != 0x01b3) {
Olivier Grenie713d54a2011-01-04 04:54:31 -03001384 dprintk("wrong Vendor ID (read=0x%x)", value);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001385 return -EREMOTEIO;
1386 }
1387
1388 if ((value = dib7000p_read_word(st, 769)) != 0x4000) {
Olivier Grenie713d54a2011-01-04 04:54:31 -03001389 dprintk("wrong Device ID (%x)", value);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001390 return -EREMOTEIO;
1391 }
1392
1393 return 0;
1394}
1395
Mauro Carvalho Chehab7c61d802011-12-30 11:30:21 -03001396static int dib7000p_get_frontend(struct dvb_frontend *fe)
Patrick Boettchera75763f2006-10-18 08:34:16 -03001397{
Mauro Carvalho Chehab7c61d802011-12-30 11:30:21 -03001398 struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001399 struct dib7000p_state *state = fe->demodulator_priv;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001400 u16 tps = dib7000p_read_word(state, 463);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001401
1402 fep->inversion = INVERSION_AUTO;
1403
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001404 fep->bandwidth_hz = BANDWIDTH_TO_HZ(state->current_bandwidth);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001405
1406 switch ((tps >> 8) & 0x3) {
Olivier Grenie713d54a2011-01-04 04:54:31 -03001407 case 0:
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001408 fep->transmission_mode = TRANSMISSION_MODE_2K;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001409 break;
1410 case 1:
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001411 fep->transmission_mode = TRANSMISSION_MODE_8K;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001412 break;
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001413 /* case 2: fep->transmission_mode = TRANSMISSION_MODE_4K; break; */
Patrick Boettchera75763f2006-10-18 08:34:16 -03001414 }
1415
1416 switch (tps & 0x3) {
Olivier Grenie713d54a2011-01-04 04:54:31 -03001417 case 0:
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001418 fep->guard_interval = GUARD_INTERVAL_1_32;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001419 break;
1420 case 1:
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001421 fep->guard_interval = GUARD_INTERVAL_1_16;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001422 break;
1423 case 2:
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001424 fep->guard_interval = GUARD_INTERVAL_1_8;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001425 break;
1426 case 3:
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001427 fep->guard_interval = GUARD_INTERVAL_1_4;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001428 break;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001429 }
1430
1431 switch ((tps >> 14) & 0x3) {
Olivier Grenie713d54a2011-01-04 04:54:31 -03001432 case 0:
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001433 fep->modulation = QPSK;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001434 break;
1435 case 1:
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001436 fep->modulation = QAM_16;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001437 break;
1438 case 2:
1439 default:
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001440 fep->modulation = QAM_64;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001441 break;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001442 }
1443
1444 /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
1445 /* (tps >> 13) & 0x1 == hrch is used, (tps >> 10) & 0x7 == alpha */
1446
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001447 fep->hierarchy = HIERARCHY_NONE;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001448 switch ((tps >> 5) & 0x7) {
Olivier Grenie713d54a2011-01-04 04:54:31 -03001449 case 1:
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001450 fep->code_rate_HP = FEC_1_2;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001451 break;
1452 case 2:
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001453 fep->code_rate_HP = FEC_2_3;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001454 break;
1455 case 3:
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001456 fep->code_rate_HP = FEC_3_4;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001457 break;
1458 case 5:
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001459 fep->code_rate_HP = FEC_5_6;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001460 break;
1461 case 7:
1462 default:
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001463 fep->code_rate_HP = FEC_7_8;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001464 break;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001465
1466 }
1467
1468 switch ((tps >> 2) & 0x7) {
Olivier Grenie713d54a2011-01-04 04:54:31 -03001469 case 1:
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001470 fep->code_rate_LP = FEC_1_2;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001471 break;
1472 case 2:
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001473 fep->code_rate_LP = FEC_2_3;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001474 break;
1475 case 3:
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001476 fep->code_rate_LP = FEC_3_4;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001477 break;
1478 case 5:
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001479 fep->code_rate_LP = FEC_5_6;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001480 break;
1481 case 7:
1482 default:
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001483 fep->code_rate_LP = FEC_7_8;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001484 break;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001485 }
1486
1487 /* native interleaver: (dib7000p_read_word(state, 464) >> 5) & 0x1 */
1488
1489 return 0;
1490}
1491
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001492static int dib7000p_set_frontend(struct dvb_frontend *fe)
Patrick Boettchera75763f2006-10-18 08:34:16 -03001493{
Mauro Carvalho Chehab7c61d802011-12-30 11:30:21 -03001494 struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001495 struct dib7000p_state *state = fe->demodulator_priv;
Soeren Moch853ea132008-01-25 06:27:06 -03001496 int time, ret;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001497
Olivier Grenie2e802862011-08-05 10:39:15 -03001498 if (state->version == SOC7090)
Olivier Grenie713d54a2011-01-04 04:54:31 -03001499 dib7090_set_diversity_in(fe, 0);
Olivier Grenie2e802862011-08-05 10:39:15 -03001500 else
Olivier Grenie713d54a2011-01-04 04:54:31 -03001501 dib7000p_set_output_mode(state, OUTMODE_HIGH_Z);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001502
Olivier Grenie713d54a2011-01-04 04:54:31 -03001503 /* maybe the parameter has been changed */
Matt Doran8f6956c2007-07-31 07:09:30 -03001504 state->sfn_workaround_active = buggy_sfn_workaround;
1505
Patrick Boettchera75763f2006-10-18 08:34:16 -03001506 if (fe->ops.tuner_ops.set_params)
Mauro Carvalho Chehab14d24d12011-12-24 12:24:33 -03001507 fe->ops.tuner_ops.set_params(fe);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001508
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001509 /* start up the AGC */
1510 state->agc_state = 0;
1511 do {
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001512 time = dib7000p_agc_startup(fe);
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001513 if (time != -1)
1514 msleep(time);
1515 } while (time != -1);
1516
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001517 if (fep->transmission_mode == TRANSMISSION_MODE_AUTO ||
1518 fep->guard_interval == GUARD_INTERVAL_AUTO || fep->modulation == QAM_AUTO || fep->code_rate_HP == FEC_AUTO) {
Patrick Boettchera75763f2006-10-18 08:34:16 -03001519 int i = 800, found;
1520
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001521 dib7000p_autosearch_start(fe);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001522 do {
1523 msleep(1);
1524 found = dib7000p_autosearch_is_irq(fe);
1525 } while (found == 0 && i--);
1526
Olivier Grenie713d54a2011-01-04 04:54:31 -03001527 dprintk("autosearch returns: %d", found);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001528 if (found == 0 || found == 1)
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001529 return 0;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001530
Mauro Carvalho Chehab7c61d802011-12-30 11:30:21 -03001531 dib7000p_get_frontend(fe);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001532 }
1533
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03001534 ret = dib7000p_tune(fe);
Soeren Moch853ea132008-01-25 06:27:06 -03001535
Patrick Boettchera75763f2006-10-18 08:34:16 -03001536 /* make this a config parameter */
Olivier Grenie2e802862011-08-05 10:39:15 -03001537 if (state->version == SOC7090) {
Olivier Grenie713d54a2011-01-04 04:54:31 -03001538 dib7090_set_output_mode(fe, state->cfg.output_mode);
Olivier Grenie2e802862011-08-05 10:39:15 -03001539 if (state->cfg.enMpegOutput == 0) {
1540 dib7090_setDibTxMux(state, MPEG_ON_DIBTX);
1541 dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
1542 }
1543 } else
Olivier Grenie713d54a2011-01-04 04:54:31 -03001544 dib7000p_set_output_mode(state, state->cfg.output_mode);
1545
1546 return ret;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001547}
1548
Olivier Grenie713d54a2011-01-04 04:54:31 -03001549static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t * stat)
Patrick Boettchera75763f2006-10-18 08:34:16 -03001550{
1551 struct dib7000p_state *state = fe->demodulator_priv;
1552 u16 lock = dib7000p_read_word(state, 509);
1553
1554 *stat = 0;
1555
1556 if (lock & 0x8000)
1557 *stat |= FE_HAS_SIGNAL;
1558 if (lock & 0x3000)
1559 *stat |= FE_HAS_CARRIER;
1560 if (lock & 0x0100)
1561 *stat |= FE_HAS_VITERBI;
1562 if (lock & 0x0010)
1563 *stat |= FE_HAS_SYNC;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001564 if ((lock & 0x0038) == 0x38)
Patrick Boettchera75763f2006-10-18 08:34:16 -03001565 *stat |= FE_HAS_LOCK;
1566
1567 return 0;
1568}
1569
Olivier Grenie713d54a2011-01-04 04:54:31 -03001570static int dib7000p_read_ber(struct dvb_frontend *fe, u32 * ber)
Patrick Boettchera75763f2006-10-18 08:34:16 -03001571{
1572 struct dib7000p_state *state = fe->demodulator_priv;
1573 *ber = (dib7000p_read_word(state, 500) << 16) | dib7000p_read_word(state, 501);
1574 return 0;
1575}
1576
Olivier Grenie713d54a2011-01-04 04:54:31 -03001577static int dib7000p_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
Patrick Boettchera75763f2006-10-18 08:34:16 -03001578{
1579 struct dib7000p_state *state = fe->demodulator_priv;
1580 *unc = dib7000p_read_word(state, 506);
1581 return 0;
1582}
1583
Olivier Grenie713d54a2011-01-04 04:54:31 -03001584static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
Patrick Boettchera75763f2006-10-18 08:34:16 -03001585{
1586 struct dib7000p_state *state = fe->demodulator_priv;
1587 u16 val = dib7000p_read_word(state, 394);
1588 *strength = 65535 - val;
1589 return 0;
1590}
1591
Olivier Grenie713d54a2011-01-04 04:54:31 -03001592static int dib7000p_read_snr(struct dvb_frontend *fe, u16 * snr)
Patrick Boettchera75763f2006-10-18 08:34:16 -03001593{
Olivier Grenieef801962009-09-15 06:46:52 -03001594 struct dib7000p_state *state = fe->demodulator_priv;
1595 u16 val;
1596 s32 signal_mant, signal_exp, noise_mant, noise_exp;
1597 u32 result = 0;
1598
1599 val = dib7000p_read_word(state, 479);
1600 noise_mant = (val >> 4) & 0xff;
1601 noise_exp = ((val & 0xf) << 2);
1602 val = dib7000p_read_word(state, 480);
1603 noise_exp += ((val >> 14) & 0x3);
1604 if ((noise_exp & 0x20) != 0)
1605 noise_exp -= 0x40;
1606
1607 signal_mant = (val >> 6) & 0xFF;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001608 signal_exp = (val & 0x3F);
Olivier Grenieef801962009-09-15 06:46:52 -03001609 if ((signal_exp & 0x20) != 0)
1610 signal_exp -= 0x40;
1611
1612 if (signal_mant != 0)
Olivier Grenie713d54a2011-01-04 04:54:31 -03001613 result = intlog10(2) * 10 * signal_exp + 10 * intlog10(signal_mant);
Olivier Grenieef801962009-09-15 06:46:52 -03001614 else
1615 result = intlog10(2) * 10 * signal_exp - 100;
1616
1617 if (noise_mant != 0)
Olivier Grenie713d54a2011-01-04 04:54:31 -03001618 result -= intlog10(2) * 10 * noise_exp + 10 * intlog10(noise_mant);
Olivier Grenieef801962009-09-15 06:46:52 -03001619 else
1620 result -= intlog10(2) * 10 * noise_exp - 100;
1621
1622 *snr = result / ((1 << 24) / 10);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001623 return 0;
1624}
1625
Olivier Grenie713d54a2011-01-04 04:54:31 -03001626static int dib7000p_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
Patrick Boettchera75763f2006-10-18 08:34:16 -03001627{
1628 tune->min_delay_ms = 1000;
1629 return 0;
1630}
1631
1632static void dib7000p_release(struct dvb_frontend *demod)
1633{
1634 struct dib7000p_state *st = demod->demodulator_priv;
1635 dibx000_exit_i2c_master(&st->i2c_master);
Olivier Grenie713d54a2011-01-04 04:54:31 -03001636 i2c_del_adapter(&st->dib7090_tuner_adap);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001637 kfree(st);
1638}
1639
Mauro Carvalho Chehab8abe4a02014-05-29 09:20:15 -03001640static int dib7000pc_detection(struct i2c_adapter *i2c_adap)
Patrick Boettchera75763f2006-10-18 08:34:16 -03001641{
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001642 u8 *tx, *rx;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001643 struct i2c_msg msg[2] = {
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001644 {.addr = 18 >> 1, .flags = 0, .len = 2},
1645 {.addr = 18 >> 1, .flags = I2C_M_RD, .len = 2},
Patrick Boettchera75763f2006-10-18 08:34:16 -03001646 };
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001647 int ret = 0;
1648
1649 tx = kzalloc(2*sizeof(u8), GFP_KERNEL);
1650 if (!tx)
1651 return -ENOMEM;
1652 rx = kzalloc(2*sizeof(u8), GFP_KERNEL);
1653 if (!rx) {
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001654 ret = -ENOMEM;
Dan Carpenter0c61cc3b2011-08-06 05:00:34 -03001655 goto rx_memory_error;
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001656 }
1657
1658 msg[0].buf = tx;
1659 msg[1].buf = rx;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001660
1661 tx[0] = 0x03;
1662 tx[1] = 0x00;
1663
1664 if (i2c_transfer(i2c_adap, msg, 2) == 2)
1665 if (rx[0] == 0x01 && rx[1] == 0xb3) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001666 dprintk("-D- DiB7000PC detected");
Patrick Boettchera75763f2006-10-18 08:34:16 -03001667 return 1;
1668 }
1669
1670 msg[0].addr = msg[1].addr = 0x40;
1671
1672 if (i2c_transfer(i2c_adap, msg, 2) == 2)
1673 if (rx[0] == 0x01 && rx[1] == 0xb3) {
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001674 dprintk("-D- DiB7000PC detected");
Patrick Boettchera75763f2006-10-18 08:34:16 -03001675 return 1;
1676 }
1677
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001678 dprintk("-D- DiB7000PC not detected");
Olivier Grenie5a0deee2011-05-03 12:27:33 -03001679
1680 kfree(rx);
1681rx_memory_error:
1682 kfree(tx);
1683 return ret;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001684}
Patrick Boettchera75763f2006-10-18 08:34:16 -03001685
Mauro Carvalho Chehab8abe4a02014-05-29 09:20:15 -03001686static struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
Patrick Boettchera75763f2006-10-18 08:34:16 -03001687{
1688 struct dib7000p_state *st = demod->demodulator_priv;
1689 return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
1690}
Patrick Boettchera75763f2006-10-18 08:34:16 -03001691
Mauro Carvalho Chehab8abe4a02014-05-29 09:20:15 -03001692static int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
Olivier Grenief8731f42009-09-18 04:08:43 -03001693{
Olivier Grenie713d54a2011-01-04 04:54:31 -03001694 struct dib7000p_state *state = fe->demodulator_priv;
1695 u16 val = dib7000p_read_word(state, 235) & 0xffef;
1696 val |= (onoff & 0x1) << 4;
1697 dprintk("PID filter enabled %d", onoff);
1698 return dib7000p_write_word(state, 235, val);
Olivier Grenief8731f42009-09-18 04:08:43 -03001699}
Olivier Grenief8731f42009-09-18 04:08:43 -03001700
Mauro Carvalho Chehab8abe4a02014-05-29 09:20:15 -03001701static int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
Olivier Grenief8731f42009-09-18 04:08:43 -03001702{
Olivier Grenie713d54a2011-01-04 04:54:31 -03001703 struct dib7000p_state *state = fe->demodulator_priv;
1704 dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
1705 return dib7000p_write_word(state, 241 + id, onoff ? (1 << 13) | pid : 0);
Olivier Grenief8731f42009-09-18 04:08:43 -03001706}
Olivier Grenief8731f42009-09-18 04:08:43 -03001707
Mauro Carvalho Chehab8abe4a02014-05-29 09:20:15 -03001708static int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
Patrick Boettchera75763f2006-10-18 08:34:16 -03001709{
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001710 struct dib7000p_state *dpst;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001711 int k = 0;
1712 u8 new_addr = 0;
1713
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001714 dpst = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL);
1715 if (!dpst)
Andrew Morton0b427602010-04-27 19:09:45 -03001716 return -ENOMEM;
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001717
1718 dpst->i2c_adap = i2c;
Patrick Boettcher79fcce32011-08-03 12:08:21 -03001719 mutex_init(&dpst->i2c_buffer_lock);
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001720
Olivier Grenie713d54a2011-01-04 04:54:31 -03001721 for (k = no_of_demods - 1; k >= 0; k--) {
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001722 dpst->cfg = cfg[k];
Patrick Boettchera75763f2006-10-18 08:34:16 -03001723
1724 /* designated i2c address */
Olivier Grenie713d54a2011-01-04 04:54:31 -03001725 if (cfg[k].default_i2c_addr != 0)
1726 new_addr = cfg[k].default_i2c_addr + (k << 1);
1727 else
1728 new_addr = (0x40 + k) << 1;
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001729 dpst->i2c_addr = new_addr;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001730 dib7000p_write_word(dpst, 1287, 0x0003); /* sram lead in, rdy */
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001731 if (dib7000p_identify(dpst) != 0) {
1732 dpst->i2c_addr = default_addr;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001733 dib7000p_write_word(dpst, 1287, 0x0003); /* sram lead in, rdy */
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001734 if (dib7000p_identify(dpst) != 0) {
Patrick Boettchera75763f2006-10-18 08:34:16 -03001735 dprintk("DiB7000P #%d: not identified\n", k);
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001736 kfree(dpst);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001737 return -EIO;
1738 }
1739 }
1740
1741 /* start diversity to pull_down div_str - just for i2c-enumeration */
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001742 dib7000p_set_output_mode(dpst, OUTMODE_DIVERSITY);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001743
1744 /* set new i2c address and force divstart */
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001745 dib7000p_write_word(dpst, 1285, (new_addr << 2) | 0x2);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001746
Patrick Boettcherb6884a12007-07-27 10:08:51 -03001747 dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001748 }
1749
1750 for (k = 0; k < no_of_demods; k++) {
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001751 dpst->cfg = cfg[k];
Olivier Grenie713d54a2011-01-04 04:54:31 -03001752 if (cfg[k].default_i2c_addr != 0)
1753 dpst->i2c_addr = (cfg[k].default_i2c_addr + k) << 1;
1754 else
1755 dpst->i2c_addr = (0x40 + k) << 1;
Patrick Boettchera75763f2006-10-18 08:34:16 -03001756
1757 // unforce divstr
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001758 dib7000p_write_word(dpst, 1285, dpst->i2c_addr << 2);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001759
1760 /* deactivate div - it was just for i2c-enumeration */
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001761 dib7000p_set_output_mode(dpst, OUTMODE_HIGH_Z);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001762 }
1763
Randy Dunlap30d81bb2010-02-08 20:30:44 -03001764 kfree(dpst);
Patrick Boettchera75763f2006-10-18 08:34:16 -03001765 return 0;
1766}
Patrick Boettchera75763f2006-10-18 08:34:16 -03001767
Olivier Grenie713d54a2011-01-04 04:54:31 -03001768static const s32 lut_1000ln_mant[] = {
1769 6908, 6956, 7003, 7047, 7090, 7131, 7170, 7208, 7244, 7279, 7313, 7346, 7377, 7408, 7438, 7467, 7495, 7523, 7549, 7575, 7600
1770};
1771
1772static s32 dib7000p_get_adc_power(struct dvb_frontend *fe)
1773{
1774 struct dib7000p_state *state = fe->demodulator_priv;
1775 u32 tmp_val = 0, exp = 0, mant = 0;
1776 s32 pow_i;
1777 u16 buf[2];
1778 u8 ix = 0;
1779
1780 buf[0] = dib7000p_read_word(state, 0x184);
1781 buf[1] = dib7000p_read_word(state, 0x185);
1782 pow_i = (buf[0] << 16) | buf[1];
1783 dprintk("raw pow_i = %d", pow_i);
1784
1785 tmp_val = pow_i;
1786 while (tmp_val >>= 1)
1787 exp++;
1788
1789 mant = (pow_i * 1000 / (1 << exp));
1790 dprintk(" mant = %d exp = %d", mant / 1000, exp);
1791
1792 ix = (u8) ((mant - 1000) / 100); /* index of the LUT */
1793 dprintk(" ix = %d", ix);
1794
1795 pow_i = (lut_1000ln_mant[ix] + 693 * (exp - 20) - 6908);
1796 pow_i = (pow_i << 8) / 1000;
1797 dprintk(" pow_i = %d", pow_i);
1798
1799 return pow_i;
1800}
1801
1802static int map_addr_to_serpar_number(struct i2c_msg *msg)
1803{
1804 if ((msg->buf[0] <= 15))
1805 msg->buf[0] -= 1;
1806 else if (msg->buf[0] == 17)
1807 msg->buf[0] = 15;
1808 else if (msg->buf[0] == 16)
1809 msg->buf[0] = 17;
1810 else if (msg->buf[0] == 19)
1811 msg->buf[0] = 16;
1812 else if (msg->buf[0] >= 21 && msg->buf[0] <= 25)
1813 msg->buf[0] -= 3;
1814 else if (msg->buf[0] == 28)
1815 msg->buf[0] = 23;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03001816 else
Olivier Grenie713d54a2011-01-04 04:54:31 -03001817 return -EINVAL;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001818 return 0;
1819}
1820
1821static int w7090p_tuner_write_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
1822{
1823 struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
1824 u8 n_overflow = 1;
1825 u16 i = 1000;
1826 u16 serpar_num = msg[0].buf[0];
1827
1828 while (n_overflow == 1 && i) {
1829 n_overflow = (dib7000p_read_word(state, 1984) >> 1) & 0x1;
1830 i--;
1831 if (i == 0)
1832 dprintk("Tuner ITF: write busy (overflow)");
1833 }
1834 dib7000p_write_word(state, 1985, (1 << 6) | (serpar_num & 0x3f));
1835 dib7000p_write_word(state, 1986, (msg[0].buf[1] << 8) | msg[0].buf[2]);
1836
1837 return num;
1838}
1839
1840static int w7090p_tuner_read_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
1841{
1842 struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
1843 u8 n_overflow = 1, n_empty = 1;
1844 u16 i = 1000;
1845 u16 serpar_num = msg[0].buf[0];
1846 u16 read_word;
1847
1848 while (n_overflow == 1 && i) {
1849 n_overflow = (dib7000p_read_word(state, 1984) >> 1) & 0x1;
1850 i--;
1851 if (i == 0)
1852 dprintk("TunerITF: read busy (overflow)");
1853 }
1854 dib7000p_write_word(state, 1985, (0 << 6) | (serpar_num & 0x3f));
1855
1856 i = 1000;
1857 while (n_empty == 1 && i) {
1858 n_empty = dib7000p_read_word(state, 1984) & 0x1;
1859 i--;
1860 if (i == 0)
1861 dprintk("TunerITF: read busy (empty)");
1862 }
1863 read_word = dib7000p_read_word(state, 1987);
1864 msg[1].buf[0] = (read_word >> 8) & 0xff;
1865 msg[1].buf[1] = (read_word) & 0xff;
1866
1867 return num;
1868}
1869
1870static int w7090p_tuner_rw_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
1871{
1872 if (map_addr_to_serpar_number(&msg[0]) == 0) { /* else = Tuner regs to ignore : DIG_CFG, CTRL_RF_LT, PLL_CFG, PWM1_REG, ADCCLK, DIG_CFG_3; SLEEP_EN... */
1873 if (num == 1) { /* write */
1874 return w7090p_tuner_write_serpar(i2c_adap, msg, 1);
1875 } else { /* read */
1876 return w7090p_tuner_read_serpar(i2c_adap, msg, 2);
1877 }
1878 }
1879 return num;
1880}
1881
Olivier Greniea685dbb2011-08-05 14:10:40 -03001882static int dib7090p_rw_on_apb(struct i2c_adapter *i2c_adap,
1883 struct i2c_msg msg[], int num, u16 apb_address)
Olivier Grenie713d54a2011-01-04 04:54:31 -03001884{
1885 struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
1886 u16 word;
1887
1888 if (num == 1) { /* write */
1889 dib7000p_write_word(state, apb_address, ((msg[0].buf[1] << 8) | (msg[0].buf[2])));
1890 } else {
1891 word = dib7000p_read_word(state, apb_address);
1892 msg[1].buf[0] = (word >> 8) & 0xff;
1893 msg[1].buf[1] = (word) & 0xff;
1894 }
1895
1896 return num;
1897}
1898
1899static int dib7090_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
1900{
1901 struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
1902
1903 u16 apb_address = 0, word;
1904 int i = 0;
1905 switch (msg[0].buf[0]) {
1906 case 0x12:
1907 apb_address = 1920;
1908 break;
1909 case 0x14:
1910 apb_address = 1921;
1911 break;
1912 case 0x24:
1913 apb_address = 1922;
1914 break;
1915 case 0x1a:
1916 apb_address = 1923;
1917 break;
1918 case 0x22:
1919 apb_address = 1924;
1920 break;
1921 case 0x33:
1922 apb_address = 1926;
1923 break;
1924 case 0x34:
1925 apb_address = 1927;
1926 break;
1927 case 0x35:
1928 apb_address = 1928;
1929 break;
1930 case 0x36:
1931 apb_address = 1929;
1932 break;
1933 case 0x37:
1934 apb_address = 1930;
1935 break;
1936 case 0x38:
1937 apb_address = 1931;
1938 break;
1939 case 0x39:
1940 apb_address = 1932;
1941 break;
1942 case 0x2a:
1943 apb_address = 1935;
1944 break;
1945 case 0x2b:
1946 apb_address = 1936;
1947 break;
1948 case 0x2c:
1949 apb_address = 1937;
1950 break;
1951 case 0x2d:
1952 apb_address = 1938;
1953 break;
1954 case 0x2e:
1955 apb_address = 1939;
1956 break;
1957 case 0x2f:
1958 apb_address = 1940;
1959 break;
1960 case 0x30:
1961 apb_address = 1941;
1962 break;
1963 case 0x31:
1964 apb_address = 1942;
1965 break;
1966 case 0x32:
1967 apb_address = 1943;
1968 break;
1969 case 0x3e:
1970 apb_address = 1944;
1971 break;
1972 case 0x3f:
1973 apb_address = 1945;
1974 break;
1975 case 0x40:
1976 apb_address = 1948;
1977 break;
1978 case 0x25:
1979 apb_address = 914;
1980 break;
1981 case 0x26:
1982 apb_address = 915;
1983 break;
1984 case 0x27:
Olivier Grenie2e802862011-08-05 10:39:15 -03001985 apb_address = 917;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001986 break;
1987 case 0x28:
Olivier Grenie2e802862011-08-05 10:39:15 -03001988 apb_address = 916;
Olivier Grenie713d54a2011-01-04 04:54:31 -03001989 break;
1990 case 0x1d:
1991 i = ((dib7000p_read_word(state, 72) >> 12) & 0x3);
1992 word = dib7000p_read_word(state, 384 + i);
1993 msg[1].buf[0] = (word >> 8) & 0xff;
1994 msg[1].buf[1] = (word) & 0xff;
1995 return num;
1996 case 0x1f:
1997 if (num == 1) { /* write */
1998 word = (u16) ((msg[0].buf[1] << 8) | msg[0].buf[2]);
1999 word &= 0x3;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002000 word = (dib7000p_read_word(state, 72) & ~(3 << 12)) | (word << 12);
Olivier Grenie713d54a2011-01-04 04:54:31 -03002001 dib7000p_write_word(state, 72, word); /* Set the proper input */
2002 return num;
2003 }
2004 }
2005
2006 if (apb_address != 0) /* R/W acces via APB */
2007 return dib7090p_rw_on_apb(i2c_adap, msg, num, apb_address);
2008 else /* R/W access via SERPAR */
2009 return w7090p_tuner_rw_serpar(i2c_adap, msg, num);
2010
2011 return 0;
2012}
2013
2014static u32 dib7000p_i2c_func(struct i2c_adapter *adapter)
2015{
2016 return I2C_FUNC_I2C;
2017}
2018
2019static struct i2c_algorithm dib7090_tuner_xfer_algo = {
2020 .master_xfer = dib7090_tuner_xfer,
2021 .functionality = dib7000p_i2c_func,
2022};
2023
Mauro Carvalho Chehab8abe4a02014-05-29 09:20:15 -03002024static struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
Olivier Grenie713d54a2011-01-04 04:54:31 -03002025{
2026 struct dib7000p_state *st = fe->demodulator_priv;
2027 return &st->dib7090_tuner_adap;
2028}
Olivier Grenie713d54a2011-01-04 04:54:31 -03002029
2030static int dib7090_host_bus_drive(struct dib7000p_state *state, u8 drive)
2031{
2032 u16 reg;
2033
2034 /* drive host bus 2, 3, 4 */
2035 reg = dib7000p_read_word(state, 1798) & ~((0x7) | (0x7 << 6) | (0x7 << 12));
2036 reg |= (drive << 12) | (drive << 6) | drive;
2037 dib7000p_write_word(state, 1798, reg);
2038
2039 /* drive host bus 5,6 */
2040 reg = dib7000p_read_word(state, 1799) & ~((0x7 << 2) | (0x7 << 8));
2041 reg |= (drive << 8) | (drive << 2);
2042 dib7000p_write_word(state, 1799, reg);
2043
2044 /* drive host bus 7, 8, 9 */
2045 reg = dib7000p_read_word(state, 1800) & ~((0x7) | (0x7 << 6) | (0x7 << 12));
2046 reg |= (drive << 12) | (drive << 6) | drive;
2047 dib7000p_write_word(state, 1800, reg);
2048
2049 /* drive host bus 10, 11 */
2050 reg = dib7000p_read_word(state, 1801) & ~((0x7 << 2) | (0x7 << 8));
2051 reg |= (drive << 8) | (drive << 2);
2052 dib7000p_write_word(state, 1801, reg);
2053
2054 /* drive host bus 12, 13, 14 */
2055 reg = dib7000p_read_word(state, 1802) & ~((0x7) | (0x7 << 6) | (0x7 << 12));
2056 reg |= (drive << 12) | (drive << 6) | drive;
2057 dib7000p_write_word(state, 1802, reg);
2058
2059 return 0;
2060}
2061
2062static u32 dib7090_calcSyncFreq(u32 P_Kin, u32 P_Kout, u32 insertExtSynchro, u32 syncSize)
2063{
2064 u32 quantif = 3;
2065 u32 nom = (insertExtSynchro * P_Kin + syncSize);
2066 u32 denom = P_Kout;
2067 u32 syncFreq = ((nom << quantif) / denom);
2068
2069 if ((syncFreq & ((1 << quantif) - 1)) != 0)
2070 syncFreq = (syncFreq >> quantif) + 1;
2071 else
2072 syncFreq = (syncFreq >> quantif);
2073
2074 if (syncFreq != 0)
2075 syncFreq = syncFreq - 1;
2076
2077 return syncFreq;
2078}
2079
2080static int dib7090_cfg_DibTx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout, u32 insertExtSynchro, u32 synchroMode, u32 syncWord, u32 syncSize)
2081{
Olivier Grenie713d54a2011-01-04 04:54:31 -03002082 dprintk("Configure DibStream Tx");
Olivier Grenie713d54a2011-01-04 04:54:31 -03002083
2084 dib7000p_write_word(state, 1615, 1);
2085 dib7000p_write_word(state, 1603, P_Kin);
2086 dib7000p_write_word(state, 1605, P_Kout);
2087 dib7000p_write_word(state, 1606, insertExtSynchro);
2088 dib7000p_write_word(state, 1608, synchroMode);
2089 dib7000p_write_word(state, 1609, (syncWord >> 16) & 0xffff);
2090 dib7000p_write_word(state, 1610, syncWord & 0xffff);
2091 dib7000p_write_word(state, 1612, syncSize);
2092 dib7000p_write_word(state, 1615, 0);
2093
Olivier Grenie713d54a2011-01-04 04:54:31 -03002094 return 0;
2095}
2096
2097static int dib7090_cfg_DibRx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout, u32 synchroMode, u32 insertExtSynchro, u32 syncWord, u32 syncSize,
2098 u32 dataOutRate)
2099{
2100 u32 syncFreq;
2101
2102 dprintk("Configure DibStream Rx");
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002103 if ((P_Kin != 0) && (P_Kout != 0)) {
Olivier Grenie713d54a2011-01-04 04:54:31 -03002104 syncFreq = dib7090_calcSyncFreq(P_Kin, P_Kout, insertExtSynchro, syncSize);
2105 dib7000p_write_word(state, 1542, syncFreq);
2106 }
2107 dib7000p_write_word(state, 1554, 1);
2108 dib7000p_write_word(state, 1536, P_Kin);
2109 dib7000p_write_word(state, 1537, P_Kout);
2110 dib7000p_write_word(state, 1539, synchroMode);
2111 dib7000p_write_word(state, 1540, (syncWord >> 16) & 0xffff);
2112 dib7000p_write_word(state, 1541, syncWord & 0xffff);
2113 dib7000p_write_word(state, 1543, syncSize);
2114 dib7000p_write_word(state, 1544, dataOutRate);
2115 dib7000p_write_word(state, 1554, 0);
2116
2117 return 0;
2118}
2119
Olivier Grenie2e802862011-08-05 10:39:15 -03002120static void dib7090_enMpegMux(struct dib7000p_state *state, int onoff)
Olivier Grenie713d54a2011-01-04 04:54:31 -03002121{
Olivier Grenie2e802862011-08-05 10:39:15 -03002122 u16 reg_1287 = dib7000p_read_word(state, 1287);
Olivier Grenie713d54a2011-01-04 04:54:31 -03002123
Olivier Grenie2e802862011-08-05 10:39:15 -03002124 switch (onoff) {
2125 case 1:
2126 reg_1287 &= ~(1<<7);
2127 break;
2128 case 0:
2129 reg_1287 |= (1<<7);
2130 break;
2131 }
Olivier Grenie713d54a2011-01-04 04:54:31 -03002132
Olivier Grenie2e802862011-08-05 10:39:15 -03002133 dib7000p_write_word(state, 1287, reg_1287);
Olivier Grenie713d54a2011-01-04 04:54:31 -03002134}
2135
Olivier Grenie2e802862011-08-05 10:39:15 -03002136static void dib7090_configMpegMux(struct dib7000p_state *state,
2137 u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2)
Olivier Grenie713d54a2011-01-04 04:54:31 -03002138{
Olivier Grenie713d54a2011-01-04 04:54:31 -03002139 dprintk("Enable Mpeg mux");
Olivier Grenie713d54a2011-01-04 04:54:31 -03002140
Olivier Grenie2e802862011-08-05 10:39:15 -03002141 dib7090_enMpegMux(state, 0);
Olivier Grenie713d54a2011-01-04 04:54:31 -03002142
Olivier Grenie2e802862011-08-05 10:39:15 -03002143 /* If the input mode is MPEG do not divide the serial clock */
2144 if ((enSerialMode == 1) && (state->input_mode_mpeg == 1))
2145 enSerialClkDiv2 = 0;
Olivier Grenie713d54a2011-01-04 04:54:31 -03002146
Olivier Grenie2e802862011-08-05 10:39:15 -03002147 dib7000p_write_word(state, 1287, ((pulseWidth & 0x1f) << 2)
2148 | ((enSerialMode & 0x1) << 1)
2149 | (enSerialClkDiv2 & 0x1));
2150
2151 dib7090_enMpegMux(state, 1);
Olivier Grenie713d54a2011-01-04 04:54:31 -03002152}
2153
Olivier Grenie2e802862011-08-05 10:39:15 -03002154static void dib7090_setDibTxMux(struct dib7000p_state *state, int mode)
Olivier Grenie713d54a2011-01-04 04:54:31 -03002155{
Olivier Grenie2e802862011-08-05 10:39:15 -03002156 u16 reg_1288 = dib7000p_read_word(state, 1288) & ~(0x7 << 7);
Olivier Grenie713d54a2011-01-04 04:54:31 -03002157
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002158 switch (mode) {
Olivier Grenie2e802862011-08-05 10:39:15 -03002159 case MPEG_ON_DIBTX:
2160 dprintk("SET MPEG ON DIBSTREAM TX");
2161 dib7090_cfg_DibTx(state, 8, 5, 0, 0, 0, 0);
2162 reg_1288 |= (1<<9);
Olivier Grenie713d54a2011-01-04 04:54:31 -03002163 break;
Olivier Grenie2e802862011-08-05 10:39:15 -03002164 case DIV_ON_DIBTX:
2165 dprintk("SET DIV_OUT ON DIBSTREAM TX");
2166 dib7090_cfg_DibTx(state, 5, 5, 0, 0, 0, 0);
2167 reg_1288 |= (1<<8);
Olivier Grenie713d54a2011-01-04 04:54:31 -03002168 break;
Olivier Grenie2e802862011-08-05 10:39:15 -03002169 case ADC_ON_DIBTX:
2170 dprintk("SET ADC_OUT ON DIBSTREAM TX");
2171 dib7090_cfg_DibTx(state, 20, 5, 10, 0, 0, 0);
2172 reg_1288 |= (1<<7);
2173 break;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002174 default:
Olivier Grenie713d54a2011-01-04 04:54:31 -03002175 break;
2176 }
Olivier Grenie2e802862011-08-05 10:39:15 -03002177 dib7000p_write_word(state, 1288, reg_1288);
Olivier Grenie713d54a2011-01-04 04:54:31 -03002178}
2179
Olivier Grenie2e802862011-08-05 10:39:15 -03002180static void dib7090_setHostBusMux(struct dib7000p_state *state, int mode)
Olivier Grenie713d54a2011-01-04 04:54:31 -03002181{
Olivier Grenie2e802862011-08-05 10:39:15 -03002182 u16 reg_1288 = dib7000p_read_word(state, 1288) & ~(0x7 << 4);
2183
2184 switch (mode) {
2185 case DEMOUT_ON_HOSTBUS:
2186 dprintk("SET DEM OUT OLD INTERF ON HOST BUS");
2187 dib7090_enMpegMux(state, 0);
2188 reg_1288 |= (1<<6);
2189 break;
2190 case DIBTX_ON_HOSTBUS:
2191 dprintk("SET DIBSTREAM TX ON HOST BUS");
2192 dib7090_enMpegMux(state, 0);
2193 reg_1288 |= (1<<5);
2194 break;
2195 case MPEG_ON_HOSTBUS:
2196 dprintk("SET MPEG MUX ON HOST BUS");
2197 reg_1288 |= (1<<4);
2198 break;
2199 default:
2200 break;
2201 }
2202 dib7000p_write_word(state, 1288, reg_1288);
2203}
2204
2205int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff)
2206{
2207 struct dib7000p_state *state = fe->demodulator_priv;
2208 u16 reg_1287;
2209
Olivier Grenie713d54a2011-01-04 04:54:31 -03002210 switch (onoff) {
Olivier Grenie2e802862011-08-05 10:39:15 -03002211 case 0: /* only use the internal way - not the diversity input */
2212 dprintk("%s mode OFF : by default Enable Mpeg INPUT", __func__);
2213 dib7090_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0);
2214
2215 /* Do not divide the serial clock of MPEG MUX */
2216 /* in SERIAL MODE in case input mode MPEG is used */
2217 reg_1287 = dib7000p_read_word(state, 1287);
2218 /* enSerialClkDiv2 == 1 ? */
2219 if ((reg_1287 & 0x1) == 1) {
2220 /* force enSerialClkDiv2 = 0 */
2221 reg_1287 &= ~0x1;
2222 dib7000p_write_word(state, 1287, reg_1287);
2223 }
2224 state->input_mode_mpeg = 1;
2225 break;
2226 case 1: /* both ways */
2227 case 2: /* only the diversity input */
2228 dprintk("%s ON : Enable diversity INPUT", __func__);
2229 dib7090_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0);
2230 state->input_mode_mpeg = 0;
2231 break;
Olivier Grenie713d54a2011-01-04 04:54:31 -03002232 }
2233
Olivier Grenie2e802862011-08-05 10:39:15 -03002234 dib7000p_set_diversity_in(&state->demod, onoff);
Olivier Grenie713d54a2011-01-04 04:54:31 -03002235 return 0;
2236}
2237
2238static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode)
2239{
2240 struct dib7000p_state *state = fe->demodulator_priv;
2241
2242 u16 outreg, smo_mode, fifo_threshold;
2243 u8 prefer_mpeg_mux_use = 1;
2244 int ret = 0;
2245
2246 dib7090_host_bus_drive(state, 1);
2247
2248 fifo_threshold = 1792;
2249 smo_mode = (dib7000p_read_word(state, 235) & 0x0050) | (1 << 1);
2250 outreg = dib7000p_read_word(state, 1286) & ~((1 << 10) | (0x7 << 6) | (1 << 1));
2251
2252 switch (mode) {
2253 case OUTMODE_HIGH_Z:
2254 outreg = 0;
2255 break;
2256
2257 case OUTMODE_MPEG2_SERIAL:
2258 if (prefer_mpeg_mux_use) {
Olivier Grenie2e802862011-08-05 10:39:15 -03002259 dprintk("setting output mode TS_SERIAL using Mpeg Mux");
2260 dib7090_configMpegMux(state, 3, 1, 1);
2261 dib7090_setHostBusMux(state, MPEG_ON_HOSTBUS);
2262 } else {/* Use Smooth block */
2263 dprintk("setting output mode TS_SERIAL using Smooth bloc");
2264 dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
2265 outreg |= (2<<6) | (0 << 1);
Olivier Grenie713d54a2011-01-04 04:54:31 -03002266 }
2267 break;
2268
2269 case OUTMODE_MPEG2_PAR_GATED_CLK:
2270 if (prefer_mpeg_mux_use) {
Olivier Grenie2e802862011-08-05 10:39:15 -03002271 dprintk("setting output mode TS_PARALLEL_GATED using Mpeg Mux");
2272 dib7090_configMpegMux(state, 2, 0, 0);
2273 dib7090_setHostBusMux(state, MPEG_ON_HOSTBUS);
2274 } else { /* Use Smooth block */
2275 dprintk("setting output mode TS_PARALLEL_GATED using Smooth block");
2276 dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
2277 outreg |= (0<<6);
Olivier Grenie713d54a2011-01-04 04:54:31 -03002278 }
2279 break;
2280
2281 case OUTMODE_MPEG2_PAR_CONT_CLK: /* Using Smooth block only */
Olivier Grenie2e802862011-08-05 10:39:15 -03002282 dprintk("setting output mode TS_PARALLEL_CONT using Smooth block");
2283 dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
2284 outreg |= (1<<6);
Olivier Grenie713d54a2011-01-04 04:54:31 -03002285 break;
2286
2287 case OUTMODE_MPEG2_FIFO: /* Using Smooth block because not supported by new Mpeg Mux bloc */
Olivier Grenie2e802862011-08-05 10:39:15 -03002288 dprintk("setting output mode TS_FIFO using Smooth block");
2289 dib7090_setHostBusMux(state, DEMOUT_ON_HOSTBUS);
2290 outreg |= (5<<6);
Olivier Grenie713d54a2011-01-04 04:54:31 -03002291 smo_mode |= (3 << 1);
2292 fifo_threshold = 512;
2293 break;
2294
2295 case OUTMODE_DIVERSITY:
Olivier Grenie2e802862011-08-05 10:39:15 -03002296 dprintk("setting output mode MODE_DIVERSITY");
2297 dib7090_setDibTxMux(state, DIV_ON_DIBTX);
2298 dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
Olivier Grenie713d54a2011-01-04 04:54:31 -03002299 break;
2300
2301 case OUTMODE_ANALOG_ADC:
Olivier Grenie2e802862011-08-05 10:39:15 -03002302 dprintk("setting output mode MODE_ANALOG_ADC");
2303 dib7090_setDibTxMux(state, ADC_ON_DIBTX);
2304 dib7090_setHostBusMux(state, DIBTX_ON_HOSTBUS);
Olivier Grenie713d54a2011-01-04 04:54:31 -03002305 break;
2306 }
Olivier Grenie2e802862011-08-05 10:39:15 -03002307 if (mode != OUTMODE_HIGH_Z)
2308 outreg |= (1 << 10);
Olivier Grenie713d54a2011-01-04 04:54:31 -03002309
2310 if (state->cfg.output_mpeg2_in_188_bytes)
2311 smo_mode |= (1 << 5);
2312
2313 ret |= dib7000p_write_word(state, 235, smo_mode);
2314 ret |= dib7000p_write_word(state, 236, fifo_threshold); /* synchronous fread */
Olivier Grenie2e802862011-08-05 10:39:15 -03002315 ret |= dib7000p_write_word(state, 1286, outreg);
Olivier Grenie713d54a2011-01-04 04:54:31 -03002316
2317 return ret;
2318}
2319
Mauro Carvalho Chehab8abe4a02014-05-29 09:20:15 -03002320static int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
Olivier Grenie713d54a2011-01-04 04:54:31 -03002321{
2322 struct dib7000p_state *state = fe->demodulator_priv;
2323 u16 en_cur_state;
2324
2325 dprintk("sleep dib7090: %d", onoff);
2326
2327 en_cur_state = dib7000p_read_word(state, 1922);
2328
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002329 if (en_cur_state > 0xff)
Olivier Grenie713d54a2011-01-04 04:54:31 -03002330 state->tuner_enable = en_cur_state;
Olivier Grenie713d54a2011-01-04 04:54:31 -03002331
2332 if (onoff)
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002333 en_cur_state &= 0x00ff;
Olivier Grenie713d54a2011-01-04 04:54:31 -03002334 else {
2335 if (state->tuner_enable != 0)
2336 en_cur_state = state->tuner_enable;
2337 }
2338
2339 dib7000p_write_word(state, 1922, en_cur_state);
2340
2341 return 0;
2342}
Olivier Grenie713d54a2011-01-04 04:54:31 -03002343
Mauro Carvalho Chehab8abe4a02014-05-29 09:20:15 -03002344static int dib7090_get_adc_power(struct dvb_frontend *fe)
Olivier Grenie713d54a2011-01-04 04:54:31 -03002345{
2346 return dib7000p_get_adc_power(fe);
2347}
Olivier Grenie713d54a2011-01-04 04:54:31 -03002348
Mauro Carvalho Chehab8abe4a02014-05-29 09:20:15 -03002349static int dib7090_slave_reset(struct dvb_frontend *fe)
Olivier Grenie713d54a2011-01-04 04:54:31 -03002350{
2351 struct dib7000p_state *state = fe->demodulator_priv;
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002352 u16 reg;
Olivier Grenie713d54a2011-01-04 04:54:31 -03002353
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002354 reg = dib7000p_read_word(state, 1794);
2355 dib7000p_write_word(state, 1794, reg | (4 << 12));
Olivier Grenie713d54a2011-01-04 04:54:31 -03002356
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002357 dib7000p_write_word(state, 1032, 0xffff);
2358 return 0;
Olivier Grenie713d54a2011-01-04 04:54:31 -03002359}
Olivier Grenie713d54a2011-01-04 04:54:31 -03002360
Patrick Boettchera75763f2006-10-18 08:34:16 -03002361static struct dvb_frontend_ops dib7000p_ops;
Mauro Carvalho Chehab8abe4a02014-05-29 09:20:15 -03002362static struct dvb_frontend *dib7000p_init(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
Patrick Boettchera75763f2006-10-18 08:34:16 -03002363{
2364 struct dvb_frontend *demod;
2365 struct dib7000p_state *st;
2366 st = kzalloc(sizeof(struct dib7000p_state), GFP_KERNEL);
2367 if (st == NULL)
2368 return NULL;
2369
2370 memcpy(&st->cfg, cfg, sizeof(struct dib7000p_config));
2371 st->i2c_adap = i2c_adap;
2372 st->i2c_addr = i2c_addr;
2373 st->gpio_val = cfg->gpio_val;
2374 st->gpio_dir = cfg->gpio_dir;
2375
Steven Totha38d6e32008-04-22 15:37:01 -03002376 /* Ensure the output mode remains at the previous default if it's
2377 * not specifically set by the caller.
2378 */
Olivier Grenie713d54a2011-01-04 04:54:31 -03002379 if ((st->cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (st->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
Steven Totha38d6e32008-04-22 15:37:01 -03002380 st->cfg.output_mode = OUTMODE_MPEG2_FIFO;
2381
Olivier Grenie713d54a2011-01-04 04:54:31 -03002382 demod = &st->demod;
Patrick Boettchera75763f2006-10-18 08:34:16 -03002383 demod->demodulator_priv = st;
2384 memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002385 mutex_init(&st->i2c_buffer_lock);
Patrick Boettchera75763f2006-10-18 08:34:16 -03002386
Olivier Grenie713d54a2011-01-04 04:54:31 -03002387 dib7000p_write_word(st, 1287, 0x0003); /* sram lead in, rdy */
Olivier Grenieeac1fe12009-09-23 13:41:27 -03002388
Patrick Boettchera75763f2006-10-18 08:34:16 -03002389 if (dib7000p_identify(st) != 0)
2390 goto error;
2391
Olivier Grenie713d54a2011-01-04 04:54:31 -03002392 st->version = dib7000p_read_word(st, 897);
2393
Martin Samek7646b9d2009-09-30 22:59:09 -03002394 /* FIXME: make sure the dev.parent field is initialized, or else
Patrick Boettcher79fcce32011-08-03 12:08:21 -03002395 request_firmware() will hit an OOPS (this should be moved somewhere
2396 more common) */
2397 st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent;
Martin Samek7646b9d2009-09-30 22:59:09 -03002398
Patrick Boettchera75763f2006-10-18 08:34:16 -03002399 dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr);
2400
Olivier Grenie713d54a2011-01-04 04:54:31 -03002401 /* init 7090 tuner adapter */
2402 strncpy(st->dib7090_tuner_adap.name, "DiB7090 tuner interface", sizeof(st->dib7090_tuner_adap.name));
2403 st->dib7090_tuner_adap.algo = &dib7090_tuner_xfer_algo;
2404 st->dib7090_tuner_adap.algo_data = NULL;
2405 st->dib7090_tuner_adap.dev.parent = st->i2c_adap->dev.parent;
2406 i2c_set_adapdata(&st->dib7090_tuner_adap, st);
2407 i2c_add_adapter(&st->dib7090_tuner_adap);
2408
Patrick Boettchera75763f2006-10-18 08:34:16 -03002409 dib7000p_demod_reset(st);
2410
Olivier Grenie713d54a2011-01-04 04:54:31 -03002411 if (st->version == SOC7090) {
2412 dib7090_set_output_mode(demod, st->cfg.output_mode);
2413 dib7090_set_diversity_in(demod, 0);
2414 }
2415
Patrick Boettchera75763f2006-10-18 08:34:16 -03002416 return demod;
2417
Olivier Grenieb4d6046e2011-01-04 13:08:14 -03002418error:
Patrick Boettchera75763f2006-10-18 08:34:16 -03002419 kfree(st);
2420 return NULL;
2421}
Mauro Carvalho Chehab8abe4a02014-05-29 09:20:15 -03002422
2423void *dib7000p_attach(struct dib7000p_ops *ops)
2424{
2425 if (!ops)
2426 return NULL;
2427
2428 ops->slave_reset = dib7090_slave_reset;
2429 ops->get_adc_power = dib7090_get_adc_power;
2430 ops->dib7000pc_detection = dib7000pc_detection;
2431 ops->get_i2c_tuner = dib7090_get_i2c_tuner;
2432 ops->tuner_sleep = dib7090_tuner_sleep;
2433 ops->init = dib7000p_init;
2434 ops->set_agc1_min = dib7000p_set_agc1_min;
2435 ops->set_gpio = dib7000p_set_gpio;
2436 ops->i2c_enumeration = dib7000p_i2c_enumeration;
2437 ops->pid_filter = dib7000p_pid_filter;
2438 ops->pid_filter_ctrl = dib7000p_pid_filter_ctrl;
2439 ops->get_i2c_master = dib7000p_get_i2c_master;
2440 ops->update_pll = dib7000p_update_pll;
2441 ops->ctrl_timf = dib7000p_ctrl_timf;
2442 ops->get_agc_values = dib7000p_get_agc_values;
2443 ops->set_wbd_ref = dib7000p_set_wbd_ref;
2444
2445 return ops;
2446}
2447EXPORT_SYMBOL(dib7000p_attach);
Patrick Boettchera75763f2006-10-18 08:34:16 -03002448
2449static struct dvb_frontend_ops dib7000p_ops = {
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03002450 .delsys = { SYS_DVBT },
Patrick Boettchera75763f2006-10-18 08:34:16 -03002451 .info = {
Olivier Grenie713d54a2011-01-04 04:54:31 -03002452 .name = "DiBcom 7000PC",
Olivier Grenie713d54a2011-01-04 04:54:31 -03002453 .frequency_min = 44250000,
2454 .frequency_max = 867250000,
2455 .frequency_stepsize = 62500,
2456 .caps = FE_CAN_INVERSION_AUTO |
2457 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
2458 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
2459 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
2460 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO,
2461 },
Patrick Boettchera75763f2006-10-18 08:34:16 -03002462
Olivier Grenie713d54a2011-01-04 04:54:31 -03002463 .release = dib7000p_release,
Patrick Boettchera75763f2006-10-18 08:34:16 -03002464
Olivier Grenie713d54a2011-01-04 04:54:31 -03002465 .init = dib7000p_wakeup,
2466 .sleep = dib7000p_sleep,
Patrick Boettchera75763f2006-10-18 08:34:16 -03002467
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03002468 .set_frontend = dib7000p_set_frontend,
Olivier Grenie713d54a2011-01-04 04:54:31 -03002469 .get_tune_settings = dib7000p_fe_get_tune_settings,
Mauro Carvalho Chehabc1f814f2011-12-22 19:06:20 -03002470 .get_frontend = dib7000p_get_frontend,
Patrick Boettchera75763f2006-10-18 08:34:16 -03002471
Olivier Grenie713d54a2011-01-04 04:54:31 -03002472 .read_status = dib7000p_read_status,
2473 .read_ber = dib7000p_read_ber,
Patrick Boettchera75763f2006-10-18 08:34:16 -03002474 .read_signal_strength = dib7000p_read_signal_strength,
Olivier Grenie713d54a2011-01-04 04:54:31 -03002475 .read_snr = dib7000p_read_snr,
2476 .read_ucblocks = dib7000p_read_unc_blocks,
Patrick Boettchera75763f2006-10-18 08:34:16 -03002477};
2478
Olivier Grenie713d54a2011-01-04 04:54:31 -03002479MODULE_AUTHOR("Olivier Grenie <ogrenie@dibcom.fr>");
Patrick Boettchera75763f2006-10-18 08:34:16 -03002480MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
2481MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator");
2482MODULE_LICENSE("GPL");