Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

V4L/DVB (12898): DiB0070: Update to latest internal release

General update of the dib0070-driver based on DiBcom's latest release.

New driver features can enable better performance in some reception situations.

Signed-off-by: Patrick Boettcher <Patrick.Boettcher@dibcom.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

authored by

Patrick Boettcher and committed by
Mauro Carvalho Chehab
7e5ce651 e7b7949a

+420 -297
+5 -2
drivers/media/dvb/dvb-usb/dib0700_devices.c
··· 1098 1098 1099 1099 static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff) 1100 1100 { 1101 + deb_info("reset: %d", onoff); 1101 1102 return dib7000p_set_gpio(fe, 8, 0, !onoff); 1102 1103 } 1103 1104 1104 1105 static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff) 1105 1106 { 1107 + deb_info("sleep: %d", onoff); 1106 1108 return dib7000p_set_gpio(fe, 9, 0, onoff); 1107 1109 } 1108 1110 ··· 1114 1112 .reset = dib7070_tuner_reset, 1115 1113 .sleep = dib7070_tuner_sleep, 1116 1114 .clock_khz = 12000, 1117 - .clock_pad_drive = 4 1115 + .clock_pad_drive = 4, 1116 + .charge_pump = 2, 1118 1117 }, { 1119 1118 .i2c_address = DEFAULT_DIB0070_I2C_ADDRESS, 1120 1119 .reset = dib7070_tuner_reset, 1121 1120 .sleep = dib7070_tuner_sleep, 1122 1121 .clock_khz = 12000, 1123 - 1122 + .charge_pump = 2, 1124 1123 } 1125 1124 }; 1126 1125
+404 -295
drivers/media/dvb/frontends/dib0070.c
··· 1 1 /* 2 2 * Linux-DVB Driver for DiBcom's DiB0070 base-band RF Tuner. 3 3 * 4 - * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/) 4 + * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/) 5 5 * 6 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. 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 + * 9 25 */ 26 + 10 27 #include <linux/kernel.h> 11 28 #include <linux/i2c.h> 12 29 ··· 36 19 module_param(debug, int, 0644); 37 20 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); 38 21 39 - #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB0070: "); printk(args); printk("\n"); } } while (0) 22 + #define dprintk(args...) do { \ 23 + if (debug) { \ 24 + printk(KERN_DEBUG "DiB0070: "); \ 25 + printk(args); \ 26 + printk("\n"); \ 27 + } \ 28 + } while (0) 40 29 41 30 #define DIB0070_P1D 0x00 42 31 #define DIB0070_P1F 0x01 43 32 #define DIB0070_P1G 0x03 44 33 #define DIB0070S_P1A 0x02 34 + 35 + enum frontend_tune_state { 36 + CT_TUNER_START = 10, 37 + CT_TUNER_STEP_0, 38 + CT_TUNER_STEP_1, 39 + CT_TUNER_STEP_2, 40 + CT_TUNER_STEP_3, 41 + CT_TUNER_STEP_4, 42 + CT_TUNER_STEP_5, 43 + CT_TUNER_STEP_6, 44 + CT_TUNER_STEP_7, 45 + CT_TUNER_STOP, 46 + }; 47 + 48 + #define FE_CALLBACK_TIME_NEVER 0xffffffff 45 49 46 50 struct dib0070_state { 47 51 struct i2c_adapter *i2c; ··· 70 32 const struct dib0070_config *cfg; 71 33 u16 wbd_ff_offset; 72 34 u8 revision; 35 + 36 + enum frontend_tune_state tune_state; 37 + u32 current_rf; 38 + 39 + /* for the captrim binary search */ 40 + s8 step; 41 + u16 adc_diff; 42 + 43 + s8 captrim; 44 + s8 fcaptrim; 45 + u16 lo4; 46 + 47 + const struct dib0070_tuning *current_tune_table_index; 48 + const struct dib0070_lna_match *lna_match; 49 + 50 + u8 wbd_gain_current; 51 + u16 wbd_offset_3_3[2]; 73 52 }; 74 53 75 54 static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) ··· 114 59 return 0; 115 60 } 116 61 117 - #define HARD_RESET(state) do { if (state->cfg->reset) { state->cfg->reset(state->fe,1); msleep(10); state->cfg->reset(state->fe,0); msleep(10); } } while (0) 62 + #define HARD_RESET(state) do { \ 63 + state->cfg->sleep(state->fe, 0); \ 64 + if (state->cfg->reset) { \ 65 + state->cfg->reset(state->fe,1); msleep(10); \ 66 + state->cfg->reset(state->fe,0); msleep(10); \ 67 + } \ 68 + } while (0) 118 69 119 70 static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) 120 71 { 121 - struct dib0070_state *st = fe->tuner_priv; 122 - u16 tmp = 0; 123 - tmp = dib0070_read_reg(st, 0x02) & 0x3fff; 72 + struct dib0070_state *st = fe->tuner_priv; 73 + u16 tmp = dib0070_read_reg(st, 0x02) & 0x3fff; 124 74 125 - switch(BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth)) { 126 - case 8000: 127 - tmp |= (0 << 14); 128 - break; 129 - case 7000: 130 - tmp |= (1 << 14); 131 - break; 132 - case 6000: 133 - tmp |= (2 << 14); 134 - break; 135 - case 5000: 136 - default: 137 - tmp |= (3 << 14); 138 - break; 139 - } 140 - dib0070_write_reg(st, 0x02, tmp); 75 + if (fe->dtv_property_cache.bandwidth_hz/1000 > 7000) 76 + tmp |= (0 << 14); 77 + else if (fe->dtv_property_cache.bandwidth_hz/1000 > 6000) 78 + tmp |= (1 << 14); 79 + else if (fe->dtv_property_cache.bandwidth_hz/1000 > 5000) 80 + tmp |= (2 << 14); 81 + else 82 + tmp |= (3 << 14); 83 + 84 + dib0070_write_reg(st, 0x02, tmp); 85 + 86 + /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */ 87 + if (fe->dtv_property_cache.delivery_system == SYS_ISDBT) { 88 + u16 value = dib0070_read_reg(st, 0x17); 89 + 90 + dib0070_write_reg(st, 0x17, value & 0xfffc); 91 + tmp = dib0070_read_reg(st, 0x01) & 0x01ff; 92 + dib0070_write_reg(st, 0x01, tmp | (60 << 9)); 93 + 94 + dib0070_write_reg(st, 0x17, value); 95 + } 141 96 return 0; 142 97 } 143 98 144 - static void dib0070_captrim(struct dib0070_state *st, u16 LO4) 99 + static int dib0070_captrim(struct dib0070_state *st, enum frontend_tune_state *tune_state) 145 100 { 146 - int8_t captrim, fcaptrim, step_sign, step; 147 - u16 adc, adc_diff = 3000; 101 + int8_t step_sign; 102 + u16 adc; 103 + int ret = 0; 148 104 105 + if (*tune_state == CT_TUNER_STEP_0) { 149 106 107 + dib0070_write_reg(st, 0x0f, 0xed10); 108 + dib0070_write_reg(st, 0x17, 0x0034); 150 109 151 - dib0070_write_reg(st, 0x0f, 0xed10); 152 - dib0070_write_reg(st, 0x17, 0x0034); 110 + dib0070_write_reg(st, 0x18, 0x0032); 111 + st->step = st->captrim = st->fcaptrim = 64; 112 + st->adc_diff = 3000; 113 + ret = 20; 153 114 154 - dib0070_write_reg(st, 0x18, 0x0032); 155 - msleep(2); 115 + *tune_state = CT_TUNER_STEP_1; 116 + } else if (*tune_state == CT_TUNER_STEP_1) { 117 + st->step /= 2; 118 + dib0070_write_reg(st, 0x14, st->lo4 | st->captrim); 119 + ret = 15; 156 120 157 - step = captrim = fcaptrim = 64; 121 + *tune_state = CT_TUNER_STEP_2; 122 + } else if (*tune_state == CT_TUNER_STEP_2) { 158 123 159 - do { 160 - step /= 2; 161 - dib0070_write_reg(st, 0x14, LO4 | captrim); 162 - msleep(1); 163 124 adc = dib0070_read_reg(st, 0x19); 164 125 165 - dprintk( "CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", captrim, adc, (u32) adc*(u32)1800/(u32)1024); 126 + dprintk( "CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", st->captrim, adc, (u32) adc*(u32)1800/(u32)1024); 166 127 167 128 if (adc >= 400) { 168 129 adc -= 400; ··· 188 117 step_sign = 1; 189 118 } 190 119 191 - if (adc < adc_diff) { 192 - dprintk( "CAPTRIM=%hd is closer to target (%hd/%hd)", captrim, adc, adc_diff); 193 - adc_diff = adc; 194 - fcaptrim = captrim; 120 + if (adc < st->adc_diff) { 121 + dprintk( "CAPTRIM=%hd is closer to target (%hd/%hd)", st->captrim, adc, st->adc_diff); 122 + st->adc_diff = adc; 123 + st->fcaptrim = st->captrim; 195 124 196 125 197 126 198 127 } 199 - captrim += (step_sign * step); 200 - } while (step >= 1); 128 + st->captrim += (step_sign * st->step); 201 129 202 - dib0070_write_reg(st, 0x14, LO4 | fcaptrim); 203 - dib0070_write_reg(st, 0x18, 0x07ff); 130 + if (st->step >= 1) 131 + *tune_state = CT_TUNER_STEP_1; 132 + else 133 + *tune_state = CT_TUNER_STEP_3; 134 + 135 + } else if (*tune_state == CT_TUNER_STEP_3) { 136 + dib0070_write_reg(st, 0x14, st->lo4 | st->fcaptrim); 137 + dib0070_write_reg(st, 0x18, 0x07ff); 138 + *tune_state = CT_TUNER_STEP_4; 139 + } 140 + 141 + return ret; 204 142 } 205 143 144 + static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt) 145 + { 146 + struct dib0070_state *state = fe->tuner_priv; 147 + u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0); 148 + dprintk( "CTRL_LO5: 0x%x", lo5); 149 + return dib0070_write_reg(state, 0x15, lo5); 150 + } 151 + 152 + struct dib0070_tuning 153 + { 154 + u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ 155 + u8 switch_trim; 156 + u8 vco_band; 157 + u8 hfdiv; 158 + u8 vco_multi; 159 + u8 presc; 160 + u8 wbdmux; 161 + u16 tuner_enable; 162 + }; 163 + 164 + struct dib0070_lna_match 165 + { 166 + u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ 167 + u8 lna_band; 168 + }; 169 + 170 + static const struct dib0070_tuning dib0070s_tuning_table[] = 171 + 172 + { 173 + { 570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */ 174 + { 700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 }, 175 + { 863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 }, 176 + { 1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */ 177 + { 1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, 178 + { 2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, 179 + { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */ 180 + }; 181 + 182 + static const struct dib0070_tuning dib0070_tuning_table[] = 183 + 184 + { 185 + { 115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */ 186 + { 179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */ 187 + { 189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 }, 188 + { 250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 }, 189 + { 569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800 }, /* UHF */ 190 + { 699999, 2, 0 ,1, 4, 2, 2, 0x4000 | 0x0800 }, 191 + { 863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800 }, 192 + { 0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */ 193 + }; 194 + 195 + static const struct dib0070_lna_match dib0070_lna_flip_chip[] = 196 + 197 + { 198 + { 180000, 0 }, /* VHF */ 199 + { 188000, 1 }, 200 + { 196400, 2 }, 201 + { 250000, 3 }, 202 + { 550000, 0 }, /* UHF */ 203 + { 590000, 1 }, 204 + { 666000, 3 }, 205 + { 864000, 5 }, 206 + { 1500000, 0 }, /* LBAND or everything higher than UHF */ 207 + { 1600000, 1 }, 208 + { 2000000, 3 }, 209 + { 0xffffffff, 7 }, 210 + }; 211 + 212 + static const struct dib0070_lna_match dib0070_lna[] = 213 + 214 + { 215 + { 180000, 0 }, /* VHF */ 216 + { 188000, 1 }, 217 + { 196400, 2 }, 218 + { 250000, 3 }, 219 + { 550000, 2 }, /* UHF */ 220 + { 650000, 3 }, 221 + { 750000, 5 }, 222 + { 850000, 6 }, 223 + { 864000, 7 }, 224 + { 1500000, 0 }, /* LBAND or everything higher than UHF */ 225 + { 1600000, 1 }, 226 + { 2000000, 3 }, 227 + { 0xffffffff, 7 }, 228 + }; 229 + 206 230 #define LPF 100 // define for the loop filter 100kHz by default 16-07-06 207 - #define LO4_SET_VCO_HFDIV(l, v, h) l |= ((v) << 11) | ((h) << 7) 208 - #define LO4_SET_SD(l, s) l |= ((s) << 14) | ((s) << 12) 209 - #define LO4_SET_CTRIM(l, c) l |= (c) << 10 210 231 static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) 211 232 { 212 - struct dib0070_state *st = fe->tuner_priv; 213 - u32 freq = ch->frequency/1000 + (BAND_OF_FREQUENCY(ch->frequency/1000) == BAND_VHF ? st->cfg->freq_offset_khz_vhf : st->cfg->freq_offset_khz_uhf); 233 + struct dib0070_state *st = fe->tuner_priv; 214 234 215 - u8 band = BAND_OF_FREQUENCY(freq), c; 235 + const struct dib0070_tuning *tune; 236 + const struct dib0070_lna_match *lna_match; 216 237 217 - /*******************VCO***********************************/ 218 - u16 lo4 = 0; 238 + enum frontend_tune_state *tune_state = &st->tune_state; 239 + int ret = 10; /* 1ms is the default delay most of the time */ 219 240 220 - u8 REFDIV, PRESC = 2; 221 - u32 FBDiv, Rest, FREF, VCOF_kHz; 222 - u16 Num, Den; 223 - /*******************FrontEnd******************************/ 224 - u16 value = 0; 241 + u8 band = (u8)BAND_OF_FREQUENCY(ch->frequency/1000); 242 + u32 freq = ch->frequency/1000 + (band == BAND_VHF ? st->cfg->freq_offset_khz_vhf : st->cfg->freq_offset_khz_uhf); 225 243 244 + 245 + 246 + 247 + 248 + #ifdef CONFIG_STANDARD_ISDBT 249 + if (fe->dtv_property_cache.delivery_system == SYS_ISDBT && ch->u.isdbt.sb_mode == 1) 250 + if ( ( (ch->u.isdbt.sb_conn_total_seg % 2) && (ch->u.isdbt.sb_wanted_seg == ((ch->u.isdbt.sb_conn_total_seg/2) + 1) ) ) || 251 + ( ( (ch->u.isdbt.sb_conn_total_seg % 2) == 0) && (ch->u.isdbt.sb_wanted_seg == (ch->u.isdbt.sb_conn_total_seg/2) ) ) || 252 + ( ( (ch->u.isdbt.sb_conn_total_seg % 2) == 0) && (ch->u.isdbt.sb_wanted_seg == ((ch->u.isdbt.sb_conn_total_seg/2)+1))) ) 253 + freq += 850; 254 + #endif 255 + if (st->current_rf != freq) { 256 + 257 + switch (st->revision) { 258 + case DIB0070S_P1A: 259 + tune = dib0070s_tuning_table; 260 + lna_match = dib0070_lna; 261 + break; 262 + default: 263 + tune = dib0070_tuning_table; 264 + if (st->cfg->flip_chip) 265 + lna_match = dib0070_lna_flip_chip; 266 + else 267 + lna_match = dib0070_lna; 268 + break; 269 + } 270 + while (freq > tune->max_freq) /* find the right one */ 271 + tune++; 272 + while (freq > lna_match->max_freq) /* find the right one */ 273 + lna_match++; 274 + 275 + st->current_tune_table_index = tune; 276 + st->lna_match = lna_match; 277 + } 278 + 279 + if (*tune_state == CT_TUNER_START) { 226 280 dprintk( "Tuning for Band: %hd (%d kHz)", band, freq); 281 + if (st->current_rf != freq) { 282 + u8 REFDIV; 283 + u32 FBDiv, Rest, FREF, VCOF_kHz; 284 + u8 Den; 285 + 286 + st->current_rf = freq; 287 + st->lo4 = (st->current_tune_table_index->vco_band << 11) | (st->current_tune_table_index->hfdiv << 7); 227 288 228 289 229 - dib0070_write_reg(st, 0x17, 0x30); 290 + dib0070_write_reg(st, 0x17, 0x30); 230 291 231 - dib0070_set_bandwidth(fe, ch); /* c is used as HF */ 232 - switch (st->revision) { 233 - case DIB0070S_P1A: 234 - switch (band) { 235 - case BAND_LBAND: 236 - LO4_SET_VCO_HFDIV(lo4, 1, 1); 237 - c = 2; 238 - break; 239 - case BAND_SBAND: 240 - LO4_SET_VCO_HFDIV(lo4, 0, 0); 241 - LO4_SET_CTRIM(lo4, 1); 242 - c = 1; 243 - break; 244 - case BAND_UHF: 245 - default: 246 - if (freq < 570000) { 247 - LO4_SET_VCO_HFDIV(lo4, 1, 3); 248 - PRESC = 6; c = 6; 249 - } else if (freq < 680000) { 250 - LO4_SET_VCO_HFDIV(lo4, 0, 2); 251 - c = 4; 252 - } else { 253 - LO4_SET_VCO_HFDIV(lo4, 1, 2); 254 - c = 4; 255 - } 256 - break; 257 - } break; 258 292 259 - case DIB0070_P1G: 260 - case DIB0070_P1F: 261 - default: 262 - switch (band) { 263 - case BAND_FM: 264 - LO4_SET_VCO_HFDIV(lo4, 0, 7); 265 - c = 24; 266 - break; 267 - case BAND_LBAND: 268 - LO4_SET_VCO_HFDIV(lo4, 1, 0); 269 - c = 2; 270 - break; 271 - case BAND_VHF: 272 - if (freq < 180000) { 273 - LO4_SET_VCO_HFDIV(lo4, 0, 3); 274 - c = 16; 275 - } else if (freq < 190000) { 276 - LO4_SET_VCO_HFDIV(lo4, 1, 3); 277 - c = 16; 278 - } else { 279 - LO4_SET_VCO_HFDIV(lo4, 0, 6); 280 - c = 12; 281 - } 282 - break; 293 + VCOF_kHz = st->current_tune_table_index->vco_multi * freq * 2; 283 294 284 - case BAND_UHF: 285 - default: 286 - if (freq < 570000) { 287 - LO4_SET_VCO_HFDIV(lo4, 1, 5); 288 - c = 6; 289 - } else if (freq < 700000) { 290 - LO4_SET_VCO_HFDIV(lo4, 0, 1); 291 - c = 4; 292 - } else { 293 - LO4_SET_VCO_HFDIV(lo4, 1, 1); 294 - c = 4; 295 - } 296 - break; 297 - } 295 + switch (band) { 296 + case BAND_VHF: 297 + REFDIV = (u8) ((st->cfg->clock_khz + 9999) / 10000); 298 298 break; 299 - } 300 - 301 - dprintk( "HFDIV code: %hd", (lo4 >> 7) & 0xf); 302 - dprintk( "VCO = %hd", (lo4 >> 11) & 0x3); 303 - 304 - 305 - VCOF_kHz = (c * freq) * 2; 306 - dprintk( "VCOF in kHz: %d ((%hd*%d) << 1))",VCOF_kHz, c, freq); 307 - 308 - switch (band) { 309 - case BAND_VHF: 310 - REFDIV = (u8) ((st->cfg->clock_khz + 9999) / 10000); 311 - break; 312 - case BAND_FM: 313 - REFDIV = (u8) ((st->cfg->clock_khz) / 1000); 314 - break; 315 - default: 316 - REFDIV = (u8) ( st->cfg->clock_khz / 10000); 317 - break; 318 - } 319 - FREF = st->cfg->clock_khz / REFDIV; 320 - 321 - dprintk( "REFDIV: %hd, FREF: %d", REFDIV, FREF); 299 + case BAND_FM: 300 + REFDIV = (u8) ((st->cfg->clock_khz) / 1000); 301 + break; 302 + default: 303 + REFDIV = (u8) ( st->cfg->clock_khz / 10000); 304 + break; 305 + } 306 + FREF = st->cfg->clock_khz / REFDIV; 322 307 323 308 324 309 325 - switch (st->revision) { 326 - case DIB0070S_P1A: 327 - FBDiv = (VCOF_kHz / PRESC / FREF); 328 - Rest = (VCOF_kHz / PRESC) - FBDiv * FREF; 329 - break; 310 + switch (st->revision) { 311 + case DIB0070S_P1A: 312 + FBDiv = (VCOF_kHz / st->current_tune_table_index->presc / FREF); 313 + Rest = (VCOF_kHz / st->current_tune_table_index->presc) - FBDiv * FREF; 314 + break; 330 315 331 - case DIB0070_P1G: 332 - case DIB0070_P1F: 333 - default: 334 - FBDiv = (freq / (FREF / 2)); 335 - Rest = 2 * freq - FBDiv * FREF; 336 - break; 337 - } 316 + case DIB0070_P1G: 317 + case DIB0070_P1F: 318 + default: 319 + FBDiv = (freq / (FREF / 2)); 320 + Rest = 2 * freq - FBDiv * FREF; 321 + break; 322 + } 338 323 339 324 340 - if (Rest < LPF) Rest = 0; 341 - else if (Rest < 2 * LPF) Rest = 2 * LPF; 342 - else if (Rest > (FREF - LPF)) { Rest = 0 ; FBDiv += 1; } 343 - else if (Rest > (FREF - 2 * LPF)) Rest = FREF - 2 * LPF; 344 - Rest = (Rest * 6528) / (FREF / 10); 345 - dprintk( "FBDIV: %d, Rest: %d", FBDiv, Rest); 325 + if (Rest < LPF) Rest = 0; 326 + else if (Rest < 2 * LPF) Rest = 2 * LPF; 327 + else if (Rest > (FREF - LPF)) { Rest = 0 ; FBDiv += 1; } 328 + else if (Rest > (FREF - 2 * LPF)) Rest = FREF - 2 * LPF; 329 + Rest = (Rest * 6528) / (FREF / 10); 346 330 347 - Num = 0; 348 - Den = 1; 349 - 350 - if (Rest > 0) { 351 - LO4_SET_SD(lo4, 1); 331 + Den = 1; 332 + if (Rest > 0) { 333 + st->lo4 |= (1 << 14) | (1 << 12); 352 334 Den = 255; 353 - Num = (u16)Rest; 335 + } 336 + 337 + 338 + dib0070_write_reg(st, 0x11, (u16)FBDiv); 339 + dib0070_write_reg(st, 0x12, (Den << 8) | REFDIV); 340 + dib0070_write_reg(st, 0x13, (u16) Rest); 341 + 342 + if (st->revision == DIB0070S_P1A) { 343 + 344 + if (band == BAND_SBAND) { 345 + dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); 346 + dib0070_write_reg(st, 0x1d,0xFFFF); 347 + } else 348 + dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1); 349 + } 350 + 351 + 352 + dib0070_write_reg(st, 0x20, 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | st->current_tune_table_index->tuner_enable); 353 + 354 + dprintk( "REFDIV: %hd, FREF: %d", REFDIV, FREF); 355 + dprintk( "FBDIV: %d, Rest: %d", FBDiv, Rest); 356 + dprintk( "Num: %hd, Den: %hd, SD: %hd",(u16) Rest, Den, (st->lo4 >> 12) & 0x1); 357 + dprintk( "HFDIV code: %hd", st->current_tune_table_index->hfdiv); 358 + dprintk( "VCO = %hd", st->current_tune_table_index->vco_band); 359 + dprintk( "VCOF: ((%hd*%d) << 1))", st->current_tune_table_index->vco_multi, freq); 360 + 361 + *tune_state = CT_TUNER_STEP_0; 362 + } else { /* we are already tuned to this frequency - the configuration is correct */ 363 + ret = 50; /* wakeup time */ 364 + *tune_state = CT_TUNER_STEP_5; 354 365 } 355 - dprintk( "Num: %hd, Den: %hd, SD: %hd",Num, Den, (lo4 >> 12) & 0x1); 366 + } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) { 356 367 368 + ret = dib0070_captrim(st, tune_state); 357 369 358 - 359 - dib0070_write_reg(st, 0x11, (u16)FBDiv); 360 - 361 - 362 - dib0070_write_reg(st, 0x12, (Den << 8) | REFDIV); 363 - 364 - 365 - dib0070_write_reg(st, 0x13, Num); 366 - 367 - 368 - value = 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001; 369 - 370 - switch (band) { 371 - case BAND_UHF: value |= 0x4000 | 0x0800; break; 372 - case BAND_LBAND: value |= 0x2000 | 0x0400; break; 373 - default: value |= 0x8000 | 0x1000; break; 374 - } 375 - dib0070_write_reg(st, 0x20, value); 376 - 377 - dib0070_captrim(st, lo4); 378 - if (st->revision == DIB0070S_P1A) { 379 - if (band == BAND_SBAND) 380 - dib0070_write_reg(st, 0x15, 0x16e2); 381 - else 382 - dib0070_write_reg(st, 0x15, 0x56e5); 370 + } else if (*tune_state == CT_TUNER_STEP_4) { 371 + const struct dib0070_wbd_gain_cfg *tmp = st->cfg->wbd_gain; 372 + if (tmp != NULL) { 373 + while (freq/1000 > tmp->freq) /* find the right one */ 374 + tmp++; 375 + dib0070_write_reg(st, 0x0f, (0 << 15) | (1 << 14) | (3 << 12) | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7) | (st->current_tune_table_index->wbdmux << 0)); 376 + st->wbd_gain_current = tmp->wbd_gain_val; 377 + } else { 378 + dib0070_write_reg(st, 0x0f, (0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (st->current_tune_table_index->wbdmux << 0)); 379 + st->wbd_gain_current = 6; 383 380 } 384 381 385 - 386 - 387 - switch (band) { 388 - case BAND_UHF: value = 0x7c82; break; 389 - case BAND_LBAND: value = 0x7c84; break; 390 - default: value = 0x7c81; break; 391 - } 392 - dib0070_write_reg(st, 0x0f, value); 393 382 dib0070_write_reg(st, 0x06, 0x3fff); 394 - 395 - /* Front End */ 396 - /* c == TUNE, value = SWITCH */ 397 - c = 0; 398 - value = 0; 399 - switch (band) { 400 - case BAND_FM: 401 - c = 0; value = 1; 402 - break; 403 - 404 - case BAND_VHF: 405 - if (freq <= 180000) c = 0; 406 - else if (freq <= 188200) c = 1; 407 - else if (freq <= 196400) c = 2; 408 - else c = 3; 409 - value = 1; 410 - break; 411 - 412 - case BAND_LBAND: 413 - if (freq <= 1500000) c = 0; 414 - else if (freq <= 1600000) c = 1; 415 - else c = 3; 416 - break; 417 - 418 - case BAND_SBAND: 419 - c = 7; 420 - dib0070_write_reg(st, 0x1d,0xFFFF); 421 - break; 422 - 423 - case BAND_UHF: 424 - default: 425 - if (st->cfg->flip_chip) { 426 - if (freq <= 550000) c = 0; 427 - else if (freq <= 590000) c = 1; 428 - else if (freq <= 666000) c = 3; 429 - else c = 5; 430 - } else { 431 - if (freq <= 550000) c = 2; 432 - else if (freq <= 650000) c = 3; 433 - else if (freq <= 750000) c = 5; 434 - else if (freq <= 850000) c = 6; 435 - else c = 7; 436 - } 437 - value = 2; 438 - break; 439 - } 440 - 441 - /* default: LNA_MATCH=7, BIAS=3 */ 442 - dib0070_write_reg(st, 0x07, (value << 11) | (7 << 8) | (c << 3) | (3 << 0)); 443 - dib0070_write_reg(st, 0x08, (c << 10) | (3 << 7) | (127)); 383 + dib0070_write_reg(st, 0x07, (st->current_tune_table_index->switch_trim << 11) | (7 << 8) | (st->lna_match->lna_band << 3) | (3 << 0)); 384 + dib0070_write_reg(st, 0x08, (st->lna_match->lna_band << 10) | (3 << 7) | (127)); 444 385 dib0070_write_reg(st, 0x0d, 0x0d80); 445 386 446 387 447 388 dib0070_write_reg(st, 0x18, 0x07ff); 448 389 dib0070_write_reg(st, 0x17, 0x0033); 449 390 450 - return 0; 391 + 392 + *tune_state = CT_TUNER_STEP_5; 393 + } else if (*tune_state == CT_TUNER_STEP_5) { 394 + dib0070_set_bandwidth(fe, ch); 395 + *tune_state = CT_TUNER_STOP; 396 + } else { 397 + ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */ 398 + } 399 + return ret; 400 + } 401 + 402 + 403 + static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) 404 + { 405 + struct dib0070_state *state = fe->tuner_priv; 406 + uint32_t ret; 407 + 408 + state->tune_state = CT_TUNER_START; 409 + 410 + do { 411 + ret = dib0070_tune_digital(fe, p); 412 + if (ret != FE_CALLBACK_TIME_NEVER) 413 + msleep(ret/10); 414 + else 415 + break; 416 + } while (state->tune_state != CT_TUNER_STOP); 417 + 418 + return 0; 451 419 } 452 420 453 421 static int dib0070_wakeup(struct dvb_frontend *fe) ··· 505 395 return 0; 506 396 } 507 397 508 - static u16 dib0070_p1f_defaults[] = 398 + static const u16 dib0070_p1f_defaults[] = 509 399 510 400 { 511 401 7, 0x02, ··· 544 434 0, 545 435 }; 546 436 547 - static void dib0070_wbd_calibration(struct dvb_frontend *fe) 437 + static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain) 548 438 { 549 - u16 wbd_offs; 550 - struct dib0070_state *state = fe->tuner_priv; 439 + u16 tuner_en = dib0070_read_reg(state, 0x20); 440 + u16 offset; 551 441 552 - if (state->cfg->sleep) 553 - state->cfg->sleep(fe, 0); 442 + dib0070_write_reg(state, 0x18, 0x07ff); 443 + dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001); 444 + dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0)); 445 + msleep(9); 446 + offset = dib0070_read_reg(state, 0x19); 447 + dib0070_write_reg(state, 0x20, tuner_en); 448 + return offset; 449 + } 554 450 555 - dib0070_write_reg(state, 0x0f, 0x6d81); 556 - dib0070_write_reg(state, 0x20, 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001); 557 - msleep(9); 558 - wbd_offs = dib0070_read_reg(state, 0x19); 559 - dib0070_write_reg(state, 0x20, 0); 560 - state->wbd_ff_offset = ((wbd_offs * 8 * 18 / 33 + 1) / 2); 561 - dprintk( "WBDStart = %d (Vargen) - FF = %hd", (u32) wbd_offs * 1800/1024, state->wbd_ff_offset); 562 - 563 - if (state->cfg->sleep) 564 - state->cfg->sleep(fe, 1); 565 - 451 + static void dib0070_wbd_offset_calibration(struct dib0070_state *state) 452 + { 453 + u8 gain; 454 + for (gain = 6; gain < 8; gain++) { 455 + state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2); 456 + dprintk( "Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain-6]); 457 + } 566 458 } 567 459 568 460 u16 dib0070_wbd_offset(struct dvb_frontend *fe) 569 461 { 570 462 struct dib0070_state *st = fe->tuner_priv; 571 - return st->wbd_ff_offset; 463 + return st->wbd_offset_3_3[st->wbd_gain_current - 6]; 572 464 } 573 465 574 466 EXPORT_SYMBOL(dib0070_wbd_offset); 575 - static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt) 576 - { 577 - struct dib0070_state *state = fe->tuner_priv; 578 - u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0); 579 - dprintk( "CTRL_LO5: 0x%x", lo5); 580 - return dib0070_write_reg(state, 0x15, lo5); 581 - } 582 - 583 467 #define pgm_read_word(w) (*w) 584 - static int dib0070_reset(struct dib0070_state *state) 468 + static int dib0070_reset(struct dvb_frontend *fe) 585 469 { 470 + struct dib0070_state *state = fe->tuner_priv; 586 471 u16 l, r, *n; 587 472 588 473 HARD_RESET(state); ··· 587 482 if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1) 588 483 state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff; 589 484 else 485 + #else 486 + #warning forcing SBAND 590 487 #endif 591 488 state->revision = DIB0070S_P1A; 592 489 ··· 618 511 else 619 512 r = 2; 620 513 514 + 621 515 r |= state->cfg->osc_buffer_state << 3; 622 516 623 517 dib0070_write_reg(state, 0x10, r); 624 - dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 4)); 518 + dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5)); 625 519 626 520 if (state->cfg->invert_iq) { 627 521 r = dib0070_read_reg(state, 0x02) & 0xffdf; 628 522 dib0070_write_reg(state, 0x02, r | (1 << 5)); 629 523 } 630 524 631 - 632 - if (state->revision == DIB0070S_P1A) 633 - dib0070_set_ctrl_lo5(state->fe, 4, 7, 3, 1); 634 - else 635 - dib0070_set_ctrl_lo5(state->fe, 4, 4, 2, 0); 525 + if (state->revision == DIB0070S_P1A) 526 + dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); 527 + else 528 + dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter); 636 529 637 530 dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8); 638 - return 0; 531 + 532 + dib0070_wbd_offset_calibration(state); 533 + 534 + return 0; 639 535 } 640 536 641 537 ··· 649 539 return 0; 650 540 } 651 541 652 - static struct dvb_tuner_ops dib0070_ops = { 542 + static const struct dvb_tuner_ops dib0070_ops = { 653 543 .info = { 654 544 .name = "DiBcom DiB0070", 655 545 .frequency_min = 45000000, ··· 660 550 661 551 .init = dib0070_wakeup, 662 552 .sleep = dib0070_sleep, 663 - .set_params = dib0070_tune_digital, 553 + .set_params = dib0070_tune, 554 + 664 555 // .get_frequency = dib0070_get_frequency, 665 556 // .get_bandwidth = dib0070_get_bandwidth 666 557 }; ··· 677 566 state->fe = fe; 678 567 fe->tuner_priv = state; 679 568 680 - if (dib0070_reset(state) != 0) 569 + if (dib0070_reset(fe) != 0) 681 570 goto free_mem; 682 - 683 - dib0070_wbd_calibration(fe); 684 571 685 572 printk(KERN_INFO "DiB0070: successfully identified\n"); 686 573 memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
+11
drivers/media/dvb/frontends/dib0070.h
··· 15 15 16 16 #define DEFAULT_DIB0070_I2C_ADDRESS 0x60 17 17 18 + struct dib0070_wbd_gain_cfg { 19 + u16 freq; 20 + u16 wbd_gain_val; 21 + }; 22 + 18 23 struct dib0070_config { 19 24 u8 i2c_address; 20 25 ··· 40 35 u8 force_crystal_mode; /* if == 0 -> decision is made in the driver default: <24 -> 2, >=24 -> 1 */ 41 36 42 37 u8 flip_chip; 38 + u8 enable_third_order_filter; 39 + u8 charge_pump; 40 + 41 + const struct dib0070_wbd_gain_cfg * wbd_gain; 42 + 43 + u8 vga_filter; 43 44 }; 44 45 45 46 #if defined(CONFIG_DVB_TUNER_DIB0070) || (defined(CONFIG_DVB_TUNER_DIB0070_MODULE) && defined(MODULE))