diff options
Diffstat (limited to 'drivers/media/dvb/frontends/dib8000.c')
-rw-r--r-- | drivers/media/dvb/frontends/dib8000.c | 3560 |
1 files changed, 0 insertions, 3560 deletions
diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c deleted file mode 100644 index 1f3bcb5a1de8..000000000000 --- a/drivers/media/dvb/frontends/dib8000.c +++ /dev/null @@ -1,3560 +0,0 @@ -/* - * Linux-DVB Driver for DiBcom's DiB8000 chip (ISDB-T). - * - * Copyright (C) 2009 DiBcom (http://www.dibcom.fr/) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - */ -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/i2c.h> -#include <linux/mutex.h> - -#include "dvb_math.h" - -#include "dvb_frontend.h" - -#include "dib8000.h" - -#define LAYER_ALL -1 -#define LAYER_A 1 -#define LAYER_B 2 -#define LAYER_C 3 - -#define FE_CALLBACK_TIME_NEVER 0xffffffff -#define MAX_NUMBER_OF_FRONTENDS 6 - -static int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); - -#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB8000: "); printk(args); printk("\n"); } } while (0) - -#define FE_STATUS_TUNE_FAILED 0 - -struct i2c_device { - struct i2c_adapter *adap; - u8 addr; - u8 *i2c_write_buffer; - u8 *i2c_read_buffer; - struct mutex *i2c_buffer_lock; -}; - -struct dib8000_state { - struct dib8000_config cfg; - - struct i2c_device i2c; - - struct dibx000_i2c_master i2c_master; - - u16 wbd_ref; - - u8 current_band; - u32 current_bandwidth; - struct dibx000_agc_config *current_agc; - u32 timf; - u32 timf_default; - - u8 div_force_off:1; - u8 div_state:1; - u16 div_sync_wait; - - u8 agc_state; - u8 differential_constellation; - u8 diversity_onoff; - - s16 ber_monitored_layer; - u16 gpio_dir; - u16 gpio_val; - - u16 revision; - u8 isdbt_cfg_loaded; - enum frontend_tune_state tune_state; - u32 status; - - struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS]; - - /* for the I2C transfer */ - struct i2c_msg msg[2]; - u8 i2c_write_buffer[4]; - u8 i2c_read_buffer[2]; - struct mutex i2c_buffer_lock; - u8 input_mode_mpeg; - - u16 tuner_enable; - struct i2c_adapter dib8096p_tuner_adap; -}; - -enum dib8000_power_mode { - DIB8000_POWER_ALL = 0, - DIB8000_POWER_INTERFACE_ONLY, -}; - -static u16 dib8000_i2c_read16(struct i2c_device *i2c, u16 reg) -{ - u16 ret; - struct i2c_msg msg[2] = { - {.addr = i2c->addr >> 1, .flags = 0, .len = 2}, - {.addr = i2c->addr >> 1, .flags = I2C_M_RD, .len = 2}, - }; - - if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) { - dprintk("could not acquire lock"); - return 0; - } - - msg[0].buf = i2c->i2c_write_buffer; - msg[0].buf[0] = reg >> 8; - msg[0].buf[1] = reg & 0xff; - msg[1].buf = i2c->i2c_read_buffer; - - if (i2c_transfer(i2c->adap, msg, 2) != 2) - dprintk("i2c read error on %d", reg); - - ret = (msg[1].buf[0] << 8) | msg[1].buf[1]; - mutex_unlock(i2c->i2c_buffer_lock); - return ret; -} - -static u16 dib8000_read_word(struct dib8000_state *state, u16 reg) -{ - u16 ret; - - if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { - dprintk("could not acquire lock"); - return 0; - } - - state->i2c_write_buffer[0] = reg >> 8; - state->i2c_write_buffer[1] = reg & 0xff; - - memset(state->msg, 0, 2 * sizeof(struct i2c_msg)); - state->msg[0].addr = state->i2c.addr >> 1; - state->msg[0].flags = 0; - state->msg[0].buf = state->i2c_write_buffer; - state->msg[0].len = 2; - state->msg[1].addr = state->i2c.addr >> 1; - state->msg[1].flags = I2C_M_RD; - state->msg[1].buf = state->i2c_read_buffer; - state->msg[1].len = 2; - - if (i2c_transfer(state->i2c.adap, state->msg, 2) != 2) - dprintk("i2c read error on %d", reg); - - ret = (state->i2c_read_buffer[0] << 8) | state->i2c_read_buffer[1]; - mutex_unlock(&state->i2c_buffer_lock); - - return ret; -} - -static u32 dib8000_read32(struct dib8000_state *state, u16 reg) -{ - u16 rw[2]; - - rw[0] = dib8000_read_word(state, reg + 0); - rw[1] = dib8000_read_word(state, reg + 1); - - return ((rw[0] << 16) | (rw[1])); -} - -static int dib8000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val) -{ - struct i2c_msg msg = {.addr = i2c->addr >> 1, .flags = 0, .len = 4}; - int ret = 0; - - if (mutex_lock_interruptible(i2c->i2c_buffer_lock) < 0) { - dprintk("could not acquire lock"); - return -EINVAL; - } - - msg.buf = i2c->i2c_write_buffer; - msg.buf[0] = (reg >> 8) & 0xff; - msg.buf[1] = reg & 0xff; - msg.buf[2] = (val >> 8) & 0xff; - msg.buf[3] = val & 0xff; - - ret = i2c_transfer(i2c->adap, &msg, 1) != 1 ? -EREMOTEIO : 0; - mutex_unlock(i2c->i2c_buffer_lock); - - return ret; -} - -static int dib8000_write_word(struct dib8000_state *state, u16 reg, u16 val) -{ - int ret; - - if (mutex_lock_interruptible(&state->i2c_buffer_lock) < 0) { - dprintk("could not acquire lock"); - return -EINVAL; - } - - state->i2c_write_buffer[0] = (reg >> 8) & 0xff; - state->i2c_write_buffer[1] = reg & 0xff; - state->i2c_write_buffer[2] = (val >> 8) & 0xff; - state->i2c_write_buffer[3] = val & 0xff; - - memset(&state->msg[0], 0, sizeof(struct i2c_msg)); - state->msg[0].addr = state->i2c.addr >> 1; - state->msg[0].flags = 0; - state->msg[0].buf = state->i2c_write_buffer; - state->msg[0].len = 4; - - ret = (i2c_transfer(state->i2c.adap, state->msg, 1) != 1 ? - -EREMOTEIO : 0); - mutex_unlock(&state->i2c_buffer_lock); - - return ret; -} - -static const s16 coeff_2k_sb_1seg_dqpsk[8] = { - (769 << 5) | 0x0a, (745 << 5) | 0x03, (595 << 5) | 0x0d, (769 << 5) | 0x0a, (920 << 5) | 0x09, (784 << 5) | 0x02, (519 << 5) | 0x0c, - (920 << 5) | 0x09 -}; - -static const s16 coeff_2k_sb_1seg[8] = { - (692 << 5) | 0x0b, (683 << 5) | 0x01, (519 << 5) | 0x09, (692 << 5) | 0x0b, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f -}; - -static const s16 coeff_2k_sb_3seg_0dqpsk_1dqpsk[8] = { - (832 << 5) | 0x10, (912 << 5) | 0x05, (900 << 5) | 0x12, (832 << 5) | 0x10, (-931 << 5) | 0x0f, (912 << 5) | 0x04, (807 << 5) | 0x11, - (-931 << 5) | 0x0f -}; - -static const s16 coeff_2k_sb_3seg_0dqpsk[8] = { - (622 << 5) | 0x0c, (941 << 5) | 0x04, (796 << 5) | 0x10, (622 << 5) | 0x0c, (982 << 5) | 0x0c, (519 << 5) | 0x02, (572 << 5) | 0x0e, - (982 << 5) | 0x0c -}; - -static const s16 coeff_2k_sb_3seg_1dqpsk[8] = { - (699 << 5) | 0x14, (607 << 5) | 0x04, (944 << 5) | 0x13, (699 << 5) | 0x14, (-720 << 5) | 0x0d, (640 << 5) | 0x03, (866 << 5) | 0x12, - (-720 << 5) | 0x0d -}; - -static const s16 coeff_2k_sb_3seg[8] = { - (664 << 5) | 0x0c, (925 << 5) | 0x03, (937 << 5) | 0x10, (664 << 5) | 0x0c, (-610 << 5) | 0x0a, (697 << 5) | 0x01, (836 << 5) | 0x0e, - (-610 << 5) | 0x0a -}; - -static const s16 coeff_4k_sb_1seg_dqpsk[8] = { - (-955 << 5) | 0x0e, (687 << 5) | 0x04, (818 << 5) | 0x10, (-955 << 5) | 0x0e, (-922 << 5) | 0x0d, (750 << 5) | 0x03, (665 << 5) | 0x0f, - (-922 << 5) | 0x0d -}; - -static const s16 coeff_4k_sb_1seg[8] = { - (638 << 5) | 0x0d, (683 << 5) | 0x02, (638 << 5) | 0x0d, (638 << 5) | 0x0d, (-655 << 5) | 0x0a, (517 << 5) | 0x00, (698 << 5) | 0x0d, - (-655 << 5) | 0x0a -}; - -static const s16 coeff_4k_sb_3seg_0dqpsk_1dqpsk[8] = { - (-707 << 5) | 0x14, (910 << 5) | 0x06, (889 << 5) | 0x16, (-707 << 5) | 0x14, (-958 << 5) | 0x13, (993 << 5) | 0x05, (523 << 5) | 0x14, - (-958 << 5) | 0x13 -}; - -static const s16 coeff_4k_sb_3seg_0dqpsk[8] = { - (-723 << 5) | 0x13, (910 << 5) | 0x05, (777 << 5) | 0x14, (-723 << 5) | 0x13, (-568 << 5) | 0x0f, (547 << 5) | 0x03, (696 << 5) | 0x12, - (-568 << 5) | 0x0f -}; - -static const s16 coeff_4k_sb_3seg_1dqpsk[8] = { - (-940 << 5) | 0x15, (607 << 5) | 0x05, (915 << 5) | 0x16, (-940 << 5) | 0x15, (-848 << 5) | 0x13, (683 << 5) | 0x04, (543 << 5) | 0x14, - (-848 << 5) | 0x13 -}; - -static const s16 coeff_4k_sb_3seg[8] = { - (612 << 5) | 0x12, (910 << 5) | 0x04, (864 << 5) | 0x14, (612 << 5) | 0x12, (-869 << 5) | 0x13, (683 << 5) | 0x02, (869 << 5) | 0x12, - (-869 << 5) | 0x13 -}; - -static const s16 coeff_8k_sb_1seg_dqpsk[8] = { - (-835 << 5) | 0x12, (684 << 5) | 0x05, (735 << 5) | 0x14, (-835 << 5) | 0x12, (-598 << 5) | 0x10, (781 << 5) | 0x04, (739 << 5) | 0x13, - (-598 << 5) | 0x10 -}; - -static const s16 coeff_8k_sb_1seg[8] = { - (673 << 5) | 0x0f, (683 << 5) | 0x03, (808 << 5) | 0x12, (673 << 5) | 0x0f, (585 << 5) | 0x0f, (512 << 5) | 0x01, (780 << 5) | 0x0f, - (585 << 5) | 0x0f -}; - -static const s16 coeff_8k_sb_3seg_0dqpsk_1dqpsk[8] = { - (863 << 5) | 0x17, (930 << 5) | 0x07, (878 << 5) | 0x19, (863 << 5) | 0x17, (0 << 5) | 0x14, (521 << 5) | 0x05, (980 << 5) | 0x18, - (0 << 5) | 0x14 -}; - -static const s16 coeff_8k_sb_3seg_0dqpsk[8] = { - (-924 << 5) | 0x17, (910 << 5) | 0x06, (774 << 5) | 0x17, (-924 << 5) | 0x17, (-877 << 5) | 0x15, (565 << 5) | 0x04, (553 << 5) | 0x15, - (-877 << 5) | 0x15 -}; - -static const s16 coeff_8k_sb_3seg_1dqpsk[8] = { - (-921 << 5) | 0x19, (607 << 5) | 0x06, (881 << 5) | 0x19, (-921 << 5) | 0x19, (-921 << 5) | 0x14, (713 << 5) | 0x05, (1018 << 5) | 0x18, - (-921 << 5) | 0x14 -}; - -static const s16 coeff_8k_sb_3seg[8] = { - (514 << 5) | 0x14, (910 << 5) | 0x05, (861 << 5) | 0x17, (514 << 5) | 0x14, (690 << 5) | 0x14, (683 << 5) | 0x03, (662 << 5) | 0x15, - (690 << 5) | 0x14 -}; - -static const s16 ana_fe_coeff_3seg[24] = { - 81, 80, 78, 74, 68, 61, 54, 45, 37, 28, 19, 11, 4, 1022, 1017, 1013, 1010, 1008, 1008, 1008, 1008, 1010, 1014, 1017 -}; - -static const s16 ana_fe_coeff_1seg[24] = { - 249, 226, 164, 82, 5, 981, 970, 988, 1018, 20, 31, 26, 8, 1012, 1000, 1018, 1012, 8, 15, 14, 9, 3, 1017, 1003 -}; - -static const s16 ana_fe_coeff_13seg[24] = { - 396, 305, 105, -51, -77, -12, 41, 31, -11, -30, -11, 14, 15, -2, -13, -7, 5, 8, 1, -6, -7, -3, 0, 1 -}; - -static u16 fft_to_mode(struct dib8000_state *state) -{ - u16 mode; - switch (state->fe[0]->dtv_property_cache.transmission_mode) { - case TRANSMISSION_MODE_2K: - mode = 1; - break; - case TRANSMISSION_MODE_4K: - mode = 2; - break; - default: - case TRANSMISSION_MODE_AUTO: - case TRANSMISSION_MODE_8K: - mode = 3; - break; - } - return mode; -} - -static void dib8000_set_acquisition_mode(struct dib8000_state *state) -{ - u16 nud = dib8000_read_word(state, 298); - nud |= (1 << 3) | (1 << 0); - dprintk("acquisition mode activated"); - dib8000_write_word(state, 298, nud); -} -static int dib8000_set_output_mode(struct dvb_frontend *fe, int mode) -{ - struct dib8000_state *state = fe->demodulator_priv; - - u16 outreg, fifo_threshold, smo_mode, sram = 0x0205; /* by default SDRAM deintlv is enabled */ - - outreg = 0; - fifo_threshold = 1792; - smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1); - - dprintk("-I- Setting output mode for demod %p to %d", - &state->fe[0], mode); - - switch (mode) { - case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock - outreg = (1 << 10); /* 0x0400 */ - break; - case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock - outreg = (1 << 10) | (1 << 6); /* 0x0440 */ - break; - case OUTMODE_MPEG2_SERIAL: // STBs with serial input - outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */ - break; - case OUTMODE_DIVERSITY: - if (state->cfg.hostbus_diversity) { - outreg = (1 << 10) | (4 << 6); /* 0x0500 */ - sram &= 0xfdff; - } else - sram |= 0x0c00; - break; - case OUTMODE_MPEG2_FIFO: // e.g. USB feeding - smo_mode |= (3 << 1); - fifo_threshold = 512; - outreg = (1 << 10) | (5 << 6); - break; - case OUTMODE_HIGH_Z: // disable - outreg = 0; - break; - - case OUTMODE_ANALOG_ADC: - outreg = (1 << 10) | (3 << 6); - dib8000_set_acquisition_mode(state); - break; - - default: - dprintk("Unhandled output_mode passed to be set for demod %p", - &state->fe[0]); - return -EINVAL; - } - - if (state->cfg.output_mpeg2_in_188_bytes) - smo_mode |= (1 << 5); - - dib8000_write_word(state, 299, smo_mode); - dib8000_write_word(state, 300, fifo_threshold); /* synchronous fread */ - dib8000_write_word(state, 1286, outreg); - dib8000_write_word(state, 1291, sram); - - return 0; -} - -static int dib8000_set_diversity_in(struct dvb_frontend *fe, int onoff) -{ - struct dib8000_state *state = fe->demodulator_priv; - u16 sync_wait = dib8000_read_word(state, 273) & 0xfff0; - - if (!state->differential_constellation) { - dib8000_write_word(state, 272, 1 << 9); //dvsy_off_lmod4 = 1 - dib8000_write_word(state, 273, sync_wait | (1 << 2) | 2); // sync_enable = 1; comb_mode = 2 - } else { - dib8000_write_word(state, 272, 0); //dvsy_off_lmod4 = 0 - dib8000_write_word(state, 273, sync_wait); // sync_enable = 0; comb_mode = 0 - } - state->diversity_onoff = onoff; - - switch (onoff) { - case 0: /* only use the internal way - not the diversity input */ - dib8000_write_word(state, 270, 1); - dib8000_write_word(state, 271, 0); - break; - case 1: /* both ways */ - dib8000_write_word(state, 270, 6); - dib8000_write_word(state, 271, 6); - break; - case 2: /* only the diversity input */ - dib8000_write_word(state, 270, 0); - dib8000_write_word(state, 271, 1); - break; - } - return 0; -} - -static void dib8000_set_power_mode(struct dib8000_state *state, enum dib8000_power_mode mode) -{ - /* by default everything is going to be powered off */ - u16 reg_774 = 0x3fff, reg_775 = 0xffff, reg_776 = 0xffff, - reg_900 = (dib8000_read_word(state, 900) & 0xfffc) | 0x3, - reg_1280; - - if (state->revision != 0x8090) - reg_1280 = (dib8000_read_word(state, 1280) & 0x00ff) | 0xff00; - else - reg_1280 = (dib8000_read_word(state, 1280) & 0x707f) | 0x8f80; - - /* now, depending on the requested mode, we power on */ - switch (mode) { - /* power up everything in the demod */ - case DIB8000_POWER_ALL: - reg_774 = 0x0000; - reg_775 = 0x0000; - reg_776 = 0x0000; - reg_900 &= 0xfffc; - if (state->revision != 0x8090) - reg_1280 &= 0x00ff; - else - reg_1280 &= 0x707f; - break; - case DIB8000_POWER_INTERFACE_ONLY: - if (state->revision != 0x8090) - reg_1280 &= 0x00ff; - else - reg_1280 &= 0xfa7b; - break; - } - - dprintk("powermode : 774 : %x ; 775 : %x; 776 : %x ; 900 : %x; 1280 : %x", reg_774, reg_775, reg_776, reg_900, reg_1280); - dib8000_write_word(state, 774, reg_774); - dib8000_write_word(state, 775, reg_775); - dib8000_write_word(state, 776, reg_776); - dib8000_write_word(state, 900, reg_900); - dib8000_write_word(state, 1280, reg_1280); -} - -static int dib8000_init_sdram(struct dib8000_state *state) -{ - u16 reg = 0; - dprintk("Init sdram"); - - reg = dib8000_read_word(state, 274)&0xfff0; - /* P_dintlv_delay_ram = 7 because of MobileSdram */ - dib8000_write_word(state, 274, reg | 0x7); - - dib8000_write_word(state, 1803, (7<<2)); - - reg = dib8000_read_word(state, 1280); - /* force restart P_restart_sdram */ - dib8000_write_word(state, 1280, reg | (1<<2)); - - /* release restart P_restart_sdram */ - dib8000_write_word(state, 1280, reg); - - return 0; -} - -static int dib8000_set_adc_state(struct dib8000_state *state, enum dibx000_adc_states no) -{ - int ret = 0; - u16 reg, reg_907 = dib8000_read_word(state, 907); - u16 reg_908 = dib8000_read_word(state, 908); - - switch (no) { - case DIBX000_SLOW_ADC_ON: - if (state->revision != 0x8090) { - reg_908 |= (1 << 1) | (1 << 0); - ret |= dib8000_write_word(state, 908, reg_908); - reg_908 &= ~(1 << 1); - } else { - reg = dib8000_read_word(state, 1925); - /* en_slowAdc = 1 & reset_sladc = 1 */ - dib8000_write_word(state, 1925, reg | - (1<<4) | (1<<2)); - - /* read acces to make it works... strange ... */ - reg = dib8000_read_word(state, 1925); - msleep(20); - /* en_slowAdc = 1 & reset_sladc = 0 */ - dib8000_write_word(state, 1925, reg & ~(1<<4)); - - reg = dib8000_read_word(state, 921) & ~((0x3 << 14) - | (0x3 << 12)); - /* ref = Vin1 => Vbg ; sel = Vin0 or Vin3 ; - (Vin2 = Vcm) */ - dib8000_write_word(state, 921, reg | (1 << 14) - | (3 << 12)); - } - break; - - case DIBX000_SLOW_ADC_OFF: - if (state->revision == 0x8090) { - reg = dib8000_read_word(state, 1925); - /* reset_sladc = 1 en_slowAdc = 0 */ - dib8000_write_word(state, 1925, - (reg & ~(1<<2)) | (1<<4)); - } - reg_908 |= (1 << 1) | (1 << 0); - break; - - case DIBX000_ADC_ON: - reg_907 &= 0x0fff; - reg_908 &= 0x0003; - break; - - case DIBX000_ADC_OFF: // leave the VBG voltage on - reg_907 |= (1 << 14) | (1 << 13) | (1 << 12); - reg_908 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2); - break; - - case DIBX000_VBG_ENABLE: - reg_907 &= ~(1 << 15); - break; - - case DIBX000_VBG_DISABLE: - reg_907 |= (1 << 15); - break; - - default: - break; - } - - ret |= dib8000_write_word(state, 907, reg_907); - ret |= dib8000_write_word(state, 908, reg_908); - - return ret; -} - -static int dib8000_set_bandwidth(struct dvb_frontend *fe, u32 bw) -{ - struct dib8000_state *state = fe->demodulator_priv; - u32 timf; - - if (bw == 0) - bw = 6000; - - if (state->timf == 0) { - dprintk("using default timf"); - timf = state->timf_default; - } else { - dprintk("using updated timf"); - timf = state->timf; - } - - dib8000_write_word(state, 29, (u16) ((timf >> 16) & 0xffff)); - dib8000_write_word(state, 30, (u16) ((timf) & 0xffff)); - - return 0; -} - -static int dib8000_sad_calib(struct dib8000_state *state) -{ - if (state->revision == 0x8090) { - dprintk("%s: the sad calibration is not needed for the dib8096P", - __func__); - return 0; - } - /* internal */ - dib8000_write_word(state, 923, (0 << 1) | (0 << 0)); - dib8000_write_word(state, 924, 776); // 0.625*3.3 / 4096 - - /* do the calibration */ - dib8000_write_word(state, 923, (1 << 0)); - dib8000_write_word(state, 923, (0 << 0)); - - msleep(1); - return 0; -} - -int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value) -{ - struct dib8000_state *state = fe->demodulator_priv; - if (value > 4095) - value = 4095; - state->wbd_ref = value; - return dib8000_write_word(state, 106, value); -} - -EXPORT_SYMBOL(dib8000_set_wbd_ref); -static void dib8000_reset_pll_common(struct dib8000_state *state, const struct dibx000_bandwidth_config *bw) -{ - dprintk("ifreq: %d %x, inversion: %d", bw->ifreq, bw->ifreq, bw->ifreq >> 25); - if (state->revision != 0x8090) { - dib8000_write_word(state, 23, - (u16) (((bw->internal * 1000) >> 16) & 0xffff)); - dib8000_write_word(state, 24, - (u16) ((bw->internal * 1000) & 0xffff)); - } else { - dib8000_write_word(state, 23, (u16) (((bw->internal / 2 * 1000) >> 16) & 0xffff)); - dib8000_write_word(state, 24, - (u16) ((bw->internal / 2 * 1000) & 0xffff)); - } - dib8000_write_word(state, 27, (u16) ((bw->ifreq >> 16) & 0x01ff)); - dib8000_write_word(state, 28, (u16) (bw->ifreq & 0xffff)); - dib8000_write_word(state, 26, (u16) ((bw->ifreq >> 25) & 0x0003)); - - if (state->revision != 0x8090) - dib8000_write_word(state, 922, bw->sad_cfg); -} - -static void dib8000_reset_pll(struct dib8000_state *state) -{ - const struct dibx000_bandwidth_config *pll = state->cfg.pll; - u16 clk_cfg1, reg; - - if (state->revision != 0x8090) { - dib8000_write_word(state, 901, - (pll->pll_prediv << 8) | (pll->pll_ratio << 0)); - - clk_cfg1 = (1 << 10) | (0 << 9) | (pll->IO_CLK_en_core << 8) | - (pll->bypclk_div << 5) | (pll->enable_refdiv << 4) | - (1 << 3) | (pll->pll_range << 1) | - (pll->pll_reset << 0); - - dib8000_write_word(state, 902, clk_cfg1); - clk_cfg1 = (clk_cfg1 & 0xfff7) | (pll->pll_bypass << 3); - dib8000_write_word(state, 902, clk_cfg1); - - dprintk("clk_cfg1: 0x%04x", clk_cfg1); - - /* smpl_cfg: P_refclksel=2, P_ensmplsel=1 nodivsmpl=1 */ - if (state->cfg.pll->ADClkSrc == 0) - dib8000_write_word(state, 904, - (0 << 15) | (0 << 12) | (0 << 10) | - (pll->modulo << 8) | - (pll->ADClkSrc << 7) | (0 << 1)); - else if (state->cfg.refclksel != 0) - dib8000_write_word(state, 904, (0 << 15) | (1 << 12) | - ((state->cfg.refclksel & 0x3) << 10) | - (pll->modulo << 8) | - (pll->ADClkSrc << 7) | (0 << 1)); - else - dib8000_write_word(state, 904, (0 << 15) | (1 << 12) | - (3 << 10) | (pll->modulo << 8) | - (pll->ADClkSrc << 7) | (0 << 1)); - } else { - dib8000_write_word(state, 1856, (!pll->pll_reset<<13) | - (pll->pll_range<<12) | (pll->pll_ratio<<6) | - (pll->pll_prediv)); - - reg = dib8000_read_word(state, 1857); - dib8000_write_word(state, 1857, reg|(!pll->pll_bypass<<15)); - - reg = dib8000_read_word(state, 1858); /* Force clk out pll /2 */ - dib8000_write_word(state, 1858, reg | 1); - - dib8000_write_word(state, 904, (pll->modulo << 8)); - } - - dib8000_reset_pll_common(state, pll); -} - -int dib8000_update_pll(struct dvb_frontend *fe, - struct dibx000_bandwidth_config *pll) -{ - struct dib8000_state *state = fe->demodulator_priv; - u16 reg_1857, reg_1856 = dib8000_read_word(state, 1856); - u8 loopdiv, prediv; - u32 internal, xtal; - - /* get back old values */ - prediv = reg_1856 & 0x3f; - loopdiv = (reg_1856 >> 6) & 0x3f; - - if ((pll != NULL) && (pll->pll_prediv != prediv || - pll->pll_ratio != loopdiv)) { - dprintk("Updating pll (prediv: old = %d new = %d ; loopdiv : old = %d new = %d)", prediv, pll->pll_prediv, loopdiv, pll->pll_ratio); - reg_1856 &= 0xf000; - reg_1857 = dib8000_read_word(state, 1857); - /* disable PLL */ - dib8000_write_word(state, 1857, reg_1857 & ~(1 << 15)); - - dib8000_write_word(state, 1856, reg_1856 | - ((pll->pll_ratio & 0x3f) << 6) | - (pll->pll_prediv & 0x3f)); - - /* write new system clk into P_sec_len */ - internal = dib8000_read32(state, 23) / 1000; - dprintk("Old Internal = %d", internal); - xtal = 2 * (internal / loopdiv) * prediv; - internal = 1000 * (xtal/pll->pll_prediv) * pll->pll_ratio; - dprintk("Xtal = %d , New Fmem = %d New Fdemod = %d, New Fsampling = %d", xtal, internal/1000, internal/2000, internal/8000); - dprintk("New Internal = %d", internal); - - dib8000_write_word(state, 23, - (u16) (((internal / 2) >> 16) & 0xffff)); - dib8000_write_word(state, 24, (u16) ((internal / 2) & 0xffff)); - /* enable PLL */ - dib8000_write_word(state, 1857, reg_1857 | (1 << 15)); - - while (((dib8000_read_word(state, 1856)>>15)&0x1) != 1) - dprintk("Waiting for PLL to lock"); - - /* verify */ - reg_1856 = dib8000_read_word(state, 1856); - dprintk("PLL Updated with prediv = %d and loopdiv = %d", - reg_1856&0x3f, (reg_1856>>6)&0x3f); - - return 0; - } - return -EINVAL; -} -EXPORT_SYMBOL(dib8000_update_pll); - - -static int dib8000_reset_gpio(struct dib8000_state *st) -{ - /* reset the GPIOs */ - dib8000_write_word(st, 1029, st->cfg.gpio_dir); - dib8000_write_word(st, 1030, st->cfg.gpio_val); - - /* TODO 782 is P_gpio_od */ - - dib8000_write_word(st, 1032, st->cfg.gpio_pwm_pos); - - dib8000_write_word(st, 1037, st->cfg.pwm_freq_div); - return 0; -} - -static int dib8000_cfg_gpio(struct dib8000_state *st, u8 num, u8 dir, u8 val) -{ - st->cfg.gpio_dir = dib8000_read_word(st, 1029); - st->cfg.gpio_dir &= ~(1 << num); /* reset the direction bit */ - st->cfg.gpio_dir |= (dir & 0x1) << num; /* set the new direction */ - dib8000_write_word(st, 1029, st->cfg.gpio_dir); - - st->cfg.gpio_val = dib8000_read_word(st, 1030); - st->cfg.gpio_val &= ~(1 << num); /* reset the direction bit */ - st->cfg.gpio_val |= (val & 0x01) << num; /* set the new value */ - dib8000_write_word(st, 1030, st->cfg.gpio_val); - - dprintk("gpio dir: %x: gpio val: %x", st->cfg.gpio_dir, st->cfg.gpio_val); - - return 0; -} - -int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val) -{ - struct dib8000_state *state = fe->demodulator_priv; - return dib8000_cfg_gpio(state, num, dir, val); -} - -EXPORT_SYMBOL(dib8000_set_gpio); -static const u16 dib8000_defaults[] = { - /* auto search configuration - lock0 by default waiting - * for cpil_lock; lock1 cpil_lock; lock2 tmcc_sync_lock */ - 3, 7, - 0x0004, - 0x0400, - 0x0814, - - 12, 11, - 0x001b, - 0x7740, - 0x005b, - 0x8d80, - 0x01c9, - 0xc380, - 0x0000, - 0x0080, - 0x0000, - 0x0090, - 0x0001, - 0xd4c0, - - /*1, 32, - 0x6680 // P_corm_thres Lock algorithms configuration */ - - 11, 80, /* set ADC level to -16 */ - (1 << 13) - 825 - 117, - (1 << 13) - 837 - 117, - (1 << 13) - 811 - 117, - (1 << 13) - 766 - 117, - (1 << 13) - 737 - 117, - (1 << 13) - 693 - 117, - (1 << 13) - 648 - 117, - (1 << 13) - 619 - 117, - (1 << 13) - 575 - 117, - (1 << 13) - 531 - 117, - (1 << 13) - 501 - 117, - - 4, 108, - 0, - 0, - 0, - 0, - - 1, 175, - 0x0410, - 1, 179, - 8192, // P_fft_nb_to_cut - - 6, 181, - 0x2800, // P_coff_corthres_ ( 2k 4k 8k ) 0x2800 - 0x2800, - 0x2800, - 0x2800, // P_coff_cpilthres_ ( 2k 4k 8k ) 0x2800 - 0x2800, - 0x2800, - - 2, 193, - 0x0666, // P_pha3_thres - 0x0000, // P_cti_use_cpe, P_cti_use_prog - - 2, 205, - 0x200f, // P_cspu_regul, P_cspu_win_cut - 0x000f, // P_des_shift_work - - 5, 215, - 0x023d, // P_adp_regul_cnt - 0x00a4, // P_adp_noise_cnt - 0x00a4, // P_adp_regul_ext - 0x7ff0, // P_adp_noise_ext - 0x3ccc, // P_adp_fil - - 1, 230, - 0x0000, // P_2d_byp_ti_num - - 1, 263, - 0x800, //P_equal_thres_wgn - - 1, 268, - (2 << 9) | 39, // P_equal_ctrl_synchro, P_equal_speedmode - - 1, 270, - 0x0001, // P_div_lock0_wait - 1, 285, - 0x0020, //p_fec_ - 1, 299, - 0x0062, /* P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard */ - - 1, 338, - (1 << 12) | // P_ctrl_corm_thres4pre_freq_inh=1 - (1 << 10) | - (0 << 9) | /* P_ctrl_pre_freq_inh=0 */ - (3 << 5) | /* P_ctrl_pre_freq_step=3 */ - (1 << 0), /* P_pre_freq_win_len=1 */ - - 0, -}; - -static u16 dib8000_identify(struct i2c_device *client) -{ - u16 value; - - //because of glitches sometimes - value = dib8000_i2c_read16(client, 896); - - if ((value = dib8000_i2c_read16(client, 896)) != 0x01b3) { - dprintk("wrong Vendor ID (read=0x%x)", value); - return 0; - } - - value = dib8000_i2c_read16(client, 897); - if (value != 0x8000 && value != 0x8001 && - value != 0x8002 && value != 0x8090) { - dprintk("wrong Device ID (%x)", value); - return 0; - } - - switch (value) { - case 0x8000: - dprintk("found DiB8000A"); - break; - case 0x8001: - dprintk("found DiB8000B"); - break; - case 0x8002: - dprintk("found DiB8000C"); - break; - case 0x8090: - dprintk("found DiB8096P"); - break; - } - return value; -} - -static int dib8000_reset(struct dvb_frontend *fe) -{ - struct dib8000_state *state = fe->demodulator_priv; - - if ((state->revision = dib8000_identify(&state->i2c)) == 0) - return -EINVAL; - - /* sram lead in, rdy */ - if (state->revision != 0x8090) - dib8000_write_word(state, 1287, 0x0003); - - if (state->revision == 0x8000) - dprintk("error : dib8000 MA not supported"); - - dibx000_reset_i2c_master(&state->i2c_master); - - dib8000_set_power_mode(state, DIB8000_POWER_ALL); - - /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */ - dib8000_set_adc_state(state, DIBX000_VBG_ENABLE); - - /* restart all parts */ - dib8000_write_word(state, 770, 0xffff); - dib8000_write_word(state, 771, 0xffff); - dib8000_write_word(state, 772, 0xfffc); - if (state->revision == 0x8090) - dib8000_write_word(state, 1280, 0x0045); - else - dib8000_write_word(state, 1280, 0x004d); - dib8000_write_word(state, 1281, 0x000c); - - dib8000_write_word(state, 770, 0x0000); - dib8000_write_word(state, 771, 0x0000); - dib8000_write_word(state, 772, 0x0000); - dib8000_write_word(state, 898, 0x0004); // sad - dib8000_write_word(state, 1280, 0x0000); - dib8000_write_word(state, 1281, 0x0000); - - /* drives */ - if (state->revision != 0x8090) { - if (state->cfg.drives) - dib8000_write_word(state, 906, state->cfg.drives); - else { - dprintk("using standard PAD-drive-settings, please adjust settings in config-struct to be optimal."); - /* min drive SDRAM - not optimal - adjust */ - dib8000_write_word(state, 906, 0x2d98); - } - } - - dib8000_reset_pll(state); - if (state->revision != 0x8090) - dib8000_write_word(state, 898, 0x0004); - - if (dib8000_reset_gpio(state) != 0) - dprintk("GPIO reset was not successful."); - - if ((state->revision != 0x8090) && - (dib8000_set_output_mode(fe, OUTMODE_HIGH_Z) != 0)) - dprintk("OUTPUT_MODE could not be resetted."); - - state->current_agc = NULL; - - // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ... - /* P_iqc_ca2 = 0; P_iqc_impnc_on = 0; P_iqc_mode = 0; */ - if (state->cfg.pll->ifreq == 0) - dib8000_write_word(state, 40, 0x0755); /* P_iqc_corr_inh = 0 enable IQcorr block */ - else - dib8000_write_word(state, 40, 0x1f55); /* P_iqc_corr_inh = 1 disable IQcorr block */ - - { - u16 l = 0, r; - const u16 *n; - n = dib8000_defaults; - l = *n++; - while (l) { - r = *n++; - do { - dib8000_write_word(state, r, *n++); - r++; - } while (--l); - l = *n++; - } - } - if (state->revision != 0x8090) - dib8000_write_word(state, 903, (0 << 4) | 2); - state->isdbt_cfg_loaded = 0; - - //div_cfg override for special configs - if (state->cfg.div_cfg != 0) - dib8000_write_word(state, 903, state->cfg.div_cfg); - - /* unforce divstr regardless whether i2c enumeration was done or not */ - dib8000_write_word(state, 1285, dib8000_read_word(state, 1285) & ~(1 << 1)); - - dib8000_set_bandwidth(fe, 6000); - - dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON); - if (state->revision != 0x8090) { - dib8000_sad_calib(state); - dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF); - } - - dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY); - - return 0; -} - -static void dib8000_restart_agc(struct dib8000_state *state) -{ - // P_restart_iqc & P_restart_agc - dib8000_write_word(state, 770, 0x0a00); - dib8000_write_word(state, 770, 0x0000); -} - -static int dib8000_update_lna(struct dib8000_state *state) -{ - u16 dyn_gain; - - if (state->cfg.update_lna) { - // read dyn_gain here (because it is demod-dependent and not tuner) - dyn_gain = dib8000_read_word(state, 390); - - if (state->cfg.update_lna(state->fe[0], dyn_gain)) { - dib8000_restart_agc(state); - return 1; - } - } - return 0; -} - -static int dib8000_set_agc_config(struct dib8000_state *state, u8 band) -{ - struct dibx000_agc_config *agc = NULL; - int i; - u16 reg; - - if (state->current_band == band && state->current_agc != NULL) - return 0; - state->current_band = band; - - for (i = 0; i < state->cfg.agc_config_count; i++) - if (state->cfg.agc[i].band_caps & band) { - agc = &state->cfg.agc[i]; - break; - } - - if (agc == NULL) { - dprintk("no valid AGC configuration found for band 0x%02x", band); - return -EINVAL; - } - - state->current_agc = agc; - - /* AGC */ - dib8000_write_word(state, 76, agc->setup); - dib8000_write_word(state, 77, agc->inv_gain); - dib8000_write_word(state, 78, agc->time_stabiliz); - dib8000_write_word(state, 101, (agc->alpha_level << 12) | agc->thlock); - - // Demod AGC loop configuration - dib8000_write_word(state, 102, (agc->alpha_mant << 5) | agc->alpha_exp); - dib8000_write_word(state, 103, (agc->beta_mant << 6) | agc->beta_exp); - - dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d", - state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); - - /* AGC continued */ - if (state->wbd_ref != 0) - dib8000_write_word(state, 106, state->wbd_ref); - else // use default - dib8000_write_word(state, 106, agc->wbd_ref); - - if (state->revision == 0x8090) { - reg = dib8000_read_word(state, 922) & (0x3 << 2); - dib8000_write_word(state, 922, reg | (agc->wbd_sel << 2)); - } - - dib8000_write_word(state, 107, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8)); - dib8000_write_word(state, 108, agc->agc1_max); - dib8000_write_word(state, 109, agc->agc1_min); - dib8000_write_word(state, 110, agc->agc2_max); - dib8000_write_word(state, 111, agc->agc2_min); - dib8000_write_word(state, 112, (agc->agc1_pt1 << 8) | agc->agc1_pt2); - dib8000_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2); - dib8000_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2); - dib8000_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2); - - dib8000_write_word(state, 75, agc->agc1_pt3); - if (state->revision != 0x8090) - dib8000_write_word(state, 923, - (dib8000_read_word(state, 923) & 0xffe3) | - (agc->wbd_inv << 4) | (agc->wbd_sel << 2)); - - return 0; -} - -void dib8000_pwm_agc_reset(struct dvb_frontend *fe) -{ - struct dib8000_state *state = fe->demodulator_priv; - dib8000_set_adc_state(state, DIBX000_ADC_ON); - dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000))); -} -EXPORT_SYMBOL(dib8000_pwm_agc_reset); - -static int dib8000_agc_soft_split(struct dib8000_state *state) -{ - u16 agc, split_offset; - - if (!state->current_agc || !state->curre |