summaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/frontends/dib8000.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/frontends/dib8000.c')
-rw-r--r--drivers/media/dvb/frontends/dib8000.c3560
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