aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/frontends
diff options
context:
space:
mode:
authorOlivier Grenie <Olivier.Grenie@dibcom.fr>2009-12-04 11:27:57 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-12-15 21:18:16 -0500
commit03245a5ee69a5faa99b020fe1aca9bafe10c46a9 (patch)
tree0937b4966ff1f5e09bfcd38fd38bc55e7ac2abef /drivers/media/dvb/frontends
parent20232c4791507189d4e9499f81632a1ce434f2a4 (diff)
V4L/DVB (13583): DiB8090: Add the DiB0090 tuner driver and STK8096GP-board
This patchs adds support for the DiBcom DiB0090 RF tuner and for DiBcom's reference design STK8096GP. Small extracts of the DiB0070 and the DiB8000-driver into a common codebase. Signed-off-by: Patrick Boettcher <pboettcher@kernellabs.com> Signed-off-by: Olivier Grenie <Olivier.Grenie@dibcom.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/frontends')
-rw-r--r--drivers/media/dvb/frontends/Kconfig9
-rw-r--r--drivers/media/dvb/frontends/Makefile1
-rw-r--r--drivers/media/dvb/frontends/dib0070.c654
-rw-r--r--drivers/media/dvb/frontends/dib0070.h4
-rw-r--r--drivers/media/dvb/frontends/dib0090.c1525
-rw-r--r--drivers/media/dvb/frontends/dib0090.h114
-rw-r--r--drivers/media/dvb/frontends/dib8000.c64
-rw-r--r--drivers/media/dvb/frontends/dib8000.h32
-rw-r--r--drivers/media/dvb/frontends/dibx000_common.c15
-rw-r--r--drivers/media/dvb/frontends/dibx000_common.h71
10 files changed, 2150 insertions, 339 deletions
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 58aac018f109..a3b8b697349b 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -526,6 +526,15 @@ config DVB_TUNER_DIB0070
526 This device is only used inside a SiP called together with a 526 This device is only used inside a SiP called together with a
527 demodulator for now. 527 demodulator for now.
528 528
529config DVB_TUNER_DIB0090
530 tristate "DiBcom DiB0090 silicon base-band tuner"
531 depends on I2C
532 default m if DVB_FE_CUSTOMISE
533 help
534 A driver for the silicon baseband tuner DiB0090 from DiBcom.
535 This device is only used inside a SiP called together with a
536 demodulator for now.
537
529comment "SEC control devices for DVB-S" 538comment "SEC control devices for DVB-S"
530 depends on DVB_CORE 539 depends on DVB_CORE
531 540
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index 823482535d11..47575cc7b699 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_DVB_TDA10086) += tda10086.o
55obj-$(CONFIG_DVB_TDA826X) += tda826x.o 55obj-$(CONFIG_DVB_TDA826X) += tda826x.o
56obj-$(CONFIG_DVB_TDA8261) += tda8261.o 56obj-$(CONFIG_DVB_TDA8261) += tda8261.o
57obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o 57obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o
58obj-$(CONFIG_DVB_TUNER_DIB0090) += dib0090.o
58obj-$(CONFIG_DVB_TUA6100) += tua6100.o 59obj-$(CONFIG_DVB_TUA6100) += tua6100.o
59obj-$(CONFIG_DVB_S5H1409) += s5h1409.o 60obj-$(CONFIG_DVB_S5H1409) += s5h1409.o
60obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o 61obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o
diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c
index 2be17b93e0bd..81860b2cfe98 100644
--- a/drivers/media/dvb/frontends/dib0070.c
+++ b/drivers/media/dvb/frontends/dib0070.c
@@ -49,21 +49,6 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
49#define DIB0070_P1G 0x03 49#define DIB0070_P1G 0x03
50#define DIB0070S_P1A 0x02 50#define DIB0070S_P1A 0x02
51 51
52enum frontend_tune_state {
53 CT_TUNER_START = 10,
54 CT_TUNER_STEP_0,
55 CT_TUNER_STEP_1,
56 CT_TUNER_STEP_2,
57 CT_TUNER_STEP_3,
58 CT_TUNER_STEP_4,
59 CT_TUNER_STEP_5,
60 CT_TUNER_STEP_6,
61 CT_TUNER_STEP_7,
62 CT_TUNER_STOP,
63};
64
65#define FE_CALLBACK_TIME_NEVER 0xffffffff
66
67struct dib0070_state { 52struct dib0070_state {
68 struct i2c_adapter *i2c; 53 struct i2c_adapter *i2c;
69 struct dvb_frontend *fe; 54 struct dvb_frontend *fe;
@@ -71,10 +56,10 @@ struct dib0070_state {
71 u16 wbd_ff_offset; 56 u16 wbd_ff_offset;
72 u8 revision; 57 u8 revision;
73 58
74 enum frontend_tune_state tune_state; 59 enum frontend_tune_state tune_state;
75 u32 current_rf; 60 u32 current_rf;
76 61
77 /* for the captrim binary search */ 62 /* for the captrim binary search */
78 s8 step; 63 s8 step;
79 u16 adc_diff; 64 u16 adc_diff;
80 65
@@ -85,7 +70,7 @@ struct dib0070_state {
85 const struct dib0070_tuning *current_tune_table_index; 70 const struct dib0070_tuning *current_tune_table_index;
86 const struct dib0070_lna_match *lna_match; 71 const struct dib0070_lna_match *lna_match;
87 72
88 u8 wbd_gain_current; 73 u8 wbd_gain_current;
89 u16 wbd_offset_3_3[2]; 74 u16 wbd_offset_3_3[2];
90}; 75};
91 76
@@ -93,8 +78,8 @@ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
93{ 78{
94 u8 b[2]; 79 u8 b[2];
95 struct i2c_msg msg[2] = { 80 struct i2c_msg msg[2] = {
96 {.addr = state->cfg->i2c_address,.flags = 0,.buf = &reg,.len = 1}, 81 { .addr = state->cfg->i2c_address, .flags = 0, .buf = &reg, .len = 1 },
97 {.addr = state->cfg->i2c_address,.flags = I2C_M_RD,.buf = b,.len = 2}, 82 { .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2 },
98 }; 83 };
99 if (i2c_transfer(state->i2c, msg, 2) != 2) { 84 if (i2c_transfer(state->i2c, msg, 2) != 2) {
100 printk(KERN_WARNING "DiB0070 I2C read failed\n"); 85 printk(KERN_WARNING "DiB0070 I2C read failed\n");
@@ -106,7 +91,7 @@ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg)
106static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) 91static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
107{ 92{
108 u8 b[3] = { reg, val >> 8, val & 0xff }; 93 u8 b[3] = { reg, val >> 8, val & 0xff };
109 struct i2c_msg msg = {.addr = state->cfg->i2c_address,.flags = 0,.buf = b,.len = 3 }; 94 struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = b, .len = 3 };
110 if (i2c_transfer(state->i2c, &msg, 1) != 1) { 95 if (i2c_transfer(state->i2c, &msg, 1) != 1) {
111 printk(KERN_WARNING "DiB0070 I2C write failed\n"); 96 printk(KERN_WARNING "DiB0070 I2C write failed\n");
112 return -EREMOTEIO; 97 return -EREMOTEIO;
@@ -124,30 +109,30 @@ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
124 109
125static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) 110static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
126{ 111{
127 struct dib0070_state *state = fe->tuner_priv; 112 struct dib0070_state *state = fe->tuner_priv;
128 u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff; 113 u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
129 114
130 if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 7000) 115 if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 7000)
131 tmp |= (0 << 14); 116 tmp |= (0 << 14);
132 else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 6000) 117 else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 6000)
133 tmp |= (1 << 14); 118 tmp |= (1 << 14);
134 else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 5000) 119 else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 5000)
135 tmp |= (2 << 14); 120 tmp |= (2 << 14);
136 else 121 else
137 tmp |= (3 << 14); 122 tmp |= (3 << 14);
138 123
139 dib0070_write_reg(state, 0x02, tmp); 124 dib0070_write_reg(state, 0x02, tmp);
140 125
141 /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */ 126 /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */
142 if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) { 127 if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) {
143 u16 value = dib0070_read_reg(state, 0x17); 128 u16 value = dib0070_read_reg(state, 0x17);
144 129
145 dib0070_write_reg(state, 0x17, value & 0xfffc); 130 dib0070_write_reg(state, 0x17, value & 0xfffc);
146 tmp = dib0070_read_reg(state, 0x01) & 0x01ff; 131 tmp = dib0070_read_reg(state, 0x01) & 0x01ff;
147 dib0070_write_reg(state, 0x01, tmp | (60 << 9)); 132 dib0070_write_reg(state, 0x01, tmp | (60 << 9));
148 133
149 dib0070_write_reg(state, 0x17, value); 134 dib0070_write_reg(state, 0x17, value);
150 } 135 }
151 return 0; 136 return 0;
152} 137}
153 138
@@ -160,14 +145,14 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state
160 if (*tune_state == CT_TUNER_STEP_0) { 145 if (*tune_state == CT_TUNER_STEP_0) {
161 146
162 dib0070_write_reg(state, 0x0f, 0xed10); 147 dib0070_write_reg(state, 0x0f, 0xed10);
163 dib0070_write_reg(state, 0x17, 0x0034); 148 dib0070_write_reg(state, 0x17, 0x0034);
164 149
165 dib0070_write_reg(state, 0x18, 0x0032); 150 dib0070_write_reg(state, 0x18, 0x0032);
166 state->step = state->captrim = state->fcaptrim = 64; 151 state->step = state->captrim = state->fcaptrim = 64;
167 state->adc_diff = 3000; 152 state->adc_diff = 3000;
168 ret = 20; 153 ret = 20;
169 154
170 *tune_state = CT_TUNER_STEP_1; 155 *tune_state = CT_TUNER_STEP_1;
171 } else if (*tune_state == CT_TUNER_STEP_1) { 156 } else if (*tune_state == CT_TUNER_STEP_1) {
172 state->step /= 2; 157 state->step /= 2;
173 dib0070_write_reg(state, 0x14, state->lo4 | state->captrim); 158 dib0070_write_reg(state, 0x14, state->lo4 | state->captrim);
@@ -178,7 +163,7 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state
178 163
179 adc = dib0070_read_reg(state, 0x19); 164 adc = dib0070_read_reg(state, 0x19);
180 165
181 dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc * (u32) 1800 / (u32) 1024); 166 dprintk( "CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc*(u32)1800/(u32)1024);
182 167
183 if (adc >= 400) { 168 if (adc >= 400) {
184 adc -= 400; 169 adc -= 400;
@@ -189,10 +174,12 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state
189 } 174 }
190 175
191 if (adc < state->adc_diff) { 176 if (adc < state->adc_diff) {
192 dprintk("CAPTRIM=%hd is closer to target (%hd/%hd)", state->captrim, adc, state->adc_diff); 177 dprintk( "CAPTRIM=%hd is closer to target (%hd/%hd)", state->captrim, adc, state->adc_diff);
193 state->adc_diff = adc; 178 state->adc_diff = adc;
194 state->fcaptrim = state->captrim; 179 state->fcaptrim = state->captrim;
195 180
181
182
196 } 183 }
197 state->captrim += (step_sign * state->step); 184 state->captrim += (step_sign * state->step);
198 185
@@ -213,8 +200,8 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state
213static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt) 200static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt)
214{ 201{
215 struct dib0070_state *state = fe->tuner_priv; 202 struct dib0070_state *state = fe->tuner_priv;
216 u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0); 203 u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
217 dprintk("CTRL_LO5: 0x%x", lo5); 204 dprintk( "CTRL_LO5: 0x%x", lo5);
218 return dib0070_write_reg(state, 0x15, lo5); 205 return dib0070_write_reg(state, 0x15, lo5);
219} 206}
220 207
@@ -227,171 +214,175 @@ void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
227 dib0070_write_reg(state, 0x1a, 0x0000); 214 dib0070_write_reg(state, 0x1a, 0x0000);
228 } else { 215 } else {
229 dib0070_write_reg(state, 0x1b, 0x4112); 216 dib0070_write_reg(state, 0x1b, 0x4112);
230 if (state->cfg->vga_filter != 0) { 217 if (state->cfg->vga_filter != 0) {
231 dib0070_write_reg(state, 0x1a, state->cfg->vga_filter); 218 dib0070_write_reg(state, 0x1a, state->cfg->vga_filter);
232 dprintk("vga filter register is set to %x", state->cfg->vga_filter); 219 dprintk( "vga filter register is set to %x", state->cfg->vga_filter);
233 } else 220 } else
234 dib0070_write_reg(state, 0x1a, 0x0009); 221 dib0070_write_reg(state, 0x1a, 0x0009);
235 } 222 }
236} 223}
237 224
238EXPORT_SYMBOL(dib0070_ctrl_agc_filter); 225EXPORT_SYMBOL(dib0070_ctrl_agc_filter);
239struct dib0070_tuning { 226struct dib0070_tuning {
240 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ 227 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
241 u8 switch_trim; 228 u8 switch_trim;
242 u8 vco_band; 229 u8 vco_band;
243 u8 hfdiv; 230 u8 hfdiv;
244 u8 vco_multi; 231 u8 vco_multi;
245 u8 presc; 232 u8 presc;
246 u8 wbdmux; 233 u8 wbdmux;
247 u16 tuner_enable; 234 u16 tuner_enable;
248}; 235};
249 236
250struct dib0070_lna_match { 237struct dib0070_lna_match {
251 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ 238 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
252 u8 lna_band; 239 u8 lna_band;
253}; 240};
254 241
255static const struct dib0070_tuning dib0070s_tuning_table[] = { 242static const struct dib0070_tuning dib0070s_tuning_table[] = {
256 {570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800}, /* UHF */ 243 { 570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */
257 {700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800}, 244 { 700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 },
258 {863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800}, 245 { 863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 },
259 {1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400}, /* LBAND */ 246 { 1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */
260 {1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400}, 247 { 1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
261 {2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400}, 248 { 2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
262 {0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000}, /* SBAND */ 249 { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */
263}; 250};
264 251
265static const struct dib0070_tuning dib0070_tuning_table[] = { 252static const struct dib0070_tuning dib0070_tuning_table[] = {
266 {115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000}, /* FM below 92MHz cannot be tuned */ 253 { 115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */
267 {179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000}, /* VHF */ 254 { 179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */
268 {189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000}, 255 { 189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 },
269 {250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000}, 256 { 250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 },
270 {569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800}, /* UHF */ 257 { 569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800 }, /* UHF */
271 {699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800}, 258 { 699999, 2, 0 ,1, 4, 2, 2, 0x4000 | 0x0800 },
272 {863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800}, 259 { 863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800 },
273 {0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400}, /* LBAND or everything higher than UHF */ 260 { 0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */
274}; 261};
275 262
276static const struct dib0070_lna_match dib0070_lna_flip_chip[] = { 263static const struct dib0070_lna_match dib0070_lna_flip_chip[] = {
277 {180000, 0}, /* VHF */ 264 { 180000, 0 }, /* VHF */
278 {188000, 1}, 265 { 188000, 1 },
279 {196400, 2}, 266 { 196400, 2 },
280 {250000, 3}, 267 { 250000, 3 },
281 {550000, 0}, /* UHF */ 268 { 550000, 0 }, /* UHF */
282 {590000, 1}, 269 { 590000, 1 },
283 {666000, 3}, 270 { 666000, 3 },
284 {864000, 5}, 271 { 864000, 5 },
285 {1500000, 0}, /* LBAND or everything higher than UHF */ 272 { 1500000, 0 }, /* LBAND or everything higher than UHF */
286 {1600000, 1}, 273 { 1600000, 1 },
287 {2000000, 3}, 274 { 2000000, 3 },
288 {0xffffffff, 7}, 275 { 0xffffffff, 7 },
289}; 276};
290 277
291static const struct dib0070_lna_match dib0070_lna[] = { 278static const struct dib0070_lna_match dib0070_lna[] = {
292 {180000, 0}, /* VHF */ 279 { 180000, 0 }, /* VHF */
293 {188000, 1}, 280 { 188000, 1 },
294 {196400, 2}, 281 { 196400, 2 },
295 {250000, 3}, 282 { 250000, 3 },
296 {550000, 2}, /* UHF */ 283 { 550000, 2 }, /* UHF */
297 {650000, 3}, 284 { 650000, 3 },
298 {750000, 5}, 285 { 750000, 5 },
299 {850000, 6}, 286 { 850000, 6 },
300 {864000, 7}, 287 { 864000, 7 },
301 {1500000, 0}, /* LBAND or everything higher than UHF */ 288 { 1500000, 0 }, /* LBAND or everything higher than UHF */
302 {1600000, 1}, 289 { 1600000, 1 },
303 {2000000, 3}, 290 { 2000000, 3 },
304 {0xffffffff, 7}, 291 { 0xffffffff, 7 },
305}; 292};
306 293
307#define LPF 100 // define for the loop filter 100kHz by default 16-07-06 294#define LPF 100 // define for the loop filter 100kHz by default 16-07-06
308static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) 295static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
309{ 296{
310 struct dib0070_state *state = fe->tuner_priv; 297 struct dib0070_state *state = fe->tuner_priv;
311 298
312 const struct dib0070_tuning *tune; 299 const struct dib0070_tuning *tune;
313 const struct dib0070_lna_match *lna_match; 300 const struct dib0070_lna_match *lna_match;
314 301
315 enum frontend_tune_state *tune_state = &state->tune_state; 302 enum frontend_tune_state *tune_state = &state->tune_state;
316 int ret = 10; /* 1ms is the default delay most of the time */ 303 int ret = 10; /* 1ms is the default delay most of the time */
317 304
318 u8 band = (u8) BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000); 305 u8 band = (u8)BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency/1000);
319 u32 freq = fe->dtv_property_cache.frequency / 1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf); 306 u32 freq = fe->dtv_property_cache.frequency/1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf);
320 307
321#ifdef CONFIG_SYS_ISDBT 308#ifdef CONFIG_SYS_ISDBT
322 if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1) 309 if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
323 if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) 310 if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2)
324 && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))) 311 && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
325 || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) 312 || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
326 && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2))) 313 && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2)))
327 || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) 314 || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
328 && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))) 315 && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))))
329 freq += 850; 316 freq += 850;
330#endif 317#endif
318 if (state->current_rf != freq) {
319
320 switch (state->revision) {
321 case DIB0070S_P1A:
322 tune = dib0070s_tuning_table;
323 lna_match = dib0070_lna;
324 break;
325 default:
326 tune = dib0070_tuning_table;
327 if (state->cfg->flip_chip)
328 lna_match = dib0070_lna_flip_chip;
329 else
330 lna_match = dib0070_lna;
331 break;
332 }
333 while (freq > tune->max_freq) /* find the right one */
334 tune++;
335 while (freq > lna_match->max_freq) /* find the right one */
336 lna_match++;
337
338 state->current_tune_table_index = tune;
339 state->lna_match = lna_match;
340 }
341
342 if (*tune_state == CT_TUNER_START) {
343 dprintk( "Tuning for Band: %hd (%d kHz)", band, freq);
331 if (state->current_rf != freq) { 344 if (state->current_rf != freq) {
345 u8 REFDIV;
346 u32 FBDiv, Rest, FREF, VCOF_kHz;
347 u8 Den;
332 348
333 switch (state->revision) { 349 state->current_rf = freq;
334 case DIB0070S_P1A: 350 state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
335 tune = dib0070s_tuning_table;
336 lna_match = dib0070_lna;
337 break;
338 default:
339 tune = dib0070_tuning_table;
340 if (state->cfg->flip_chip)
341 lna_match = dib0070_lna_flip_chip;
342 else
343 lna_match = dib0070_lna;
344 break;
345 }
346 while (freq > tune->max_freq) /* find the right one */
347 tune++;
348 while (freq > lna_match->max_freq) /* find the right one */
349 lna_match++;
350 351
351 state->current_tune_table_index = tune;
352 state->lna_match = lna_match;
353 }
354 352
355 if (*tune_state == CT_TUNER_START) { 353 dib0070_write_reg(state, 0x17, 0x30);
356 dprintk("Tuning for Band: %hd (%d kHz)", band, freq); 354
357 if (state->current_rf != freq) { 355
358 u8 REFDIV; 356 VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
359 u32 FBDiv, Rest, FREF, VCOF_kHz; 357
360 u8 Den; 358 switch (band) {
361 359 case BAND_VHF:
362 state->current_rf = freq; 360 REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000);
363 state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7); 361 break;
364 362 case BAND_FM:
365 dib0070_write_reg(state, 0x17, 0x30); 363 REFDIV = (u8) ((state->cfg->clock_khz) / 1000);
366 364 break;
367 VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2; 365 default:
368 366 REFDIV = (u8) ( state->cfg->clock_khz / 10000);
369 switch (band) { 367 break;
370 case BAND_VHF: 368 }
371 REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000); 369 FREF = state->cfg->clock_khz / REFDIV;
372 break; 370
373 case BAND_FM: 371
374 REFDIV = (u8) ((state->cfg->clock_khz) / 1000); 372
375 break; 373 switch (state->revision) {
376 default: 374 case DIB0070S_P1A:
377 REFDIV = (u8) (state->cfg->clock_khz / 10000); 375 FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF);
378 break; 376 Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF;
379 } 377 break;
380 FREF = state->cfg->clock_khz / REFDIV; 378
381 379 case DIB0070_P1G:
382 switch (state->revision) { 380 case DIB0070_P1F:
383 case DIB0070S_P1A: 381 default:
384 FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF); 382 FBDiv = (freq / (FREF / 2));
385 Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF; 383 Rest = 2 * freq - FBDiv * FREF;
386 break; 384 break;
387 385 }
388 case DIB0070_P1G:
389 case DIB0070_P1F:
390 default:
391 FBDiv = (freq / (FREF / 2));
392 Rest = 2 * freq - FBDiv * FREF;
393 break;
394 }
395 386
396 if (Rest < LPF) 387 if (Rest < LPF)
397 Rest = 0; 388 Rest = 0;
@@ -402,98 +393,102 @@ static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_par
402 FBDiv += 1; 393 FBDiv += 1;
403 } else if (Rest > (FREF - 2 * LPF)) 394 } else if (Rest > (FREF - 2 * LPF))
404 Rest = FREF - 2 * LPF; 395 Rest = FREF - 2 * LPF;
405 Rest = (Rest * 6528) / (FREF / 10); 396 Rest = (Rest * 6528) / (FREF / 10);
406 397
407 Den = 1; 398 Den = 1;
408 if (Rest > 0) { 399 if (Rest > 0) {
409 state->lo4 |= (1 << 14) | (1 << 12); 400 state->lo4 |= (1 << 14) | (1 << 12);
410 Den = 255; 401 Den = 255;
411 } 402 }
412 403
413 dib0070_write_reg(state, 0x11, (u16) FBDiv);
414 dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV);
415 dib0070_write_reg(state, 0x13, (u16) Rest);
416 404
417 if (state->revision == DIB0070S_P1A) { 405 dib0070_write_reg(state, 0x11, (u16)FBDiv);
406 dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV);
407 dib0070_write_reg(state, 0x13, (u16) Rest);
418 408
419 if (band == BAND_SBAND) { 409 if (state->revision == DIB0070S_P1A) {
420 dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); 410
421 dib0070_write_reg(state, 0x1d, 0xFFFF); 411 if (band == BAND_SBAND) {
422 } else 412 dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
423 dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1); 413 dib0070_write_reg(state, 0x1d,0xFFFF);
424 } 414 } else
415 dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1);
416 }
425 417
426 dib0070_write_reg(state, 0x20, 418 dib0070_write_reg(state, 0x20,
427 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable); 419 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
428 420
429 dprintk("REFDIV: %hd, FREF: %d", REFDIV, FREF); 421 dprintk( "REFDIV: %hd, FREF: %d", REFDIV, FREF);
430 dprintk("FBDIV: %d, Rest: %d", FBDiv, Rest); 422 dprintk( "FBDIV: %d, Rest: %d", FBDiv, Rest);
431 dprintk("Num: %hd, Den: %hd, SD: %hd", (u16) Rest, Den, (state->lo4 >> 12) & 0x1); 423 dprintk( "Num: %hd, Den: %hd, SD: %hd",(u16) Rest, Den, (state->lo4 >> 12) & 0x1);
432 dprintk("HFDIV code: %hd", state->current_tune_table_index->hfdiv); 424 dprintk( "HFDIV code: %hd", state->current_tune_table_index->hfdiv);
433 dprintk("VCO = %hd", state->current_tune_table_index->vco_band); 425 dprintk( "VCO = %hd", state->current_tune_table_index->vco_band);
434 dprintk("VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq); 426 dprintk( "VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq);
435 427
436 *tune_state = CT_TUNER_STEP_0; 428 *tune_state = CT_TUNER_STEP_0;
437 } else { /* we are already tuned to this frequency - the configuration is correct */ 429 } else { /* we are already tuned to this frequency - the configuration is correct */
438 ret = 50; /* wakeup time */ 430 ret = 50; /* wakeup time */
439 *tune_state = CT_TUNER_STEP_5; 431 *tune_state = CT_TUNER_STEP_5;
440 } 432 }
441 } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) { 433 } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
442 434
443 ret = dib0070_captrim(state, tune_state); 435 ret = dib0070_captrim(state, tune_state);
444 436
445 } else if (*tune_state == CT_TUNER_STEP_4) { 437 } else if (*tune_state == CT_TUNER_STEP_4) {
446 const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain; 438 const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
447 if (tmp != NULL) { 439 if (tmp != NULL) {
448 while (freq / 1000 > tmp->freq) /* find the right one */ 440 while (freq/1000 > tmp->freq) /* find the right one */
449 tmp++; 441 tmp++;
450 dib0070_write_reg(state, 0x0f, 442 dib0070_write_reg(state, 0x0f,
451 (0 << 15) | (1 << 14) | (3 << 12) | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7) | (state-> 443 (0 << 15) | (1 << 14) | (3 << 12) | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7) | (state->
452 current_tune_table_index-> 444 current_tune_table_index->
453 wbdmux << 0)); 445 wbdmux << 0));
454 state->wbd_gain_current = tmp->wbd_gain_val; 446 state->wbd_gain_current = tmp->wbd_gain_val;
455 } else { 447 } else {
456 dib0070_write_reg(state, 0x0f, 448 dib0070_write_reg(state, 0x0f,
457 (0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (state->current_tune_table_index-> 449 (0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (state->current_tune_table_index->
458 wbdmux << 0)); 450 wbdmux << 0));
459 state->wbd_gain_current = 6; 451 state->wbd_gain_current = 6;
460 } 452 }
461 453
462 dib0070_write_reg(state, 0x06, 0x3fff); 454 dib0070_write_reg(state, 0x06, 0x3fff);
463 dib0070_write_reg(state, 0x07, 455 dib0070_write_reg(state, 0x07,
464 (state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0)); 456 (state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0));
465 dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127)); 457 dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127));
466 dib0070_write_reg(state, 0x0d, 0x0d80); 458 dib0070_write_reg(state, 0x0d, 0x0d80);
467 459
468 dib0070_write_reg(state, 0x18, 0x07ff);
469 dib0070_write_reg(state, 0x17, 0x0033);
470 460
471 *tune_state = CT_TUNER_STEP_5; 461 dib0070_write_reg(state, 0x18, 0x07ff);
472 } else if (*tune_state == CT_TUNER_STEP_5) { 462 dib0070_write_reg(state, 0x17, 0x0033);
473 dib0070_set_bandwidth(fe, ch); 463
474 *tune_state = CT_TUNER_STOP; 464
475 } else { 465 *tune_state = CT_TUNER_STEP_5;
476 ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */ 466 } else if (*tune_state == CT_TUNER_STEP_5) {
477 } 467 dib0070_set_bandwidth(fe, ch);
478 return ret; 468 *tune_state = CT_TUNER_STOP;
469 } else {
470 ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */
471 }
472 return ret;
479} 473}
480 474
475
481static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) 476static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
482{ 477{
483 struct dib0070_state *state = fe->tuner_priv; 478 struct dib0070_state *state = fe->tuner_priv;
484 uint32_t ret; 479 uint32_t ret;
485 480
486 state->tune_state = CT_TUNER_START; 481 state->tune_state = CT_TUNER_START;
487 482
488 do { 483 do {
489 ret = dib0070_tune_digital(fe, p); 484 ret = dib0070_tune_digital(fe, p);
490 if (ret != FE_CALLBACK_TIME_NEVER) 485 if (ret != FE_CALLBACK_TIME_NEVER)
491 msleep(ret / 10); 486 msleep(ret/10);
492 else 487 else
493 break; 488 break;
494 } while (state->tune_state != CT_TUNER_STOP); 489 } while (state->tune_state != CT_TUNER_STOP);
495 490
496 return 0; 491 return 0;
497} 492}
498 493
499static int dib0070_wakeup(struct dvb_frontend *fe) 494static int dib0070_wakeup(struct dvb_frontend *fe)
@@ -512,92 +507,111 @@ static int dib0070_sleep(struct dvb_frontend *fe)
512 return 0; 507 return 0;
513} 508}
514 509
515static const u16 dib0070_p1f_defaults[] = { 510u8 dib0070_get_rf_output(struct dvb_frontend *fe)
511{
512 struct dib0070_state *state = fe->tuner_priv;
513 return (dib0070_read_reg(state, 0x07) >> 11) & 0x3;
514}
515
516EXPORT_SYMBOL(dib0070_get_rf_output);
517int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no)
518{
519 struct dib0070_state *state = fe->tuner_priv;
520 u16 rxrf2 = dib0070_read_reg(state, 0x07) & 0xfe7ff;
521 if (no > 3) no = 3;
522 if (no < 1) no = 1;
523 return dib0070_write_reg(state, 0x07, rxrf2 | (no << 11));
524}
525
526EXPORT_SYMBOL(dib0070_set_rf_output);
527static const u16 dib0070_p1f_defaults[] =
528
529{
516 7, 0x02, 530 7, 0x02,
517 0x0008, 531 0x0008,
518 0x0000, 532 0x0000,
519 0x0000, 533 0x0000,
520 0x0000, 534 0x0000,
521 0x0000, 535 0x0000,
522 0x0002, 536 0x0002,
523 0x0100, 537 0x0100,
524 538
525 3, 0x0d, 539 3, 0x0d,
526 0x0d80, 540 0x0d80,
527 0x0001, 541 0x0001,
528 0x0000, 542 0x0000,
529 543
530 4, 0x11, 544 4, 0x11,
531 0x0000, 545 0x0000,
532 0x0103, 546 0x0103,
533 0x0000, 547 0x0000,
534 0x0000, 548 0x0000,
535 549
536 3, 0x16, 550 3, 0x16,
537 0x0004 | 0x0040, 551 0x0004 | 0x0040,
538 0x0030, 552 0x0030,
539 0x07ff, 553 0x07ff,
540 554
541 6, 0x1b, 555 6, 0x1b,
542 0x4112, 556 0x4112,
543 0xff00, 557 0xff00,
544 0xc07f, 558 0xc07f,
545 0x0000, 559 0x0000,
546 0x0180, 560 0x0180,
547 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001, 561 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
548 562
549 0, 563 0,
550}; 564};
551 565
552static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain) 566static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
553{ 567{
554 u16 tuner_en = dib0070_read_reg(state, 0x20); 568 u16 tuner_en = dib0070_read_reg(state, 0x20);
555 u16 offset; 569 u16 offset;
556 570
557 dib0070_write_reg(state, 0x18, 0x07ff); 571 dib0070_write_reg(state, 0x18, 0x07ff);
558 dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001); 572 dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
559 dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0)); 573 dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0));
560 msleep(9); 574 msleep(9);
561 offset = dib0070_read_reg(state, 0x19); 575 offset = dib0070_read_reg(state, 0x19);
562 dib0070_write_reg(state, 0x20, tuner_en); 576 dib0070_write_reg(state, 0x20, tuner_en);
563 return offset; 577 return offset;
564} 578}
565 579
566static void dib0070_wbd_offset_calibration(struct dib0070_state *state) 580static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
567{ 581{
568 u8 gain; 582 u8 gain;
569 for (gain = 6; gain < 8; gain++) { 583 for (gain = 6; gain < 8; gain++) {
570 state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2); 584 state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
571 dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain - 6]); 585 dprintk( "Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain-6]);
572 } 586 }
573} 587}
574 588
575u16 dib0070_wbd_offset(struct dvb_frontend *fe) 589u16 dib0070_wbd_offset(struct dvb_frontend *fe)
576{ 590{
577 struct dib0070_state *state = fe->tuner_priv; 591 struct dib0070_state *state = fe->tuner_priv;
578 const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain; 592 const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
579 u32 freq = fe->dtv_property_cache.frequency / 1000; 593 u32 freq = fe->dtv_property_cache.frequency/1000;
580 594
581 if (tmp != NULL) { 595 if (tmp != NULL) {
582 while (freq / 1000 > tmp->freq) /* find the right one */ 596 while (freq/1000 > tmp->freq) /* find the right one */
583 tmp++; 597 tmp++;
584 state->wbd_gain_current = tmp->wbd_gain_val; 598 state->wbd_gain_current = tmp->wbd_gain_val;
585 } else 599 } else
586 state->wbd_gain_current = 6; 600 state->wbd_gain_current = 6;
587 601
588 return state->wbd_offset_3_3[state->wbd_gain_current - 6]; 602 return state->wbd_offset_3_3[state->wbd_gain_current - 6];
589} 603}
590
591EXPORT_SYMBOL(dib0070_wbd_offset); 604EXPORT_SYMBOL(dib0070_wbd_offset);
592 605
593#define pgm_read_word(w) (*w) 606#define pgm_read_word(w) (*w)
594static int dib0070_reset(struct dvb_frontend *fe) 607static int dib0070_reset(struct dvb_frontend *fe)
595{ 608{
596 struct dib0070_state *state = fe->tuner_priv; 609 struct dib0070_state *state = fe->tuner_priv;
597 u16 l, r, *n; 610 u16 l, r, *n;
598 611
599 HARD_RESET(state); 612 HARD_RESET(state);
600 613
614
601#ifndef FORCE_SBAND_TUNER 615#ifndef FORCE_SBAND_TUNER
602 if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1) 616 if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
603 state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff; 617 state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
@@ -605,13 +619,13 @@ static int dib0070_reset(struct dvb_frontend *fe)
605#else 619#else
606#warning forcing SBAND 620#warning forcing SBAND
607#endif 621#endif
608 state->revision = DIB0070S_P1A; 622 state->revision = DIB0070S_P1A;
609 623
610 /* P1F or not */ 624 /* P1F or not */
611 dprintk("Revision: %x", state->revision); 625 dprintk( "Revision: %x", state->revision);
612 626
613 if (state->revision == DIB0070_P1D) { 627 if (state->revision == DIB0070_P1D) {
614 dprintk("Error: this driver is not to be used meant for P1D or earlier"); 628 dprintk( "Error: this driver is not to be used meant for P1D or earlier");
615 return -EINVAL; 629 return -EINVAL;
616 } 630 }
617 631
@@ -620,7 +634,7 @@ static int dib0070_reset(struct dvb_frontend *fe)
620 while (l) { 634 while (l) {
621 r = pgm_read_word(n++); 635 r = pgm_read_word(n++);
622 do { 636 do {
623 dib0070_write_reg(state, (u8) r, pgm_read_word(n++)); 637 dib0070_write_reg(state, (u8)r, pgm_read_word(n++));
624 r++; 638 r++;
625 } while (--l); 639 } while (--l);
626 l = pgm_read_word(n++); 640 l = pgm_read_word(n++);
@@ -633,6 +647,7 @@ static int dib0070_reset(struct dvb_frontend *fe)
633 else 647 else
634 r = 2; 648 r = 2;
635 649
650
636 r |= state->cfg->osc_buffer_state << 3; 651 r |= state->cfg->osc_buffer_state << 3;
637 652
638 dib0070_write_reg(state, 0x10, r); 653 dib0070_write_reg(state, 0x10, r);
@@ -643,16 +658,24 @@ static int dib0070_reset(struct dvb_frontend *fe)
643 dib0070_write_reg(state, 0x02, r | (1 << 5)); 658 dib0070_write_reg(state, 0x02, r | (1 << 5));
644 } 659 }
645 660
646 if (state->revision == DIB0070S_P1A) 661 if (state->revision == DIB0070S_P1A)
647 dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); 662 dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
648 else 663 else
649 dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter); 664 dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter);
650 665
651 dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8); 666 dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
652 667
653 dib0070_wbd_offset_calibration(state); 668 dib0070_wbd_offset_calibration(state);
654 669
655 return 0; 670 return 0;
671}
672
673static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
674{
675 struct dib0070_state *state = fe->tuner_priv;
676
677 *frequency = 1000 * state->current_rf;
678 return 0;
656} 679}
657 680
658static int dib0070_release(struct dvb_frontend *fe) 681static int dib0070_release(struct dvb_frontend *fe)
@@ -664,22 +687,22 @@ static int dib0070_release(struct dvb_frontend *fe)
664 687
665static const struct dvb_tuner_ops dib0070_ops = { 688static const struct dvb_tuner_ops dib0070_ops = {
666 .info = { 689 .info = {
667 .name = "DiBcom DiB0070", 690 .name = "DiBcom DiB0070",
668 .frequency_min = 45000000, 691 .frequency_min = 45000000,
669 .frequency_max = 860000000, 692 .frequency_max = 860000000,
670 .frequency_step = 1000, 693 .frequency_step = 1000,
671 }, 694 },
672 .release = dib0070_release, 695 .release = dib0070_release,
673 696
674 .init = dib0070_wakeup, 697 .init = dib0070_wakeup,
675 .sleep = dib0070_sleep, 698 .sleep = dib0070_sleep,
676 .set_params = dib0070_tune, 699 .set_params = dib0070_tune,
677 700
678// .get_frequency = dib0070_get_frequency, 701 .get_frequency = dib0070_get_frequency,
679// .get_bandwidth = dib0070_get_bandwidth 702// .get_bandwidth = dib0070_get_bandwidth
680}; 703};
681 704
682struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg) 705struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
683{ 706{
684 struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL); 707 struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
685 if (state == NULL) 708 if (state == NULL)
@@ -687,7 +710,7 @@ struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter
687 710
688 state->cfg = cfg; 711 state->cfg = cfg;
689 state->i2c = i2c; 712 state->i2c = i2c;
690 state->fe = fe; 713 state->fe = fe;
691 fe->tuner_priv = state; 714 fe->tuner_priv = state;
692 715
693 if (dib0070_reset(fe) != 0) 716 if (dib0070_reset(fe) != 0)
@@ -699,12 +722,11 @@ struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter
699 fe->tuner_priv = state; 722 fe->tuner_priv = state;
700 return fe; 723 return fe;
701 724
702 free_mem: 725free_mem:
703 kfree(state); 726 kfree(state);
704 fe->tuner_priv = NULL; 727 fe->tuner_priv = NULL;
705 return NULL; 728 return NULL;
706} 729}
707
708EXPORT_SYMBOL(dib0070_attach); 730EXPORT_SYMBOL(dib0070_attach);
709 731
710MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); 732MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
diff --git a/drivers/media/dvb/frontends/dib0070.h b/drivers/media/dvb/frontends/dib0070.h
index eec9e52ffa75..45c31fae3967 100644
--- a/drivers/media/dvb/frontends/dib0070.h
+++ b/drivers/media/dvb/frontends/dib0070.h
@@ -52,6 +52,8 @@ struct dib0070_config {
52extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg); 52extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg);
53extern u16 dib0070_wbd_offset(struct dvb_frontend *); 53extern u16 dib0070_wbd_offset(struct dvb_frontend *);
54extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, u8 open); 54extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, u8 open);
55extern u8 dib0070_get_rf_output(struct dvb_frontend *fe);
56extern int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no);
55#else 57#else
56static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg) 58static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
57{ 59{
@@ -62,7 +64,7 @@ static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struc
62static inline u16 dib0070_wbd_offset(struct dvb_frontend *fe) 64static inline u16 dib0070_wbd_offset(struct dvb_frontend *fe)
63{ 65{
64 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); 66 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
65 return -ENODEV; 67 return 0;
66} 68}
67 69
68static inline void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open) 70static inline void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c
new file mode 100644
index 000000000000..e37d32dbd5c5
--- /dev/null
+++ b/drivers/media/dvb/frontends/dib0090.c
@@ -0,0 +1,1525 @@
1/*
2 * Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner.
3 *
4 * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/)
5 *
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; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 *
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 *
22 * This code is more or less generated from another driver, please
23 * excuse some codingstyle oddities.
24 *
25 */
26
27#include <linux/kernel.h>
28#include <linux/i2c.h>
29
30#include "dvb_frontend.h"
31
32#include "dib0090.h"
33#include "dibx000_common.h"
34
35static int debug;
36module_param(debug, int, 0644);
37MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
38
39#define dprintk(args...) do { \
40 if (debug) { \
41 printk(KERN_DEBUG "DiB0090: "); \
42 printk(args); \
43 printk("\n"); \
44 } \
45} while (0)
46
47#define CONFIG_SYS_ISDBT
48#define CONFIG_BAND_CBAND
49#define CONFIG_BAND_VHF
50#define CONFIG_BAND_UHF
51#define CONFIG_DIB0090_USE_PWM_AGC
52
53#define EN_LNA0 0x8000
54#define EN_LNA1 0x4000
55#define EN_LNA2 0x2000
56#define EN_LNA3 0x1000
57#define EN_MIX0 0x0800
58#define EN_MIX1 0x0400
59#define EN_MIX2 0x0200
60#define EN_MIX3 0x0100
61#define EN_IQADC 0x0040
62#define EN_PLL 0x0020
63#define EN_TX 0x0010
64#define EN_BB 0x0008
65#define EN_LO 0x0004
66#define EN_BIAS 0x0001
67
68#define EN_IQANA 0x0002
69#define EN_DIGCLK 0x0080 /* not in the 0x24 reg, only in 0x1b */
70#define EN_CRYSTAL 0x0002
71
72#define EN_UHF 0x22E9
73#define EN_VHF 0x44E9
74#define EN_LBD 0x11E9
75#define EN_SBD 0x44E9
76#define EN_CAB 0x88E9
77
78#define pgm_read_word(w) (*w)
79
80struct dc_calibration;
81
82struct dib0090_tuning {
83 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
84 u8 switch_trim;
85 u8 lna_tune;
86 u8 lna_bias;
87 u16 v2i;
88 u16 mix;
89 u16 load;
90 u16 tuner_enable;
91};
92
93struct dib0090_pll {
94 u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */
95 u8 vco_band;
96 u8 hfdiv_code;
97 u8 hfdiv;
98 u8 topresc;
99};
100
101struct dib0090_state {
102 struct i2c_adapter *i2c;
103 struct dvb_frontend *fe;
104 const struct dib0090_config *config;
105
106 u8 current_band;
107 u16 revision;
108 enum frontend_tune_state tune_state;
109 u32 current_rf;
110
111 u16 wbd_offset;
112 s16 wbd_target; /* in dB */
113
114 s16 rf_gain_limit; /* take-over-point: where to split between bb and rf gain */
115 s16 current_gain; /* keeps the currently programmed gain */
116 u8 agc_step; /* new binary search */
117
118 u16 gain[2]; /* for channel monitoring */
119
120 const u16 *rf_ramp;
121 const u16 *bb_ramp;
122
123 /* for the software AGC ramps */
124 u16 bb_1_def;
125 u16 rf_lt_def;
126 u16 gain_reg[4];
127
128 /* for the captrim/dc-offset search */
129 s8 step;
130 s16 adc_diff;
131 s16 min_adc_diff;
132
133 s8 captrim;
134 s8 fcaptrim;
135
136 const struct dc_calibration *dc;
137 u16 bb6, bb7;
138
139 const struct dib0090_tuning *current_tune_table_index;
140 const struct dib0090_pll *current_pll_table_index;
141
142 u8 tuner_is_tuned;
143 u8 agc_freeze;
144
145 u8 reset;
146};
147
148static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
149{
150 u8 b[2];
151 struct i2c_msg msg[2] = {
152 {.addr = state->config->i2c_address,.flags = 0,.buf = &reg,.len = 1},
153 {.addr = state->config->i2c_address,.flags = I2C_M_RD,.buf = b,.len = 2},
154 };
155 if (i2c_transfer(state->i2c, msg, 2) != 2) {
156 printk(KERN_WARNING "DiB0090 I2C read failed\n");
157 return 0;
158 }
159 return (b[0] << 8) | b[1];
160}
161
162static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val)
163{
164 u8 b[3] = { reg & 0xff, val >> 8, val & 0xff };
165 struct i2c_msg msg = {.addr = state->config->i2c_address,.flags = 0,.buf = b,.len = 3 };
166 if (i2c_transfer(state->i2c, &msg, 1) != 1) {
167 printk(KERN_WARNING "DiB0090 I2C write failed\n");
168 return -EREMOTEIO;
169 }
170 return 0;
171}
172
173#define HARD_RESET(state) do { if (cfg->reset) { if (cfg->sleep) cfg->sleep(fe, 0); msleep(10); cfg->reset(fe, 1); msleep(10); cfg->reset(fe, 0); msleep(10); } } while (0)
174#define ADC_TARGET -220
175#define GAIN_ALPHA 5
176#define WBD_ALPHA 6
177#define LPF 100
178static void dib0090_write_regs(struct dib0090_state *state, u8 r, const u16 * b, u8 c)
179{
180 do {
181 dib0090_write_reg(state, r++, *b++);
182 } while (--c);
183}
184
185static u16 dib0090_identify(struct dvb_frontend *fe)
186{
187 struct dib0090_state *state = fe->tuner_priv;
188 u16 v;
189
190 v = dib0090_read_reg(state, 0x1a);
191
192#ifdef FIRMWARE_FIREFLY
193 /* pll is not locked locked */
194 if (!(v & 0x800))
195 dprintk("FE%d : Identification : pll is not yet locked", fe->id);
196#endif
197
198 /* without PLL lock info */
199 v &= 0x3ff;
200 dprintk("P/V: %04x:", v);
201
202 if ((v >> 8) & 0xf)
203 dprintk("FE%d : Product ID = 0x%x : KROSUS", fe->id, (v >> 8) & 0xf);
204 else
205 return 0xff;
206
207 v &= 0xff;
208 if (((v >> 5) & 0x7) == 0x1)
209 dprintk("FE%d : MP001 : 9090/8096", fe->id);
210 else if (((v >> 5) & 0x7) == 0x4)
211 dprintk("FE%d : MP005 : Single Sband", fe->id);
212 else if (((v >> 5) & 0x7) == 0x6)
213 dprintk("FE%d : MP008 : diversity VHF-UHF-LBAND", fe->id);
214 else if (((v >> 5) & 0x7) == 0x7)
215 dprintk("FE%d : MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND", fe->id);
216 else
217 return 0xff;
218
219 /* revision only */
220 if ((v & 0x1f) == 0x3)
221 dprintk("FE%d : P1-D/E/F detected", fe->id);
222 else if ((v & 0x1f) == 0x1)
223 dprintk("FE%d : P1C detected", fe->id);
224 else if ((v & 0x1f) == 0x0) {
225#ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
226 dprintk("FE%d : P1-A/B detected: using previous driver - support will be removed soon", fe->id);
227 dib0090_p1b_register(fe);
228#else
229 dprintk("FE%d : P1-A/B detected: driver is deactivated - not available", fe->id);
230 return 0xff;
231#endif
232 }
233
234 return v;
235}
236
237static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
238{
239 struct dib0090_state *state = fe->tuner_priv;
240
241 HARD_RESET(state);
242
243 dib0090_write_reg(state, 0x24, EN_PLL);
244 dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */
245
246 /* adcClkOutRatio=8->7, release reset */
247 dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0);
248 if (cfg->clkoutdrive != 0)
249 dib0090_write_reg(state, 0x23,
250 (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 10) | (1 << 9) | (0 << 8) | (cfg->clkoutdrive << 5) | (cfg->
251 clkouttobamse
252 << 4) | (0
253 <<
254 2)
255 | (0));
256 else
257 dib0090_write_reg(state, 0x23,
258 (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 10) | (1 << 9) | (0 << 8) | (7 << 5) | (cfg->
259 clkouttobamse << 4) | (0
260 <<
261 2)
262 | (0));
263
264 /* enable pll, de-activate reset, ratio: 2/1 = 60MHz */
265 dib0090_write_reg(state, 0x21,
266 (cfg->io.pll_bypass << 15) | (1 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv));
267
268}
269
270static int dib0090_wakeup(struct dvb_frontend *fe)
271{
272 struct dib0090_state *state = fe->tuner_priv;
273 if (state->config->sleep)
274 state->config->sleep(fe, 0);
275 return 0;
276}
277
278static int dib0090_sleep(struct dvb_frontend *fe)
279{
280 struct dib0090_state *state = fe->tuner_priv;
281 if (state->config->sleep)
282 state->config->sleep(fe, 1);
283 return 0;
284}
285
286extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
287{
288 struct dib0090_state *state = fe->tuner_priv;
289 if (fast)
290 dib0090_write_reg(state, 0x04, 0); //1kHz
291 else
292 dib0090_write_reg(state, 0x04, 1); //almost frozen
293}
294
295EXPORT_SYMBOL(dib0090_dcc_freq);
296static const u16 rf_ramp_pwm_cband[] = {
297 0, /* max RF gain in 10th of dB */
298 0, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
299 0, /* ramp_max = maximum X used on the ramp */
300 (0 << 10) | 0, /* 0x2c, LNA 1 = 0dB */
301 (0 << 10) | 0, /* 0x2d, LNA 1 */
302 (0 << 10) | 0, /* 0x2e, LNA 2 = 0dB */
303 (0 << 10) | 0, /* 0x2f, LNA 2 */
304 (0 << 10) | 0, /* 0x30, LNA 3 = 0dB */
305 (0 << 10) | 0, /* 0x31, LNA 3 */
306 (0 << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */
307 (0 << 10) | 0, /* GAIN_4_2, LNA 4 */
308};
309
310static const u16 rf_ramp_vhf[] = {
311 412, /* max RF gain in 10th of dB */
312 132, 307, 127, /* LNA1, 13.2dB */
313 105, 412, 255, /* LNA2, 10.5dB */
314 50, 50, 127, /* LNA3, 5dB */
315 125, 175, 127, /* LNA4, 12.5dB */
316 0, 0, 127, /* CBAND, 0dB */
317};
318
319static const u16 rf_ramp_uhf[] = {
320 412, /* max RF gain in 10th of dB */
321 132, 307, 127, /* LNA1 : total gain = 13.2dB, point on the ramp where this amp is full gain, value to write to get full gain */
322 105, 412, 255, /* LNA2 : 10.5 dB */
323 50, 50, 127, /* LNA3 : 5.0 dB */
324 125, 175, 127, /* LNA4 : 12.5 dB */
325 0, 0, 127, /* CBAND : 0.0 dB */
326};
327
328static const u16 rf_ramp_cband[] = {
329 332, /* max RF gain in 10th of dB */
330 132, 252, 127, /* LNA1, dB */
331 80, 332, 255, /* LNA2, dB */
332 0, 0, 127, /* LNA3, dB */
333 0, 0, 127, /* LNA4, dB */
334 120, 120, 127, /* LT1 CBAND */
335};
336
337static const u16 rf_ramp_pwm_vhf[] = {
338 404, /* max RF gain in 10th of dB */
339 25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
340 1011, /* ramp_max = maximum X used on the ramp */
341 (6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */
342 (0 << 10) | 756, /* 0x2d, LNA 1 */
343 (16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */
344 (0 << 10) | 1011, /* 0x2f, LNA 2 */
345 (16 << 10) | 290, /* 0x30, LNA 3 = 5dB */
346 (0 << 10) | 417, /* 0x31, LNA 3 */
347 (7 << 10) | 0, /* GAIN_4_1, LNA 4 = 12.5dB */
348 (0 << 10) | 290, /* GAIN_4_2, LNA 4 */
349};
350
351static const u16 rf_ramp_pwm_uhf[] = {
352 404, /* max RF gain in 10th of dB */
353 25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
354 1011, /* ramp_max = maximum X used on the ramp */
355 (6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */
356 (0 << 10) | 756, /* 0x2d, LNA 1 */
357 (16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */
358 (0 << 10) | 1011, /* 0x2f, LNA 2 */
359 (16 << 10) | 0, /* 0x30, LNA 3 = 5dB */
360 (0 << 10) | 127, /* 0x31, LNA 3 */
361 (7 << 10) | 127, /* GAIN_4_1, LNA 4 = 12.5dB */
362 (0 << 10) | 417, /* GAIN_4_2, LNA 4 */
363};
364
365static const u16 bb_ramp_boost[] = {
366 550, /* max BB gain in 10th of dB */
367 260, 260, 26, /* BB1, 26dB */
368 290, 550, 29, /* BB2, 29dB */
369};
370
371static const u16 bb_ramp_pwm_normal[] = {
372 500, /* max RF gain in 10th of dB */
373 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x34 */
374 400,
375 (2 << 9) | 0, /* 0x35 = 21dB */
376 (0 << 9) | 168, /* 0x36 */
377 (2 << 9) | 168, /* 0x37 = 29dB */
378 (0 << 9) | 400, /* 0x38 */
379};
380
381struct slope {
382 int16_t range;
383 int16_t slope;
384};
385static u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val)
386{
387 u8 i;
388 u16 rest;
389 u16 ret = 0;
390 for (i = 0; i < num; i++) {
391 if (val > slopes[i].range)
392 rest = slopes[i].range;
393 else
394 rest = val;
395 ret += (rest * slopes[i].slope) / slopes[i].range;
396 val -= rest;
397 }
398 return ret;
399}
400
401static const struct slope dib0090_wbd_slopes[3] = {
402 {66, 120}, /* -64,-52: offset - 65 */
403 {600, 170}, /* -52,-35: 65 - 665 */
404 {170, 250}, /* -45,-10: 665 - 835 */
405};
406
407static s16 dib0090_wbd_to_db(struct dib0090_state *state, u16 wbd)
408{
409 wbd &= 0x3ff;
410 if (wbd < state->wbd_offset)
411 wbd = 0;
412 else
413 wbd -= state->wbd_offset;
414 /* -64dB is the floor */
415 return -640 + (s16) slopes_to_scale(dib0090_wbd_slopes, ARRAY_SIZE(dib0090_wbd_slopes), wbd);
416}
417
418static void dib0090_wbd_target(struct dib0090_state *state, u32 rf)
419{
420 u16 offset = 250;
421
422 /* TODO : DAB digital N+/-1 interferer perfs : offset = 10 */
423
424 if (state->current_band == BAND_VHF)
425 offset = 650;
426#ifndef FIRMWARE_FIREFLY
427 if (state->current_band == BAND_VHF)
428 offset = state->config->wbd_vhf_offset;
429 if (state->current_band == BAND_CBAND)
430 offset = state->config->wbd_cband_offset;
431#endif
432
433 state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset);
434 dprintk("wbd-target: %d dB", (u32) state->wbd_target);
435}
436
437static const int gain_reg_addr[4] = {
438 0x08, 0x0a, 0x0f, 0x01
439};
440
441static void dib0090_gain_apply(struct dib0090_state *state, s16 gain_delta, s16 top_delta, u8 force)
442{
443 u16 rf, bb, ref;
444 u16 i, v, gain_reg[4] = { 0 }, gain;
445 const u16 *g;
446
447 if (top_delta < -511)
448 top_delta = -511;
449 if (top_delta > 511)
450 top_delta = 511;
451
452 if (force) {
453 top_delta *= (1 << WBD_ALPHA);
454 gain_delta *= (1 << GAIN_ALPHA);
455 }
456
457 if (top_delta >= ((s16) (state->rf_ramp[0] << WBD_ALPHA) - state->rf_gain_limit)) /* overflow */
458 state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
459 else
460 state->rf_gain_limit += top_delta;
461
462 if (state->rf_gain_limit < 0) /*underflow */
463 state->rf_gain_limit = 0;
464
465 /* use gain as a temporary variable and correct current_gain */
466 gain = ((state->rf_gain_limit >> WBD_ALPHA) + state->bb_ramp[0]) << GAIN_ALPHA;
467 if (gain_delta >= ((s16) gain - state->current_gain)) /* overflow */
468 state->current_gain = gain;
469 else
470 state->current_gain += gain_delta;
471 /* cannot be less than 0 (only if gain_delta is less than 0 we can have current_gain < 0) */
472 if (state->current_gain < 0)
473 state->current_gain = 0;
474
475 /* now split total gain to rf and bb gain */
476 gain = state->current_gain >> GAIN_ALPHA;
477
478 /* requested gain is bigger than rf gain limit - ACI/WBD adjustment */
479 if (gain > (state->rf_gain_limit >> WBD_ALPHA)) {
480 rf = state->rf_gain_limit >> WBD_ALPHA;
481 bb = gain - rf;
482 if (bb > state->bb_ramp[0])
483 bb = state->bb_ramp[0];
484 } else { /* high signal level -> all gains put on RF */
485 rf = gain;
486 bb = 0;
487 }
488
489 state->gain[0] = rf;
490 state->gain[1] = bb;
491
492 /* software ramp */
493 /* Start with RF gains */
494 g = state->rf_ramp + 1; /* point on RF LNA1 max gain */
495 ref = rf;
496 for (i = 0; i < 7; i++) { /* Go over all amplifiers => 5RF amps + 2 BB amps = 7 amps */
497 if (g[0] == 0 || ref < (g[1] - g[0])) /* if total gain of the current amp is null or this amp is not concerned because it starts to work from an higher gain value */
498 v = 0; /* force the gain to write for the current amp to be null */
499 else if (ref >= g[1]) /* Gain to set is higher than the high working point of this amp */
500 v = g[2]; /* force this amp to be full gain */
501 else /* compute the value to set to this amp because we are somewhere in his range */
502 v = ((ref - (g[1] - g[0])) * g[2]) / g[0];
503
504 if (i == 0) /* LNA 1 reg mapping */
505 gain_reg[0] = v;
506 else if (i == 1) /* LNA 2 reg mapping */
507 gain_reg[0] |= v << 7;
508 else if (i == 2) /* LNA 3 reg mapping */
509 gain_reg[1] = v;
510 else if (i == 3) /* LNA 4 reg mapping */
511 gain_reg[1] |= v << 7;
512 else if (i == 4) /* CBAND LNA reg mapping */
513 gain_reg[2] = v | state->rf_lt_def;
514 else if (i == 5) /* BB gain 1 reg mapping */
515 gain_reg[3] = v << 3;
516 else if (i == 6) /* BB gain 2 reg mapping */
517 gain_reg[3] |= v << 8;
518
519 g += 3; /* go to next gain bloc */
520
521 /* When RF is finished, start with BB */
522 if (i == 4) {
523 g = state->bb_ramp + 1; /* point on BB gain 1 max gain */
524 ref = bb;
525 }
526 }
527 gain_reg[3] |= state->bb_1_def;
528 gain_reg[3] |= ((bb % 10) * 100) / 125;
529
530#ifdef DEBUG_AGC
531 dprintk("GA CALC: DB: %3d(rf) + %3d(bb) = %3d gain_reg[0]=%04x gain_reg[1]=%04x gain_reg[2]=%04x gain_reg[0]=%04x", rf, bb, rf + bb,
532 gain_reg[0], gain_reg[1], gain_reg[2], gain_reg[3]);
533#endif
534
535 /* Write the amplifier regs */
536 for (i = 0; i < 4; i++) {
537 v = gain_reg[i];
538 if (force || state->gain_reg[i] != v) {
539 state->gain_reg[i] = v;
540 dib0090_write_reg(state, gain_reg_addr[i], v);
541 }
542 }
543}
544
545static void dib0090_set_boost(struct dib0090_state *state, int onoff)
546{
547 state->bb_1_def &= 0xdfff;
548 state->bb_1_def |= onoff << 13;
549}
550
551static void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg)
552{
553 state->rf_ramp = cfg;
554}
555
556static void dib0090_set_rframp_pwm(struct dib0090_state *state, const u16 * cfg)
557{
558 state->rf_ramp = cfg;
559
560 dib0090_write_reg(state, 0x2a, 0xffff);
561
562 dprintk("total RF gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x2a));
563
564 dib0090_write_regs(state, 0x2c, cfg + 3, 6);
565 dib0090_write_regs(state, 0x3e, cfg + 9, 2);
566}
567
568static void dib0090_set_bbramp(struct dib0090_state *state, const u16 * cfg)
569{
570 state->bb_ramp = cfg;
571 dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
572}
573
574static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg)
575{
576 state->bb_ramp = cfg;
577
578 dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */
579
580 dib0090_write_reg(state, 0x33, 0xffff);
581 dprintk("total BB gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x33));
582 dib0090_write_regs(state, 0x35, cfg + 3, 4);
583}
584
585void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
586{
587 struct dib0090_state *state = fe->tuner_priv;
588 /* reset the AGC */
589
590 if (state->config->use_pwm_agc) {
591#ifdef CONFIG_BAND_SBAND
592 if (state->current_band == BAND_SBAND) {
593 dib0090_set_rframp_pwm(state, rf_ramp_pwm_sband);
594 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_boost);
595 } else
596#endif
597#ifdef CONFIG_BAND_CBAND
598 if (state->current_band == BAND_CBAND) {
599 dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband);
600 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
601 } else
602#endif
603#ifdef CONFIG_BAND_VHF
604 if (state->current_band == BAND_VHF) {
605 dib0090_set_rframp_pwm(state, rf_ramp_pwm_vhf);
606 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
607 } else
608#endif
609 {
610 dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf);
611 dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
612 }
613
614 if (state->rf_ramp[0] != 0)
615 dib0090_write_reg(state, 0x32, (3 << 11));
616 else
617 dib0090_write_reg(state, 0x32, (0 << 11));
618
619 dib0090_write_reg(state, 0x39, (1 << 10)); // 0 gain by default
620 }
621}
622
623EXPORT_SYMBOL(dib0090_pwm_gain_reset);
624int dib0090_gain_control(struct dvb_frontend *fe)
625{
626 struct dib0090_state *state = fe->tuner_priv;
627 enum frontend_tune_state *tune_state = &state->tune_state;
628 int ret = 10;
629
630 u16 wbd_val = 0;
631 u8 apply_gain_immediatly = 1;
632 s16 wbd_error = 0, adc_error = 0;
633
634 if (*tune_state == CT_AGC_START) {
635 state->agc_freeze = 0;
636 dib0090_write_reg(state, 0x04, 0x0);
637
638#ifdef CONFIG_BAND_SBAND
639 if (state->current_band == BAND_SBAND) {
640 dib0090_set_rframp(state, rf_ramp_sband);
641 dib0090_set_bbramp(state, bb_ramp_boost);
642 } else
643#endif
644#ifdef CONFIG_BAND_VHF
645 if (state->current_band == BAND_VHF) {
646 dib0090_set_rframp(state, rf_ramp_vhf);
647 dib0090_set_bbramp(state, bb_ramp_boost);
648 } else
649#endif
650#ifdef CONFIG_BAND_CBAND
651 if (state->current_band == BAND_CBAND) {
652 dib0090_set_rframp(state, rf_ramp_cband);
653 dib0090_set_bbramp(state, bb_ramp_boost);
654 } else
655#endif
656 {
657 dib0090_set_rframp(state, rf_ramp_uhf);
658 dib0090_set_bbramp(state, bb_ramp_boost);
659 }
660
661 dib0090_write_reg(state, 0x32, 0);
662 dib0090_write_reg(state, 0x39, 0);
663
664 dib0090_wbd_target(state, state->current_rf);
665
666 state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA;
667 state->current_gain = ((state->rf_ramp[0] + state->bb_ramp[0]) / 2) << GAIN_ALPHA;
668
669 *tune_state = CT_AGC_STEP_0;
670 } else if (!state->agc_freeze) {
671 s16 wbd;
672
673 int adc;
674 wbd_val = dib0090_read_reg(state, 0x1d);
675
676 /* read and calc the wbd power */
677 wbd = dib0090_wbd_to_db(state, wbd_val);
678 wbd_error = state->wbd_target - wbd;
679
680 if (*tune_state == CT_AGC_STEP_0) {
681 if (wbd_error < 0 && state->rf_gain_limit > 0) {
682#ifdef CONFIG_BAND_CBAND
683 /* in case of CBAND tune reduce first the lt_gain2 before adjusting the RF gain */
684 u8 ltg2 = (state->rf_lt_def >> 10) & 0x7;
685 if (state->current_band == BAND_CBAND && ltg2) {
686 ltg2 >>= 1;
687 state->rf_lt_def &= ltg2 << 10; /* reduce in 3 steps from 7 to 0 */
688 }
689#endif
690 } else {
691 state->agc_step = 0;
692 *tune_state = CT_AGC_STEP_1;
693 }
694 } else {
695 /* calc the adc power */
696 adc = state->config->get_adc_power(fe);
697 adc = (adc * ((s32) 355774) + (((s32) 1) << 20)) >> 21; /* included in [0:-700] */
698
699 adc_error = (s16) (((s32) ADC_TARGET) - adc);
700#ifdef CONFIG_STANDARD_DAB
701 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB)
702 adc_error += 130;
703#endif
704#ifdef CONFIG_STANDARD_DVBT
705 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DVBT &&
706 (state->fe->dtv_property_cache.modulation == QAM_64 || state->fe->dtv_property_cache.modulation == QAM_16))
707 adc_error += 60;
708#endif
709#ifdef CONFIG_SYS_ISDBT
710 if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) && (((state->fe->dtv_property_cache.layer[0].segment_count >
711 0)
712 &&
713 ((state->fe->dtv_property_cache.layer[0].modulation ==
714 QAM_64)
715 || (state->fe->dtv_property_cache.layer[0].
716 modulation == QAM_16)))
717 ||
718 ((state->fe->dtv_property_cache.layer[1].segment_count >
719 0)
720 &&
721 ((state->fe->dtv_property_cache.layer[1].modulation ==
722 QAM_64)
723 || (state->fe->dtv_property_cache.layer[1].
724 modulation == QAM_16)))
725 ||
726 ((state->fe->dtv_property_cache.layer[2].segment_count >
727 0)
728 &&
729 ((state->fe->dtv_property_cache.layer[2].modulation ==
730 QAM_64)
731 || (state->fe->dtv_property_cache.layer[2].
732 modulation == QAM_16)))
733 )
734 )
735 adc_error += 60;
736#endif
737
738 if (*tune_state == CT_AGC_STEP_1) { /* quickly go to the correct range of the ADC power */
739 if (ABS(adc_error) < 50 || state->agc_step++ > 5) {
740
741#ifdef CONFIG_STANDARD_DAB
742 if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) {
743 dib0090_write_reg(state, 0x02, (1 << 15) | (15 << 11) | (31 << 6) | (63)); /* cap value = 63 : narrow BB filter : Fc = 1.8MHz */
744 dib0090_write_reg(state, 0x04, 0x0);
745 } else
746#endif
747 {
748 dib0090_write_reg(state, 0x02, (1 << 15) | (3 << 11) | (6 << 6) | (32));
749 dib0090_write_reg(state, 0x04, 0x01); /*0 = 1KHz ; 1 = 150Hz ; 2 = 50Hz ; 3 = 50KHz ; 4 = servo fast */
750 }
751
752 *tune_state = CT_AGC_STOP;
753 }
754 } else {
755 /* everything higher than or equal to CT_AGC_STOP means tracking */
756 ret = 100; /* 10ms interval */
757 apply_gain_immediatly = 0;
758 }
759 }
760#ifdef DEBUG_AGC
761 dprintk
762 ("FE: %d, tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm",
763 (u32) fe->id, (u32) * tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val,
764 (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA));
765#endif
766 }
767
768 /* apply gain */
769 if (!state->agc_freeze)
770 dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly);
771 return ret;
772}
773
774EXPORT_SYMBOL(dib0090_gain_control);
775void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
776{
777 struct dib0090_state *state = fe->tuner_priv;
778 if (rf)
779 *rf = state->gain[0];
780 if (bb)
781 *bb = state->gain[1];
782 if (rf_gain_limit)
783 *rf_gain_limit = state->rf_gain_limit;
784 if (rflt)
785 *rflt = (state->rf_lt_def >> 10) & 0x7;
786}
787
788EXPORT_SYMBOL(dib0090_get_current_gain);
789u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner)
790{
791 struct dib0090_state *st = tuner->tuner_priv;
792 return st->wbd_offset;
793}
794
795EXPORT_SYMBOL(dib0090_get_wbd_offset);
796static const u16 dib0090_defaults[] = {
797
798 25, 0x01,
799 0x0000,
800 0x99a0,
801 0x6008,
802 0x0000,
803 0x8acb,
804 0x0000,
805 0x0405,
806 0x0000,
807 0x0000,
808 0x0000,
809 0xb802,
810 0x0300,
811 0x2d12,
812 0xbac0,
813 0x7c00,
814 0xdbb9,
815 0x0954,
816 0x0743,
817 0x8000,
818 0x0001,
819 0x0040,
820 0x0100,
821 0x0000,
822 0xe910,
823 0x149e,
824
825 1, 0x1c,
826 0xff2d,
827
828 1, 0x39,
829 0x0000,
830
831 1, 0x1b,
832 EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL,
833 2, 0x1e,
834 0x07FF,
835 0x0007,
836
837 1, 0x24,
838 EN_UHF | EN_CRYSTAL,
839
840 2, 0x3c,
841 0x3ff,
842 0x111,
843 0
844};
845
846static int dib0090_reset(struct dvb_frontend *fe)
847{
848 struct dib0090_state *state = fe->tuner_priv;
849 u16 l, r, *n;
850
851 dib0090_reset_digital(fe, state->config);
852 state->revision = dib0090_identify(fe);
853
854 /* Revision definition */
855 if (state->revision == 0xff)
856 return -EINVAL;
857#ifdef EFUSE
858 else if ((state->revision & 0x1f) >= 3) /* Update the efuse : Only available for KROSUS > P1C */
859 dib0090_set_EFUSE(state);
860#endif
861
862#ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
863 if (!(state->revision & 0x1)) /* it is P1B - reset is already done */
864 return 0;
865#endif
866
867 /* Upload the default values */
868 n = (u16 *) dib0090_defaults;
869 l = pgm_read_word(n++);
870 while (l) {
871 r = pgm_read_word(n++);
872 do {
873 /* DEBUG_TUNER */
874 /* dprintk("%d, %d, %d", l, r, pgm_read_word(n)); */
875 dib0090_write_reg(state, r, pgm_read_word(n++));
876 r++;
877 } while (--l);
878 l = pgm_read_word(n++);
879 }
880
881 /* Congigure in function of the crystal */
882 if (state->config->io.clock_khz >= 24000)
883 l = 1;
884 else
885 l = 2;
886 dib0090_write_reg(state, 0x14, l);
887 dprintk("Pll lock : %d", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1);
888
889 state->reset = 3; /* enable iq-offset-calibration and wbd-calibration when tuning next time */
890
891 return 0;
892}
893
894#define steps(u) (((u)>15)?((u)-16):(u))
895#define INTERN_WAIT 10
896static int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state)
897{
898 int ret = INTERN_WAIT * 10;
899
900 switch (*tune_state) {
901 case CT_TUNER_STEP_2:
902 /* Turns to positive */
903 dib0090_write_reg(state, 0x1f, 0x7);
904 *tune_state = CT_TUNER_STEP_3;
905 break;
906
907 case CT_TUNER_STEP_3:
908 state->adc_diff = dib0090_read_reg(state, 0x1d);
909
910 /* Turns to negative */
911 dib0090_write_reg(state, 0x1f, 0x4);
912 *tune_state = CT_TUNER_STEP_4;
913 break;
914
915 case CT_TUNER_STEP_4:
916 state->adc_diff -= dib0090_read_reg(state, 0x1d);
917 *tune_state = CT_TUNER_STEP_5;
918 ret = 0;
919 break;
920
921 default:
922 break;
923 }
924
925 return ret;
926}
927
928struct dc_calibration {
929 uint8_t addr;
930 uint8_t offset;
931 uint8_t pga:1;
932 uint16_t bb1;
933 uint8_t i:1;
934};
935
936static const struct dc_calibration dc_table[] = {
937 /* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
938 {0x06, 5, 1, (1 << 13) | (0 << 8) | (26 << 3), 1},
939 {0x07, 11, 1, (1 << 13) | (0 << 8) | (26 << 3), 0},
940 /* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
941 {0x06, 0, 0, (1 << 13) | (29 << 8) | (26 << 3), 1},
942 {0x06, 10, 0, (1 << 13) | (29 << 8) | (26 << 3), 0},
943 {0},
944};
945
946static void dib0090_set_trim(struct dib0090_state *state)
947{
948 u16 *val;
949
950 if (state->dc->addr == 0x07)
951 val = &state->bb7;
952 else
953 val = &state->bb6;
954
955 *val &= ~(0x1f << state->dc->offset);
956 *val |= state->step << state->dc->offset;
957
958 dib0090_write_reg(state, state->dc->addr, *val);
959}
960
961static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
962{
963 int ret = 0;
964
965 switch (*tune_state) {
966
967 case CT_TUNER_START:
968 /* init */
969 dprintk("Internal DC calibration");
970
971 /* the LNA is off */
972 dib0090_write_reg(state, 0x24, 0x02ed);
973
974 /* force vcm2 = 0.8V */
975 state->bb6 = 0;
976 state->bb7 = 0x040d;
977
978 state->dc = dc_table;
979
980 *tune_state = CT_TUNER_STEP_0;
981
982 /* fall through */
983
984 case CT_TUNER_STEP_0:
985 dib0090_write_reg(state, 0x01, state->dc->bb1);
986 dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7));
987
988 state->step = 0;
989
990 state->min_adc_diff = 1023;
991
992 *tune_state = CT_TUNER_STEP_1;
993 ret = 50;
994 break;
995
996 case CT_TUNER_STEP_1:
997 dib0090_set_trim(state);
998
999 *tune_state = CT_TUNER_STEP_2;
1000 break;
1001
1002 case CT_TUNER_STEP_2:
1003 case CT_TUNER_STEP_3:
1004 case CT_TUNER_STEP_4:
1005 ret = dib0090_get_offset(state, tune_state);
1006 break;
1007
1008 case CT_TUNER_STEP_5: /* found an offset */
1009 dprintk("FE%d: IQC read=%d, current=%x", state->fe->id, (u32) state->adc_diff, state->step);
1010
1011 /* first turn for this frequency */
1012 if (state->step == 0) {
1013 if (state->dc->pga && state->adc_diff < 0)
1014 state->step = 0x10;
1015 if (state->dc->pga == 0 && state->adc_diff > 0)
1016 state->step = 0x10;
1017 }
1018
1019 state->adc_diff = ABS(state->adc_diff);
1020
1021 if (state->adc_diff < state->min_adc_diff && steps(state->step) < 15) { /* stop search when the delta to 0 is increasing */
1022 state->step++;
1023 state->min_adc_diff = state->adc_diff;
1024 *tune_state = CT_TUNER_STEP_1;
1025 } else {
1026
1027 /* the minimum was what we have seen in the step before */
1028 state->step--;
1029 dib0090_set_trim(state);
1030
1031 dprintk("FE%d: BB Offset Cal, BBreg=%hd,Offset=%hd,Value Set=%hd", state->fe->id, state->dc->addr, state->adc_diff,
1032 state->step);
1033
1034 state->dc++;
1035 if (state->dc->addr == 0) /* done */
1036 *tune_state = CT_TUNER_STEP_6;
1037 else
1038 *tune_state = CT_TUNER_STEP_0;
1039
1040 }
1041 break;
1042
1043 case CT_TUNER_STEP_6:
1044 dib0090_write_reg(state, 0x07, state->bb7 & ~0x0008);
1045 dib0090_write_reg(state, 0x1f, 0x7);
1046 *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */
1047 state->reset &= ~0x1;
1048 default:
1049 break;
1050 }
1051 return ret;
1052}
1053
1054static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
1055{
1056 switch (*tune_state) {
1057 case CT_TUNER_START:
1058 /* WBD-mode=log, Bias=2, Gain=6, Testmode=1, en=1, WBDMUX=1 */
1059 dib0090_write_reg(state, 0x10, 0xdb09 | (1 << 10));
1060 dib0090_write_reg(state, 0x24, EN_UHF & 0x0fff);
1061
1062 *tune_state = CT_TUNER_STEP_0;
1063 return 90; /* wait for the WBDMUX to switch and for the ADC to sample */
1064 case CT_TUNER_STEP_0:
1065 state->wbd_offset = dib0090_read_reg(state, 0x1d);
1066 dprintk("WBD calibration offset = %d", state->wbd_offset);
1067
1068 *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */
1069 state->reset &= ~0x2;
1070 break;
1071 default:
1072 break;
1073 }
1074 return 0;
1075}
1076
1077static void dib0090_set_bandwidth(struct dib0090_state *state)
1078{
1079 u16 tmp;
1080
1081 if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 5000)
1082 tmp = (3 << 14);
1083 else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 6000)
1084 tmp = (2 << 14);
1085 else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 7000)
1086 tmp = (1 << 14);
1087 else
1088 tmp = (0 << 14);
1089
1090 state->bb_1_def &= 0x3fff;
1091 state->bb_1_def |= tmp;
1092
1093 dib0090_write_reg(state, 0x01, state->bb_1_def); /* be sure that we have the right bb-filter */
1094}
1095
1096static const struct dib0090_pll dib0090_pll_table[] = {
1097#ifdef CONFIG_BAND_CBAND
1098 {56000, 0, 9, 48, 6},
1099 {70000, 1, 9, 48, 6},
1100 {87000, 0, 8, 32, 4},
1101 {105000, 1, 8, 32, 4},
1102 {115000, 0, 7, 24, 6},
1103 {140000, 1, 7, 24, 6},
1104 {170000, 0, 6, 16, 4},
1105#endif
1106#ifdef CONFIG_BAND_VHF
1107 {200000, 1, 6, 16, 4},
1108 {230000, 0, 5, 12, 6},
1109 {280000, 1, 5, 12, 6},
1110 {340000, 0, 4, 8, 4},
1111 {380000, 1, 4, 8, 4},
1112 {450000, 0, 3, 6, 6},
1113#endif
1114#ifdef CONFIG_BAND_UHF
1115 {580000, 1, 3, 6, 6},
1116 {700000, 0, 2, 4, 4},
1117 {860000, 1, 2, 4, 4},
1118#endif
1119#ifdef CONFIG_BAND_LBAND
1120 {1800000, 1, 0, 2, 4},
1121#endif
1122#ifdef CONFIG_BAND_SBAND
1123 {2900000, 0, 14, 1, 4},
1124#endif
1125};
1126
1127static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = {
1128
1129#ifdef CONFIG_BAND_CBAND
1130 {184000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1131 {227000, 4, 3, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1132 {380000, 4, 7, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1133#endif
1134#ifdef CONFIG_BAND_UHF
1135 {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1136 {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1137 {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1138 {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1139 {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1140 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1141#endif
1142#ifdef CONFIG_BAND_LBAND
1143 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1144 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1145 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1146#endif
1147#ifdef CONFIG_BAND_SBAND
1148 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1149 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1150#endif
1151};
1152
1153static const struct dib0090_tuning dib0090_tuning_table[] = {
1154
1155#ifdef CONFIG_BAND_CBAND
1156 {170000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB},
1157#endif
1158#ifdef CONFIG_BAND_VHF
1159 {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1160 {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1161 {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
1162#endif
1163#ifdef CONFIG_BAND_UHF
1164 {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1165 {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1166 {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1167 {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1168 {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1169 {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
1170#endif
1171#ifdef CONFIG_BAND_LBAND
1172 {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1173 {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1174 {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
1175#endif
1176#ifdef CONFIG_BAND_SBAND
1177 {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
1178 {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
1179#endif
1180};
1181
1182#define WBD 0x781 /* 1 1 1 1 0000 0 0 1 */
1183static int dib0090_tune(struct dvb_frontend *fe)
1184{
1185 struct dib0090_state *state = fe->tuner_priv;
1186 const struct dib0090_tuning *tune = state->current_tune_table_index;
1187 const struct dib0090_pll *pll = state->current_pll_table_index;
1188 enum frontend_tune_state *tune_state = &state->tune_state;
1189
1190 u32 rf;
1191 u16 lo4 = 0xe900, lo5, lo6, Den;
1192 u32 FBDiv, Rest, FREF, VCOF_kHz = 0;
1193 u16 tmp, adc;
1194 int8_t step_sign;
1195 int ret = 10; /* 1ms is the default delay most of the time */
1196 u8 c, i;
1197
1198 state->current_band = (u8) BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000);
1199 rf = fe->dtv_property_cache.frequency / 1000 + (state->current_band ==
1200 BAND_UHF ? state->config->freq_offset_khz_uhf : state->config->freq_offset_khz_vhf);
1201 /* in any case we first need to do a reset if needed */
1202 if (state->reset & 0x1)
1203 return dib0090_dc_offset_calibration(state, tune_state);
1204 else if (state->reset & 0x2)
1205 return dib0090_wbd_calibration(state, tune_state);
1206
1207 /************************* VCO ***************************/
1208 /* Default values for FG */
1209 /* from these are needed : */
1210 /* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv */
1211
1212#ifdef CONFIG_SYS_ISDBT
1213 if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
1214 rf += 850;
1215#endif
1216
1217 if (state->current_rf != rf) {
1218 state->tuner_is_tuned = 0;
1219
1220 tune = dib0090_tuning_table;
1221
1222 tmp = (state->revision >> 5) & 0x7;
1223 if (tmp == 0x4 || tmp == 0x7) {
1224 /* CBAND tuner version for VHF */
1225 if (state->current_band == BAND_FM || state->current_band == BAND_VHF) {
1226 /* Force CBAND */
1227 state->current_band = BAND_CBAND;
1228 tune = dib0090_tuning_table_fm_vhf_on_cband;
1229 }
1230 }
1231
1232 pll = dib0090_pll_table;
1233 /* Look for the interval */
1234 while (rf > tune->max_freq)
1235 tune++;
1236 while (rf > pll->max_freq)
1237 pll++;
1238 state->current_tune_table_index = tune;
1239 state->current_pll_table_index = pll;
1240 }
1241
1242 if (*tune_state == CT_TUNER_START) {
1243
1244 if (state->tuner_is_tuned == 0)
1245 state->current_rf = 0;
1246
1247 if (state->current_rf != rf) {
1248
1249 dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim));
1250
1251 /* external loop filter, otherwise:
1252 * lo5 = (0 << 15) | (0 << 12) | (0 << 11) | (3 << 9) | (4 << 6) | (3 << 4) | 4;
1253 * lo6 = 0x0e34 */
1254 if (pll->vco_band)
1255 lo5 = 0x049e;
1256 else if (state->config->analog_output)
1257 lo5 = 0x041d;
1258 else
1259 lo5 = 0x041c;
1260
1261 lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7); /* bit 15 is the split to the slave, we do not do it here */
1262
1263 if (!state->config->io.pll_int_loop_filt)
1264 lo6 = 0xff28;
1265 else
1266 lo6 = (state->config->io.pll_int_loop_filt << 3);
1267
1268 VCOF_kHz = (pll->hfdiv * rf) * 2;
1269
1270 FREF = state->config->io.clock_khz;
1271
1272 FBDiv = (VCOF_kHz / pll->topresc / FREF);
1273 Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF;
1274
1275 if (Rest < LPF)
1276 Rest = 0;
1277 else if (Rest < 2 * LPF)
1278 Rest = 2 * LPF;
1279 else if (Rest > (FREF - LPF)) {
1280 Rest = 0;
1281 FBDiv += 1;
1282 } else if (Rest > (FREF - 2 * LPF))
1283 Rest = FREF - 2 * LPF;
1284 Rest = (Rest * 6528) / (FREF / 10);
1285
1286 Den = 1;
1287
1288 dprintk(" ***** ******* Rest value = %d", Rest);
1289
1290 if (Rest > 0) {
1291 if (state->config->analog_output)
1292 lo6 |= (1 << 2) | 2;
1293 else
1294 lo6 |= (1 << 2) | 1;
1295 Den = 255;
1296 }
1297#ifdef CONFIG_BAND_SBAND
1298 if (state->current_band == BAND_SBAND)
1299 lo6 &= 0xfffb;
1300#endif
1301
1302 dib0090_write_reg(state, 0x15, (u16) FBDiv);
1303
1304 dib0090_write_reg(state, 0x16, (Den << 8) | 1);
1305
1306 dib0090_write_reg(state, 0x17, (u16) Rest);
1307
1308 dib0090_write_reg(state, 0x19, lo5);
1309
1310 dib0090_write_reg(state, 0x1c, lo6);
1311
1312 lo6 = tune->tuner_enable;
1313 if (state->config->analog_output)
1314 lo6 = (lo6 & 0xff9f) | 0x2;
1315
1316 dib0090_write_reg(state, 0x24, lo6 | EN_LO
1317#ifdef CONFIG_DIB0090_USE_PWM_AGC
1318 | state->config->use_pwm_agc * EN_CRYSTAL
1319#endif
1320 );
1321
1322 state->current_rf = rf;
1323
1324 /* prepare a complete captrim */
1325 state->step = state->captrim = state->fcaptrim = 64;
1326
1327 } else { /* we are already tuned to this frequency - the configuration is correct */
1328
1329 /* do a minimal captrim even if the frequency has not changed */
1330 state->step = 4;
1331 state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f;
1332 }
1333 state->adc_diff = 3000;
1334
1335 dib0090_write_reg(state, 0x10, 0x2B1);
1336
1337 dib0090_write_reg(state, 0x1e, 0x0032);
1338
1339 ret = 20;
1340 *tune_state = CT_TUNER_STEP_1;
1341 } else if (*tune_state == CT_TUNER_STEP_0) {
1342 /* nothing */
1343 } else if (*tune_state == CT_TUNER_STEP_1) {
1344 state->step /= 2;
1345 dib0090_write_reg(state, 0x18, lo4 | state->captrim);
1346 *tune_state = CT_TUNER_STEP_2;
1347 } else if (*tune_state == CT_TUNER_STEP_2) {
1348
1349 adc = dib0090_read_reg(state, 0x1d);
1350 dprintk("FE %d CAPTRIM=%d; ADC = %d (ADC) & %dmV", (u32) fe->id, (u32) state->captrim, (u32) adc,
1351 (u32) (adc) * (u32) 1800 / (u32) 1024);
1352
1353 if (adc >= 400) {
1354 adc -= 400;
1355 step_sign = -1;
1356 } else {
1357 adc = 400 - adc;
1358 step_sign = 1;
1359 }
1360
1361 if (adc < state->adc_diff) {
1362 dprintk("FE %d CAPTRIM=%d is closer to target (%d/%d)", (u32) fe->id, (u32) state->captrim, (u32) adc, (u32) state->adc_diff);
1363 state->adc_diff = adc;
1364 state->fcaptrim = state->captrim;
1365
1366 }
1367
1368 state->captrim += step_sign * state->step;
1369 if (state->step >= 1)
1370 *tune_state = CT_TUNER_STEP_1;
1371 else
1372 *tune_state = CT_TUNER_STEP_3;
1373
1374 ret = 15;
1375 } else if (*tune_state == CT_TUNER_STEP_3) {
1376 /*write the final cptrim config */
1377 dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim);
1378
1379#ifdef CONFIG_TUNER_DIB0090_CAPTRIM_MEMORY
1380 state->memory[state->memory_index].cap = state->fcaptrim;
1381#endif
1382
1383 *tune_state = CT_TUNER_STEP_4;
1384 } else if (*tune_state == CT_TUNER_STEP_4) {
1385 dib0090_write_reg(state, 0x1e, 0x07ff);
1386
1387 dprintk("FE %d Final Captrim: %d", (u32) fe->id, (u32) state->fcaptrim);
1388 dprintk("FE %d HFDIV code: %d", (u32) fe->id, (u32) pll->hfdiv_code);
1389 dprintk("FE %d VCO = %d", (u32) fe->id, (u32) pll->vco_band);
1390 dprintk("FE %d VCOF in kHz: %d ((%d*%d) << 1))", (u32) fe->id, (u32) ((pll->hfdiv * rf) * 2), (u32) pll->hfdiv, (u32) rf);
1391 dprintk("FE %d REFDIV: %d, FREF: %d", (u32) fe->id, (u32) 1, (u32) state->config->io.clock_khz);
1392 dprintk("FE %d FBDIV: %d, Rest: %d", (u32) fe->id, (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17));
1393 dprintk("FE %d Num: %d, Den: %d, SD: %d", (u32) fe->id, (u32) dib0090_read_reg(state, 0x17),
1394 (u32) (dib0090_read_reg(state, 0x16) >> 8), (u32) dib0090_read_reg(state, 0x1c) & 0x3);
1395
1396 c = 4;
1397 i = 3;
1398#if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND)
1399 if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND)) {
1400 c = 2;
1401 i = 2;
1402 }
1403#endif
1404 dib0090_write_reg(state, 0x10, (c << 13) | (i << 11) | (WBD
1405#ifdef CONFIG_DIB0090_USE_PWM_AGC
1406 | (state->config->use_pwm_agc << 1)
1407#endif
1408 ));
1409 dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | (tune->lna_bias << 0));
1410 dib0090_write_reg(state, 0x0c, tune->v2i);
1411 dib0090_write_reg(state, 0x0d, tune->mix);
1412 dib0090_write_reg(state, 0x0e, tune->load);
1413
1414 *tune_state = CT_TUNER_STEP_5;
1415 } else if (*tune_state == CT_TUNER_STEP_5) {
1416
1417 /* initialize the lt gain register */
1418 state->rf_lt_def = 0x7c00;
1419 dib0090_write_reg(state, 0x0f, state->rf_lt_def);
1420
1421 dib0090_set_bandwidth(state);
1422 state->tuner_is_tuned = 1;
1423 *tune_state = CT_TUNER_STOP;
1424 } else
1425 ret = FE_CALLBACK_TIME_NEVER;
1426 return ret;
1427}
1428
1429static int dib0090_release(struct dvb_frontend *fe)
1430{
1431 kfree(fe->tuner_priv);
1432 fe->tuner_priv = NULL;
1433 return 0;
1434}
1435
1436enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
1437{
1438 struct dib0090_state *state = fe->tuner_priv;
1439
1440 return state->tune_state;
1441}
1442
1443EXPORT_SYMBOL(dib0090_get_tune_state);
1444
1445int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
1446{
1447 struct dib0090_state *state = fe->tuner_priv;
1448
1449 state->tune_state = tune_state;
1450 return 0;
1451}
1452
1453EXPORT_SYMBOL(dib0090_set_tune_state);
1454
1455static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency)
1456{
1457 struct dib0090_state *state = fe->tuner_priv;
1458
1459 *frequency = 1000 * state->current_rf;
1460 return 0;
1461}
1462
1463static int dib0090_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
1464{
1465 struct dib0090_state *state = fe->tuner_priv;
1466 uint32_t ret;
1467
1468 state->tune_state = CT_TUNER_START;
1469
1470 do {
1471 ret = dib0090_tune(fe);
1472 if (ret != FE_CALLBACK_TIME_NEVER)
1473 msleep(ret / 10);
1474 else
1475 break;
1476 } while (state->tune_state != CT_TUNER_STOP);
1477
1478 return 0;
1479}
1480
1481static const struct dvb_tuner_ops dib0090_ops = {
1482 .info = {
1483 .name = "DiBcom DiB0090",
1484 .frequency_min = 45000000,
1485 .frequency_max = 860000000,
1486 .frequency_step = 1000,
1487 },
1488 .release = dib0090_release,
1489
1490 .init = dib0090_wakeup,
1491 .sleep = dib0090_sleep,
1492 .set_params = dib0090_set_params,
1493 .get_frequency = dib0090_get_frequency,
1494};
1495
1496struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
1497{
1498 struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL);
1499 if (st == NULL)
1500 return NULL;
1501
1502 st->config = config;
1503 st->i2c = i2c;
1504 st->fe = fe;
1505 fe->tuner_priv = st;
1506
1507 if (dib0090_reset(fe) != 0)
1508 goto free_mem;
1509
1510 printk(KERN_INFO "DiB0090: successfully identified\n");
1511 memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops));
1512
1513 return fe;
1514 free_mem:
1515 kfree(st);
1516 fe->tuner_priv = NULL;
1517 return NULL;
1518}
1519
1520EXPORT_SYMBOL(dib0090_register);
1521
1522MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
1523MODULE_AUTHOR("Olivier Grenie <olivier.grenie@dibcom.fr>");
1524MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");
1525MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dib0090.h b/drivers/media/dvb/frontends/dib0090.h
new file mode 100644
index 000000000000..d72b7d758aa6
--- /dev/null
+++ b/drivers/media/dvb/frontends/dib0090.h
@@ -0,0 +1,114 @@
1/*
2 * Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner.
3 *
4 * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/)
5 *
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#ifndef DIB0090_H
11#define DIB0090_H
12
13struct dvb_frontend;
14struct i2c_adapter;
15
16#define DEFAULT_DIB0090_I2C_ADDRESS 0x60
17
18struct dib0090_io_config {
19 u32 clock_khz;
20
21 u8 pll_bypass:1;
22 u8 pll_range:1;
23 u8 pll_prediv:6;
24 u8 pll_loopdiv:6;
25
26 u8 adc_clock_ratio; /* valid is 8, 7 ,6 */
27 u16 pll_int_loop_filt; // internal loop filt value. If not fill in , default is 8165
28};
29
30struct dib0090_config {
31 struct dib0090_io_config io;
32 int (*reset) (struct dvb_frontend *, int);
33 int (*sleep) (struct dvb_frontend *, int);
34
35 /* offset in kHz */
36 int freq_offset_khz_uhf;
37 int freq_offset_khz_vhf;
38
39 int (*get_adc_power) (struct dvb_frontend *);
40
41 u8 clkouttobamse:1; /* activate or deactivate clock output */
42 u8 analog_output;
43
44 u8 i2c_address;
45 /* add drives and other things if necessary */
46 u16 wbd_vhf_offset;
47 u16 wbd_cband_offset;
48 u8 use_pwm_agc;
49 u8 clkoutdrive;
50};
51
52#if defined(CONFIG_DVB_TUNER_DIB0090) || (defined(CONFIG_DVB_TUNER_DIB0090_MODULE) && defined(MODULE))
53extern struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config);
54extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast);
55extern void dib0090_pwm_gain_reset(struct dvb_frontend *fe);
56extern u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner);
57extern int dib0090_gain_control(struct dvb_frontend *fe);
58extern enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe);
59extern int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
60extern enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe);
61extern void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt);
62#else
63static inline struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0090_config *config)
64{
65 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
66 return NULL;
67}
68
69static inline void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
70{
71 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
72}
73
74static inline void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
75{
76 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
77}
78
79static inline u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner)
80{
81 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
82 return 0;
83}
84
85static inline int dib0090_gain_control(struct dvb_frontend *fe)
86{
87 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
88 return -ENODEV;
89}
90
91static inline enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
92{
93 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
94 return CT_DONE;
95}
96
97static inline int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
98{
99 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
100 return -ENODEV;
101}
102
103static inline num frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe)
104{
105 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
106return CT_SHUTDOWN,}
107
108static inline void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
109{
110 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
111}
112#endif
113
114#endif
diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c
index 898400d331a3..b924e7eec5ac 100644
--- a/drivers/media/dvb/frontends/dib8000.c
+++ b/drivers/media/dvb/frontends/dib8000.c
@@ -28,18 +28,6 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
28 28
29#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB8000: "); printk(args); printk("\n"); } } while (0) 29#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB8000: "); printk(args); printk("\n"); } } while (0)
30 30
31enum frontend_tune_state {
32 CT_AGC_START = 20,
33 CT_AGC_STEP_0,
34 CT_AGC_STEP_1,
35 CT_AGC_STEP_2,
36 CT_AGC_STEP_3,
37 CT_AGC_STEP_4,
38 CT_AGC_STOP,
39
40 CT_DEMOD_START = 30,
41};
42
43#define FE_STATUS_TUNE_FAILED 0 31#define FE_STATUS_TUNE_FAILED 0
44 32
45struct i2c_device { 33struct i2c_device {
@@ -852,6 +840,14 @@ static int dib8000_set_agc_config(struct dib8000_state *state, u8 band)
852 return 0; 840 return 0;
853} 841}
854 842
843void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
844{
845 struct dib8000_state *state = fe->demodulator_priv;
846 dib8000_set_adc_state(state, DIBX000_ADC_ON);
847 dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000)));
848}
849EXPORT_SYMBOL(dib8000_pwm_agc_reset);
850
855static int dib8000_agc_soft_split(struct dib8000_state *state) 851static int dib8000_agc_soft_split(struct dib8000_state *state)
856{ 852{
857 u16 agc, split_offset; 853 u16 agc, split_offset;
@@ -939,6 +935,32 @@ static int dib8000_agc_startup(struct dvb_frontend *fe)
939 935
940} 936}
941 937
938static const int32_t lut_1000ln_mant[] =
939{
940 908,7003,7090,7170,7244,7313,7377,7438,7495,7549,7600
941};
942
943int32_t dib8000_get_adc_power(struct dvb_frontend *fe, uint8_t mode)
944{
945 struct dib8000_state *state = fe->demodulator_priv;
946 uint32_t ix =0, tmp_val =0, exp = 0, mant = 0;
947 int32_t val;
948
949 val = dib8000_read32(state, 384);
950 /* mode = 1 : ln_agcpower calc using mant-exp conversion and mantis look up table */
951 if(mode) {
952 tmp_val = val;
953 while(tmp_val>>=1)
954 exp++;
955 mant = (val * 1000 / (1<<exp));
956 ix = (uint8_t)((mant-1000)/100); /* index of the LUT */
957 val = (lut_1000ln_mant[ix] + 693*(exp-20) - 6908); /* 1000 * ln(adcpower_real) ; 693 = 1000ln(2) ; 6908 = 1000*ln(1000) ; 20 comes from adc_real = adc_pow_int / 2**20 */
958 val = (val*256)/1000;
959 }
960 return val;
961}
962EXPORT_SYMBOL(dib8000_get_adc_power);
963
942static void dib8000_update_timf(struct dib8000_state *state) 964static void dib8000_update_timf(struct dib8000_state *state)
943{ 965{
944 u32 timf = state->timf = dib8000_read32(state, 435); 966 u32 timf = state->timf = dib8000_read32(state, 435);
@@ -1854,6 +1876,24 @@ static int dib8000_sleep(struct dvb_frontend *fe)
1854 } 1876 }
1855} 1877}
1856 1878
1879enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend* fe)
1880{
1881 struct dib8000_state *state = fe->demodulator_priv;
1882 return state->tune_state;
1883}
1884EXPORT_SYMBOL(dib8000_get_tune_state);
1885
1886int dib8000_set_tune_state(struct dvb_frontend* fe, enum frontend_tune_state tune_state)
1887{
1888 struct dib8000_state *state = fe->demodulator_priv;
1889 state->tune_state = tune_state;
1890 return 0;
1891}
1892EXPORT_SYMBOL(dib8000_set_tune_state);
1893
1894
1895
1896
1857static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) 1897static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
1858{ 1898{
1859 struct dib8000_state *state = fe->demodulator_priv; 1899 struct dib8000_state *state = fe->demodulator_priv;
diff --git a/drivers/media/dvb/frontends/dib8000.h b/drivers/media/dvb/frontends/dib8000.h
index 8c89482b738a..de05a0ae9d98 100644
--- a/drivers/media/dvb/frontends/dib8000.h
+++ b/drivers/media/dvb/frontends/dib8000.h
@@ -46,6 +46,10 @@ extern int dib8000_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
46extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value); 46extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value);
47extern int dib8000_pid_filter_ctrl(struct dvb_frontend *, u8 onoff); 47extern int dib8000_pid_filter_ctrl(struct dvb_frontend *, u8 onoff);
48extern int dib8000_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff); 48extern int dib8000_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
49extern int dib8000_set_tune_state(struct dvb_frontend* fe, enum frontend_tune_state tune_state);
50extern enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend* fe);
51extern void dib8000_pwm_agc_reset(struct dvb_frontend *fe);
52extern s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode);
49#else 53#else
50static inline struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg) 54static inline struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
51{ 55{
@@ -59,35 +63,53 @@ static inline struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe
59 return NULL; 63 return NULL;
60} 64}
61 65
62int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr) 66static inline int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr)
63{ 67{
64 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); 68 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
65 return -ENODEV; 69 return -ENODEV;
66} 70}
67 71
68int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val) 72static inline int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
69{ 73{
70 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); 74 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
71 return -ENODEV; 75 return -ENODEV;
72} 76}
73 77
74int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value) 78static inline int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
75{ 79{
76 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); 80 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
77 return -ENODEV; 81 return -ENODEV;
78} 82}
79 83
80int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) 84static inline int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
81{ 85{
82 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); 86 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
83 return -ENODEV; 87 return -ENODEV;
84} 88}
85 89
86int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) 90static inline int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
87{ 91{
88 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); 92 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
89 return -ENODEV; 93 return -ENODEV;
90} 94}
95static inline int dib8000_set_tune_state(struct dvb_frontend* fe, enum frontend_tune_state tune_state)
96{
97 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
98 return -ENODEV;
99}
100static inline enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend* fe)
101{
102 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
103 return CT_SHUTDOWN,
104}
105static inline void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
106{
107 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
108}
109static inline s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
110{
111 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
112}
91#endif 113#endif
92 114
93#endif 115#endif
diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c
index 4efca30d2127..e6f3d73db9d3 100644
--- a/drivers/media/dvb/frontends/dibx000_common.c
+++ b/drivers/media/dvb/frontends/dibx000_common.c
@@ -6,7 +6,7 @@ static int debug;
6module_param(debug, int, 0644); 6module_param(debug, int, 0644);
7MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); 7MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
8 8
9#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); } } while (0) 9#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); printk("\n"); } } while (0)
10 10
11static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) 11static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
12{ 12{
@@ -25,7 +25,7 @@ static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst,
25 enum dibx000_i2c_interface intf) 25 enum dibx000_i2c_interface intf)
26{ 26{
27 if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) { 27 if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) {
28 dprintk("selecting interface: %d\n", intf); 28 dprintk("selecting interface: %d", intf);
29 mst->selected_interface = intf; 29 mst->selected_interface = intf;
30 return dibx000_write_word(mst, mst->base_reg + 4, intf); 30 return dibx000_write_word(mst, mst->base_reg + 4, intf);
31 } 31 }
@@ -171,9 +171,18 @@ void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst)
171{ 171{
172 i2c_del_adapter(&mst->gated_tuner_i2c_adap); 172 i2c_del_adapter(&mst->gated_tuner_i2c_adap);
173} 173}
174
175EXPORT_SYMBOL(dibx000_exit_i2c_master); 174EXPORT_SYMBOL(dibx000_exit_i2c_master);
176 175
176
177u32 systime()
178{
179 struct timespec t;
180
181 t = current_kernel_time();
182 return (t.tv_sec * 10000) + (t.tv_nsec / 100000);
183}
184EXPORT_SYMBOL(systime);
185
177MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); 186MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
178MODULE_DESCRIPTION("Common function the DiBcom demodulator family"); 187MODULE_DESCRIPTION("Common function the DiBcom demodulator family");
179MODULE_LICENSE("GPL"); 188MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h
index 5be10eca07c0..06328d8742f8 100644
--- a/drivers/media/dvb/frontends/dibx000_common.h
+++ b/drivers/media/dvb/frontends/dibx000_common.h
@@ -36,13 +36,17 @@ extern struct i2c_adapter *dibx000_get_i2c_adapter(struct dibx000_i2c_master
36extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst); 36extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst);
37extern void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst); 37extern void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst);
38 38
39extern u32 systime(void);
40
39#define BAND_LBAND 0x01 41#define BAND_LBAND 0x01
40#define BAND_UHF 0x02 42#define BAND_UHF 0x02
41#define BAND_VHF 0x04 43#define BAND_VHF 0x04
42#define BAND_SBAND 0x08 44#define BAND_SBAND 0x08
43#define BAND_FM 0x10 45#define BAND_FM 0x10
46#define BAND_CBAND 0x20
44 47
45#define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 115000 ? BAND_FM : \ 48#define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 170000 ? BAND_CBAND : \
49 (freq_kHz) <= 115000 ? BAND_FM : \
46 (freq_kHz) <= 250000 ? BAND_VHF : \ 50 (freq_kHz) <= 250000 ? BAND_VHF : \
47 (freq_kHz) <= 863000 ? BAND_UHF : \ 51 (freq_kHz) <= 863000 ? BAND_UHF : \
48 (freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND ) 52 (freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND )
@@ -149,4 +153,67 @@ enum dibx000_adc_states {
149#define OUTMODE_MPEG2_FIFO 5 153#define OUTMODE_MPEG2_FIFO 5
150#define OUTMODE_ANALOG_ADC 6 154#define OUTMODE_ANALOG_ADC 6
151 155
156enum frontend_tune_state {
157 CT_TUNER_START = 10,
158 CT_TUNER_STEP_0,
159 CT_TUNER_STEP_1,
160 CT_TUNER_STEP_2,
161 CT_TUNER_STEP_3,
162 CT_TUNER_STEP_4,
163 CT_TUNER_STEP_5,
164 CT_TUNER_STEP_6,
165 CT_TUNER_STEP_7,
166 CT_TUNER_STOP,
167
168 CT_AGC_START = 20,
169 CT_AGC_STEP_0,
170 CT_AGC_STEP_1,
171 CT_AGC_STEP_2,
172 CT_AGC_STEP_3,
173 CT_AGC_STEP_4,
174 CT_AGC_STOP,
175
176 CT_DEMOD_START = 30,
177 CT_DEMOD_STEP_1,
178 CT_DEMOD_STEP_2,
179 CT_DEMOD_STEP_3,
180 CT_DEMOD_STEP_4,
181 CT_DEMOD_STEP_5,
182 CT_DEMOD_STEP_6,
183 CT_DEMOD_STEP_7,
184 CT_DEMOD_STEP_8,
185 CT_DEMOD_STEP_9,
186 CT_DEMOD_STEP_10,
187 CT_DEMOD_SEARCH_NEXT = 41,
188 CT_DEMOD_STEP_LOCKED,
189 CT_DEMOD_STOP,
190
191 CT_DONE = 100,
192 CT_SHUTDOWN,
193
194};
195
196struct dvb_frontend_parametersContext {
197#define CHANNEL_STATUS_PARAMETERS_UNKNOWN 0x01
198#define CHANNEL_STATUS_PARAMETERS_SET 0x02
199 u8 status;
200 u32 tune_time_estimation[2];
201 s32 tps_available;
202 u16 tps[9];
203};
204
205#define FE_STATUS_TUNE_FAILED 0
206#define FE_STATUS_TUNE_TIMED_OUT -1
207#define FE_STATUS_TUNE_TIME_TOO_SHORT -2
208#define FE_STATUS_TUNE_PENDING -3
209#define FE_STATUS_STD_SUCCESS -4
210#define FE_STATUS_FFT_SUCCESS -5
211#define FE_STATUS_DEMOD_SUCCESS -6
212#define FE_STATUS_LOCKED -7
213#define FE_STATUS_DATA_LOCKED -8
214
215#define FE_CALLBACK_TIME_NEVER 0xffffffff
216
217#define ABS(x) ((x<0)?(-x):(x))
218
152#endif 219#endif