0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0012
0013 #include <linux/kernel.h>
0014 #include <linux/slab.h>
0015 #include <linux/i2c.h>
0016 #include <linux/mutex.h>
0017
0018 #include <media/dvb_frontend.h>
0019
0020 #include "dib0070.h"
0021 #include "dibx000_common.h"
0022
0023 static int debug;
0024 module_param(debug, int, 0644);
0025 MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
0026
0027 #define dprintk(fmt, arg...) do { \
0028 if (debug) \
0029 printk(KERN_DEBUG pr_fmt("%s: " fmt), \
0030 __func__, ##arg); \
0031 } while (0)
0032
0033 #define DIB0070_P1D 0x00
0034 #define DIB0070_P1F 0x01
0035 #define DIB0070_P1G 0x03
0036 #define DIB0070S_P1A 0x02
0037
0038 struct dib0070_state {
0039 struct i2c_adapter *i2c;
0040 struct dvb_frontend *fe;
0041 const struct dib0070_config *cfg;
0042 u16 wbd_ff_offset;
0043 u8 revision;
0044
0045 enum frontend_tune_state tune_state;
0046 u32 current_rf;
0047
0048
0049 s8 step;
0050 u16 adc_diff;
0051
0052 s8 captrim;
0053 s8 fcaptrim;
0054 u16 lo4;
0055
0056 const struct dib0070_tuning *current_tune_table_index;
0057 const struct dib0070_lna_match *lna_match;
0058
0059 u8 wbd_gain_current;
0060 u16 wbd_offset_3_3[2];
0061
0062
0063 struct i2c_msg msg[2];
0064 u8 i2c_write_buffer[3];
0065 u8 i2c_read_buffer[2];
0066 struct mutex i2c_buffer_lock;
0067 };
0068
0069 static u16 dib0070_read_reg(struct dib0070_state *state, u8 reg)
0070 {
0071 u16 ret;
0072
0073 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
0074 dprintk("could not acquire lock\n");
0075 return 0;
0076 }
0077
0078 state->i2c_write_buffer[0] = reg;
0079
0080 memset(state->msg, 0, 2 * sizeof(struct i2c_msg));
0081 state->msg[0].addr = state->cfg->i2c_address;
0082 state->msg[0].flags = 0;
0083 state->msg[0].buf = state->i2c_write_buffer;
0084 state->msg[0].len = 1;
0085 state->msg[1].addr = state->cfg->i2c_address;
0086 state->msg[1].flags = I2C_M_RD;
0087 state->msg[1].buf = state->i2c_read_buffer;
0088 state->msg[1].len = 2;
0089
0090 if (i2c_transfer(state->i2c, state->msg, 2) != 2) {
0091 pr_warn("DiB0070 I2C read failed\n");
0092 ret = 0;
0093 } else
0094 ret = (state->i2c_read_buffer[0] << 8)
0095 | state->i2c_read_buffer[1];
0096
0097 mutex_unlock(&state->i2c_buffer_lock);
0098 return ret;
0099 }
0100
0101 static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val)
0102 {
0103 int ret;
0104
0105 if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) {
0106 dprintk("could not acquire lock\n");
0107 return -EINVAL;
0108 }
0109 state->i2c_write_buffer[0] = reg;
0110 state->i2c_write_buffer[1] = val >> 8;
0111 state->i2c_write_buffer[2] = val & 0xff;
0112
0113 memset(state->msg, 0, sizeof(struct i2c_msg));
0114 state->msg[0].addr = state->cfg->i2c_address;
0115 state->msg[0].flags = 0;
0116 state->msg[0].buf = state->i2c_write_buffer;
0117 state->msg[0].len = 3;
0118
0119 if (i2c_transfer(state->i2c, state->msg, 1) != 1) {
0120 pr_warn("DiB0070 I2C write failed\n");
0121 ret = -EREMOTEIO;
0122 } else
0123 ret = 0;
0124
0125 mutex_unlock(&state->i2c_buffer_lock);
0126 return ret;
0127 }
0128
0129 #define HARD_RESET(state) do { \
0130 state->cfg->sleep(state->fe, 0); \
0131 if (state->cfg->reset) { \
0132 state->cfg->reset(state->fe,1); msleep(10); \
0133 state->cfg->reset(state->fe,0); msleep(10); \
0134 } \
0135 } while (0)
0136
0137 static int dib0070_set_bandwidth(struct dvb_frontend *fe)
0138 {
0139 struct dib0070_state *state = fe->tuner_priv;
0140 u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff;
0141
0142 if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 7000)
0143 tmp |= (0 << 14);
0144 else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 6000)
0145 tmp |= (1 << 14);
0146 else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 5000)
0147 tmp |= (2 << 14);
0148 else
0149 tmp |= (3 << 14);
0150
0151 dib0070_write_reg(state, 0x02, tmp);
0152
0153
0154 if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) {
0155 u16 value = dib0070_read_reg(state, 0x17);
0156
0157 dib0070_write_reg(state, 0x17, value & 0xfffc);
0158 tmp = dib0070_read_reg(state, 0x01) & 0x01ff;
0159 dib0070_write_reg(state, 0x01, tmp | (60 << 9));
0160
0161 dib0070_write_reg(state, 0x17, value);
0162 }
0163 return 0;
0164 }
0165
0166 static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state *tune_state)
0167 {
0168 int8_t step_sign;
0169 u16 adc;
0170 int ret = 0;
0171
0172 if (*tune_state == CT_TUNER_STEP_0) {
0173 dib0070_write_reg(state, 0x0f, 0xed10);
0174 dib0070_write_reg(state, 0x17, 0x0034);
0175
0176 dib0070_write_reg(state, 0x18, 0x0032);
0177 state->step = state->captrim = state->fcaptrim = 64;
0178 state->adc_diff = 3000;
0179 ret = 20;
0180
0181 *tune_state = CT_TUNER_STEP_1;
0182 } else if (*tune_state == CT_TUNER_STEP_1) {
0183 state->step /= 2;
0184 dib0070_write_reg(state, 0x14, state->lo4 | state->captrim);
0185 ret = 15;
0186
0187 *tune_state = CT_TUNER_STEP_2;
0188 } else if (*tune_state == CT_TUNER_STEP_2) {
0189
0190 adc = dib0070_read_reg(state, 0x19);
0191
0192 dprintk("CAPTRIM=%d; ADC = %hd (ADC) & %dmV\n", state->captrim,
0193 adc, (u32)adc * (u32)1800 / (u32)1024);
0194
0195 if (adc >= 400) {
0196 adc -= 400;
0197 step_sign = -1;
0198 } else {
0199 adc = 400 - adc;
0200 step_sign = 1;
0201 }
0202
0203 if (adc < state->adc_diff) {
0204 dprintk("CAPTRIM=%d is closer to target (%hd/%hd)\n",
0205 state->captrim, adc, state->adc_diff);
0206 state->adc_diff = adc;
0207 state->fcaptrim = state->captrim;
0208 }
0209 state->captrim += (step_sign * state->step);
0210
0211 if (state->step >= 1)
0212 *tune_state = CT_TUNER_STEP_1;
0213 else
0214 *tune_state = CT_TUNER_STEP_3;
0215
0216 } else if (*tune_state == CT_TUNER_STEP_3) {
0217 dib0070_write_reg(state, 0x14, state->lo4 | state->fcaptrim);
0218 dib0070_write_reg(state, 0x18, 0x07ff);
0219 *tune_state = CT_TUNER_STEP_4;
0220 }
0221
0222 return ret;
0223 }
0224
0225 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)
0226 {
0227 struct dib0070_state *state = fe->tuner_priv;
0228 u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0);
0229
0230 dprintk("CTRL_LO5: 0x%x\n", lo5);
0231 return dib0070_write_reg(state, 0x15, lo5);
0232 }
0233
0234 void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open)
0235 {
0236 struct dib0070_state *state = fe->tuner_priv;
0237
0238 if (open) {
0239 dib0070_write_reg(state, 0x1b, 0xff00);
0240 dib0070_write_reg(state, 0x1a, 0x0000);
0241 } else {
0242 dib0070_write_reg(state, 0x1b, 0x4112);
0243 if (state->cfg->vga_filter != 0) {
0244 dib0070_write_reg(state, 0x1a, state->cfg->vga_filter);
0245 dprintk("vga filter register is set to %x\n", state->cfg->vga_filter);
0246 } else
0247 dib0070_write_reg(state, 0x1a, 0x0009);
0248 }
0249 }
0250
0251 EXPORT_SYMBOL(dib0070_ctrl_agc_filter);
0252 struct dib0070_tuning {
0253 u32 max_freq;
0254 u8 switch_trim;
0255 u8 vco_band;
0256 u8 hfdiv;
0257 u8 vco_multi;
0258 u8 presc;
0259 u8 wbdmux;
0260 u16 tuner_enable;
0261 };
0262
0263 struct dib0070_lna_match {
0264 u32 max_freq;
0265 u8 lna_band;
0266 };
0267
0268 static const struct dib0070_tuning dib0070s_tuning_table[] = {
0269 { 570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 },
0270 { 700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 },
0271 { 863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 },
0272 { 1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
0273 { 1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
0274 { 2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 },
0275 { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 },
0276 };
0277
0278 static const struct dib0070_tuning dib0070_tuning_table[] = {
0279 { 115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 },
0280 { 179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 },
0281 { 189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 },
0282 { 250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 },
0283 { 569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800 },
0284 { 699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800 },
0285 { 863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800 },
0286 { 0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400 },
0287 };
0288
0289 static const struct dib0070_lna_match dib0070_lna_flip_chip[] = {
0290 { 180000, 0 },
0291 { 188000, 1 },
0292 { 196400, 2 },
0293 { 250000, 3 },
0294 { 550000, 0 },
0295 { 590000, 1 },
0296 { 666000, 3 },
0297 { 864000, 5 },
0298 { 1500000, 0 },
0299 { 1600000, 1 },
0300 { 2000000, 3 },
0301 { 0xffffffff, 7 },
0302 };
0303
0304 static const struct dib0070_lna_match dib0070_lna[] = {
0305 { 180000, 0 },
0306 { 188000, 1 },
0307 { 196400, 2 },
0308 { 250000, 3 },
0309 { 550000, 2 },
0310 { 650000, 3 },
0311 { 750000, 5 },
0312 { 850000, 6 },
0313 { 864000, 7 },
0314 { 1500000, 0 },
0315 { 1600000, 1 },
0316 { 2000000, 3 },
0317 { 0xffffffff, 7 },
0318 };
0319
0320 #define LPF 100
0321 static int dib0070_tune_digital(struct dvb_frontend *fe)
0322 {
0323 struct dib0070_state *state = fe->tuner_priv;
0324
0325 const struct dib0070_tuning *tune;
0326 const struct dib0070_lna_match *lna_match;
0327
0328 enum frontend_tune_state *tune_state = &state->tune_state;
0329 int ret = 10;
0330
0331 u8 band = (u8)BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency/1000);
0332 u32 freq = fe->dtv_property_cache.frequency/1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf);
0333
0334 #ifdef CONFIG_SYS_ISDBT
0335 if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
0336 if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2)
0337 && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
0338 || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
0339 && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2)))
0340 || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
0341 && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))))
0342 freq += 850;
0343 #endif
0344 if (state->current_rf != freq) {
0345
0346 switch (state->revision) {
0347 case DIB0070S_P1A:
0348 tune = dib0070s_tuning_table;
0349 lna_match = dib0070_lna;
0350 break;
0351 default:
0352 tune = dib0070_tuning_table;
0353 if (state->cfg->flip_chip)
0354 lna_match = dib0070_lna_flip_chip;
0355 else
0356 lna_match = dib0070_lna;
0357 break;
0358 }
0359 while (freq > tune->max_freq)
0360 tune++;
0361 while (freq > lna_match->max_freq)
0362 lna_match++;
0363
0364 state->current_tune_table_index = tune;
0365 state->lna_match = lna_match;
0366 }
0367
0368 if (*tune_state == CT_TUNER_START) {
0369 dprintk("Tuning for Band: %d (%d kHz)\n", band, freq);
0370 if (state->current_rf != freq) {
0371 u8 REFDIV;
0372 u32 FBDiv, Rest, FREF, VCOF_kHz;
0373 u8 Den;
0374
0375 state->current_rf = freq;
0376 state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7);
0377
0378
0379 dib0070_write_reg(state, 0x17, 0x30);
0380
0381
0382 VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2;
0383
0384 switch (band) {
0385 case BAND_VHF:
0386 REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000);
0387 break;
0388 case BAND_FM:
0389 REFDIV = (u8) ((state->cfg->clock_khz) / 1000);
0390 break;
0391 default:
0392 REFDIV = (u8) (state->cfg->clock_khz / 10000);
0393 break;
0394 }
0395 FREF = state->cfg->clock_khz / REFDIV;
0396
0397
0398
0399 switch (state->revision) {
0400 case DIB0070S_P1A:
0401 FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF);
0402 Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF;
0403 break;
0404
0405 case DIB0070_P1G:
0406 case DIB0070_P1F:
0407 default:
0408 FBDiv = (freq / (FREF / 2));
0409 Rest = 2 * freq - FBDiv * FREF;
0410 break;
0411 }
0412
0413 if (Rest < LPF)
0414 Rest = 0;
0415 else if (Rest < 2 * LPF)
0416 Rest = 2 * LPF;
0417 else if (Rest > (FREF - LPF)) {
0418 Rest = 0;
0419 FBDiv += 1;
0420 } else if (Rest > (FREF - 2 * LPF))
0421 Rest = FREF - 2 * LPF;
0422 Rest = (Rest * 6528) / (FREF / 10);
0423
0424 Den = 1;
0425 if (Rest > 0) {
0426 state->lo4 |= (1 << 14) | (1 << 12);
0427 Den = 255;
0428 }
0429
0430
0431 dib0070_write_reg(state, 0x11, (u16)FBDiv);
0432 dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV);
0433 dib0070_write_reg(state, 0x13, (u16) Rest);
0434
0435 if (state->revision == DIB0070S_P1A) {
0436
0437 if (band == BAND_SBAND) {
0438 dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
0439 dib0070_write_reg(state, 0x1d, 0xFFFF);
0440 } else
0441 dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1);
0442 }
0443
0444 dib0070_write_reg(state, 0x20,
0445 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable);
0446
0447 dprintk("REFDIV: %u, FREF: %d\n", REFDIV, FREF);
0448 dprintk("FBDIV: %d, Rest: %d\n", FBDiv, Rest);
0449 dprintk("Num: %u, Den: %u, SD: %d\n", (u16)Rest, Den,
0450 (state->lo4 >> 12) & 0x1);
0451 dprintk("HFDIV code: %u\n",
0452 state->current_tune_table_index->hfdiv);
0453 dprintk("VCO = %u\n",
0454 state->current_tune_table_index->vco_band);
0455 dprintk("VCOF: ((%u*%d) << 1))\n",
0456 state->current_tune_table_index->vco_multi,
0457 freq);
0458
0459 *tune_state = CT_TUNER_STEP_0;
0460 } else {
0461 ret = 50;
0462 *tune_state = CT_TUNER_STEP_5;
0463 }
0464 } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) {
0465
0466 ret = dib0070_captrim(state, tune_state);
0467
0468 } else if (*tune_state == CT_TUNER_STEP_4) {
0469 const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
0470 if (tmp != NULL) {
0471 while (freq/1000 > tmp->freq)
0472 tmp++;
0473 dib0070_write_reg(state, 0x0f,
0474 (0 << 15) | (1 << 14) | (3 << 12)
0475 | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7)
0476 | (state->current_tune_table_index->wbdmux << 0));
0477 state->wbd_gain_current = tmp->wbd_gain_val;
0478 } else {
0479 dib0070_write_reg(state, 0x0f,
0480 (0 << 15) | (1 << 14) | (3 << 12)
0481 | (6 << 9) | (0 << 8) | (1 << 7)
0482 | (state->current_tune_table_index->wbdmux << 0));
0483 state->wbd_gain_current = 6;
0484 }
0485
0486 dib0070_write_reg(state, 0x06, 0x3fff);
0487 dib0070_write_reg(state, 0x07,
0488 (state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0));
0489 dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127));
0490 dib0070_write_reg(state, 0x0d, 0x0d80);
0491
0492
0493 dib0070_write_reg(state, 0x18, 0x07ff);
0494 dib0070_write_reg(state, 0x17, 0x0033);
0495
0496
0497 *tune_state = CT_TUNER_STEP_5;
0498 } else if (*tune_state == CT_TUNER_STEP_5) {
0499 dib0070_set_bandwidth(fe);
0500 *tune_state = CT_TUNER_STOP;
0501 } else {
0502 ret = FE_CALLBACK_TIME_NEVER;
0503 }
0504 return ret;
0505 }
0506
0507
0508 static int dib0070_tune(struct dvb_frontend *fe)
0509 {
0510 struct dib0070_state *state = fe->tuner_priv;
0511 uint32_t ret;
0512
0513 state->tune_state = CT_TUNER_START;
0514
0515 do {
0516 ret = dib0070_tune_digital(fe);
0517 if (ret != FE_CALLBACK_TIME_NEVER)
0518 msleep(ret/10);
0519 else
0520 break;
0521 } while (state->tune_state != CT_TUNER_STOP);
0522
0523 return 0;
0524 }
0525
0526 static int dib0070_wakeup(struct dvb_frontend *fe)
0527 {
0528 struct dib0070_state *state = fe->tuner_priv;
0529 if (state->cfg->sleep)
0530 state->cfg->sleep(fe, 0);
0531 return 0;
0532 }
0533
0534 static int dib0070_sleep(struct dvb_frontend *fe)
0535 {
0536 struct dib0070_state *state = fe->tuner_priv;
0537 if (state->cfg->sleep)
0538 state->cfg->sleep(fe, 1);
0539 return 0;
0540 }
0541
0542 u8 dib0070_get_rf_output(struct dvb_frontend *fe)
0543 {
0544 struct dib0070_state *state = fe->tuner_priv;
0545 return (dib0070_read_reg(state, 0x07) >> 11) & 0x3;
0546 }
0547 EXPORT_SYMBOL(dib0070_get_rf_output);
0548
0549 int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no)
0550 {
0551 struct dib0070_state *state = fe->tuner_priv;
0552 u16 rxrf2 = dib0070_read_reg(state, 0x07) & 0xfe7ff;
0553 if (no > 3)
0554 no = 3;
0555 if (no < 1)
0556 no = 1;
0557 return dib0070_write_reg(state, 0x07, rxrf2 | (no << 11));
0558 }
0559 EXPORT_SYMBOL(dib0070_set_rf_output);
0560
0561 static const u16 dib0070_p1f_defaults[] =
0562
0563 {
0564 7, 0x02,
0565 0x0008,
0566 0x0000,
0567 0x0000,
0568 0x0000,
0569 0x0000,
0570 0x0002,
0571 0x0100,
0572
0573 3, 0x0d,
0574 0x0d80,
0575 0x0001,
0576 0x0000,
0577
0578 4, 0x11,
0579 0x0000,
0580 0x0103,
0581 0x0000,
0582 0x0000,
0583
0584 3, 0x16,
0585 0x0004 | 0x0040,
0586 0x0030,
0587 0x07ff,
0588
0589 6, 0x1b,
0590 0x4112,
0591 0xff00,
0592 0xc07f,
0593 0x0000,
0594 0x0180,
0595 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001,
0596
0597 0,
0598 };
0599
0600 static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain)
0601 {
0602 u16 tuner_en = dib0070_read_reg(state, 0x20);
0603 u16 offset;
0604
0605 dib0070_write_reg(state, 0x18, 0x07ff);
0606 dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001);
0607 dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0));
0608 msleep(9);
0609 offset = dib0070_read_reg(state, 0x19);
0610 dib0070_write_reg(state, 0x20, tuner_en);
0611 return offset;
0612 }
0613
0614 static void dib0070_wbd_offset_calibration(struct dib0070_state *state)
0615 {
0616 u8 gain;
0617 for (gain = 6; gain < 8; gain++) {
0618 state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2);
0619 dprintk("Gain: %d, WBDOffset (3.3V) = %hd\n", gain, state->wbd_offset_3_3[gain-6]);
0620 }
0621 }
0622
0623 u16 dib0070_wbd_offset(struct dvb_frontend *fe)
0624 {
0625 struct dib0070_state *state = fe->tuner_priv;
0626 const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain;
0627 u32 freq = fe->dtv_property_cache.frequency/1000;
0628
0629 if (tmp != NULL) {
0630 while (freq/1000 > tmp->freq)
0631 tmp++;
0632 state->wbd_gain_current = tmp->wbd_gain_val;
0633 } else
0634 state->wbd_gain_current = 6;
0635
0636 return state->wbd_offset_3_3[state->wbd_gain_current - 6];
0637 }
0638 EXPORT_SYMBOL(dib0070_wbd_offset);
0639
0640 #define pgm_read_word(w) (*w)
0641 static int dib0070_reset(struct dvb_frontend *fe)
0642 {
0643 struct dib0070_state *state = fe->tuner_priv;
0644 u16 l, r, *n;
0645
0646 HARD_RESET(state);
0647
0648
0649 #ifndef FORCE_SBAND_TUNER
0650 if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1)
0651 state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff;
0652 else
0653 #else
0654 #warning forcing SBAND
0655 #endif
0656 state->revision = DIB0070S_P1A;
0657
0658
0659 dprintk("Revision: %x\n", state->revision);
0660
0661 if (state->revision == DIB0070_P1D) {
0662 dprintk("Error: this driver is not to be used meant for P1D or earlier\n");
0663 return -EINVAL;
0664 }
0665
0666 n = (u16 *) dib0070_p1f_defaults;
0667 l = pgm_read_word(n++);
0668 while (l) {
0669 r = pgm_read_word(n++);
0670 do {
0671 dib0070_write_reg(state, (u8)r, pgm_read_word(n++));
0672 r++;
0673 } while (--l);
0674 l = pgm_read_word(n++);
0675 }
0676
0677 if (state->cfg->force_crystal_mode != 0)
0678 r = state->cfg->force_crystal_mode;
0679 else if (state->cfg->clock_khz >= 24000)
0680 r = 1;
0681 else
0682 r = 2;
0683
0684
0685 r |= state->cfg->osc_buffer_state << 3;
0686
0687 dib0070_write_reg(state, 0x10, r);
0688 dib0070_write_reg(state, 0x1f, (1 << 8) | ((state->cfg->clock_pad_drive & 0xf) << 5));
0689
0690 if (state->cfg->invert_iq) {
0691 r = dib0070_read_reg(state, 0x02) & 0xffdf;
0692 dib0070_write_reg(state, 0x02, r | (1 << 5));
0693 }
0694
0695 if (state->revision == DIB0070S_P1A)
0696 dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0);
0697 else
0698 dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump,
0699 state->cfg->enable_third_order_filter);
0700
0701 dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8);
0702
0703 dib0070_wbd_offset_calibration(state);
0704
0705 return 0;
0706 }
0707
0708 static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency)
0709 {
0710 struct dib0070_state *state = fe->tuner_priv;
0711
0712 *frequency = 1000 * state->current_rf;
0713 return 0;
0714 }
0715
0716 static void dib0070_release(struct dvb_frontend *fe)
0717 {
0718 kfree(fe->tuner_priv);
0719 fe->tuner_priv = NULL;
0720 }
0721
0722 static const struct dvb_tuner_ops dib0070_ops = {
0723 .info = {
0724 .name = "DiBcom DiB0070",
0725 .frequency_min_hz = 45 * MHz,
0726 .frequency_max_hz = 860 * MHz,
0727 .frequency_step_hz = 1 * kHz,
0728 },
0729 .release = dib0070_release,
0730
0731 .init = dib0070_wakeup,
0732 .sleep = dib0070_sleep,
0733 .set_params = dib0070_tune,
0734
0735 .get_frequency = dib0070_get_frequency,
0736
0737 };
0738
0739 struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg)
0740 {
0741 struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL);
0742 if (state == NULL)
0743 return NULL;
0744
0745 state->cfg = cfg;
0746 state->i2c = i2c;
0747 state->fe = fe;
0748 mutex_init(&state->i2c_buffer_lock);
0749 fe->tuner_priv = state;
0750
0751 if (dib0070_reset(fe) != 0)
0752 goto free_mem;
0753
0754 pr_info("DiB0070: successfully identified\n");
0755 memcpy(&fe->ops.tuner_ops, &dib0070_ops, sizeof(struct dvb_tuner_ops));
0756
0757 fe->tuner_priv = state;
0758 return fe;
0759
0760 free_mem:
0761 kfree(state);
0762 fe->tuner_priv = NULL;
0763 return NULL;
0764 }
0765 EXPORT_SYMBOL(dib0070_attach);
0766
0767 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
0768 MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
0769 MODULE_LICENSE("GPL");