diff options
author | Patrick Boettcher <pboettcher@dibcom.fr> | 2006-10-17 17:28:14 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-12-10 05:51:00 -0500 |
commit | 69ea31e7debdefcf1412e8d590ae9bd90cf9253f (patch) | |
tree | 7c50602aed2953c92ce8b636d0e8141febb52ef5 /drivers/media/dvb | |
parent | 3cc2e4c3a137075ee66e2d4ce95a95ba153bd7b9 (diff) |
V4L/DVB (4766): Add working dib7000m-module
First working version of the dib7000m-driver.
This commit also makes the Hauppauge NOVA-T Stick working.
Signed-off-by: Francois Kanounnikoff <fkanounnikoff@dibcom.fr>
Signed-off-by: Patrick Boettcher <pboettcher@dibcom.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r-- | drivers/media/dvb/dvb-usb/dib0700_devices.c | 95 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/dvb-usb-ids.h | 1 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/Kconfig | 8 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/dib7000m.c | 976 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/dib7000m.h | 5 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/dibx000_common.c | 2 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/dibx000_common.h | 13 |
8 files changed, 1073 insertions, 28 deletions
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index b4e339df72e5..305dd35a1021 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c | |||
@@ -96,29 +96,97 @@ static int bristol_tuner_attach(struct dvb_usb_adapter *adap) | |||
96 | } | 96 | } |
97 | 97 | ||
98 | /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ | 98 | /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */ |
99 | /* | 99 | static struct dibx000_agc_config stk7700p_dib7000m_agc_config = { |
100 | static struct mt2060_config stk7000p_mt2060_config = { | 100 | BAND_UHF | BAND_VHF, // band_caps |
101 | 0x60 | 101 | |
102 | /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=5, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, | ||
103 | * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=2, P_agc_write=0 */ | ||
104 | (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), // setup | ||
105 | |||
106 | 712, // inv_gain | ||
107 | 41, // time_stabiliz | ||
108 | |||
109 | 0, // alpha_level | ||
110 | 118, // thlock | ||
111 | |||
112 | 0, // wbd_inv | ||
113 | 4095, // wbd_ref | ||
114 | 0, // wbd_sel | ||
115 | 0, // wbd_alpha | ||
116 | |||
117 | 42598, // agc1_max | ||
118 | 17694, // agc1_min | ||
119 | 45875, // agc2_max | ||
120 | 2621, // agc2_min | ||
121 | 0, // agc1_pt1 | ||
122 | 76, // agc1_pt2 | ||
123 | 139, // agc1_pt3 | ||
124 | 52, // agc1_slope1 | ||
125 | 59, // agc1_slope2 | ||
126 | 107, // agc2_pt1 | ||
127 | 172, // agc2_pt2 | ||
128 | 57, // agc2_slope1 | ||
129 | 70, // agc2_slope2 | ||
130 | |||
131 | 21, // alpha_mant | ||
132 | 25, // alpha_exp | ||
133 | 28, // beta_mant | ||
134 | 48, // beta_exp | ||
135 | |||
136 | 1, // perform_agc_softsplit | ||
137 | { 0, // split_min | ||
138 | 107, // split_max | ||
139 | 51800, // global_split_min | ||
140 | 24700 // global_split_max | ||
141 | }, | ||
142 | }; | ||
143 | |||
144 | static struct dibx000_bandwidth_config stk7700p_dib7000m_mt2060_config = { | ||
145 | 60000, 30000, // internal, sampling | ||
146 | 1, 8, 3, 1, 0, // pll_cfg: prediv, ratio, range, reset, bypass | ||
147 | 0, 0, 1, 1, 0, // misc: refdiv, bypclk_div, IO_CLK_en_core, ADClkSrc, modulo | ||
148 | (3 << 14) | (1 << 12) | (524 << 0), // sad_cfg: refsel, sel, freq_15k | ||
149 | 60258167, // ifreq | ||
150 | 20452225, // timf | ||
151 | }; | ||
152 | |||
153 | static struct dib7000m_config stk7700p_dib7000m_config = { | ||
154 | .dvbt_mode = 1, | ||
155 | .output_mpeg2_in_188_bytes = 1, | ||
156 | .quartz_direct = 1, | ||
157 | |||
158 | .agc_config_count = 1, | ||
159 | .agc = &stk7700p_dib7000m_agc_config, | ||
160 | .bw = &stk7700p_dib7000m_mt2060_config, | ||
161 | |||
162 | .gpio_dir = DIB7000M_GPIO_DEFAULT_DIRECTIONS, | ||
163 | .gpio_val = DIB7000M_GPIO_DEFAULT_VALUES, | ||
164 | .gpio_pwm_pos = DIB7000M_GPIO_DEFAULT_PWM_POS, | ||
102 | }; | 165 | }; |
103 | */ | ||
104 | 166 | ||
105 | static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap) | 167 | static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap) |
106 | { | 168 | { |
169 | struct dib0700_state *st = adap->dev->priv; | ||
107 | /* unless there is no real power management in DVB - we leave the device on GPIO6 */ | 170 | /* unless there is no real power management in DVB - we leave the device on GPIO6 */ |
108 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10); | 171 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10); |
109 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10); | 172 | dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10); |
110 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(10); | ||
111 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10); | 173 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10); |
174 | dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(10); | ||
112 | 175 | ||
113 | // adap->fe = dib7000m_attach(&adap->dev->i2c_adap, &stk7700p_dib7000m_config, 18); | 176 | st->mt2060_if1[0] = 1220; |
114 | return 0; | 177 | return (adap->fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config)) == NULL ? -ENODEV : 0; |
115 | } | 178 | } |
116 | 179 | ||
180 | static struct mt2060_config stk7700p_mt2060_config = { | ||
181 | 0x60 | ||
182 | }; | ||
183 | |||
117 | static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap) | 184 | static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap) |
118 | { | 185 | { |
119 | // tun_i2c = dib7000m_get_tuner_i2c_master(adap->fe, 1); | 186 | struct dib0700_state *st = adap->dev->priv; |
120 | // return mt2060_attach(adap->fe, tun_i2c, &stk3000p_mt2060_config, if1); | 187 | struct i2c_adapter *tun_i2c = dib7000m_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1); |
121 | return 0; | 188 | return dvb_attach(mt2060_attach,adap->fe, tun_i2c, &stk7700p_mt2060_config, |
189 | st->mt2060_if1[0]) == NULL ? -ENODEV : 0; | ||
122 | } | 190 | } |
123 | 191 | ||
124 | struct usb_device_id dib0700_usb_id_table[] = { | 192 | struct usb_device_id dib0700_usb_id_table[] = { |
@@ -127,6 +195,7 @@ struct usb_device_id dib0700_usb_id_table[] = { | |||
127 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) }, | 195 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) }, |
128 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) }, | 196 | { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) }, |
129 | { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) }, | 197 | { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) }, |
198 | { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_STK7700P_PC) }, | ||
130 | { } /* Terminating entry */ | 199 | { } /* Terminating entry */ |
131 | }; | 200 | }; |
132 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); | 201 | MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table); |
@@ -171,7 +240,7 @@ struct dvb_usb_device_properties dib0700_devices[] = { | |||
171 | .num_device_descs = 3, | 240 | .num_device_descs = 3, |
172 | .devices = { | 241 | .devices = { |
173 | { "DiBcom STK7700P reference design", | 242 | { "DiBcom STK7700P reference design", |
174 | { &dib0700_usb_id_table[0], NULL }, | 243 | { &dib0700_usb_id_table[0], &dib0700_usb_id_table[5] }, |
175 | { NULL }, | 244 | { NULL }, |
176 | }, | 245 | }, |
177 | { "Hauppauge Nova-T Stick", | 246 | { "Hauppauge Nova-T Stick", |
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index 967d10269607..fd8ba2535c08 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h | |||
@@ -53,6 +53,7 @@ | |||
53 | #define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6 | 53 | #define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6 |
54 | #define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7 | 54 | #define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7 |
55 | #define USB_PID_DIBCOM_STK7700P 0x1e14 | 55 | #define USB_PID_DIBCOM_STK7700P 0x1e14 |
56 | #define USB_PID_DIBCOM_STK7700P_PC 0x1e78 | ||
56 | #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 | 57 | #define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 |
57 | #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 | 58 | #define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 |
58 | #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 | 59 | #define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 |
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index aebb8d6f26f8..093c7695883d 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig | |||
@@ -172,6 +172,14 @@ config DVB_DIB3000MC | |||
172 | A DVB-T tuner module. Designed for mobile usage. Say Y when you want | 172 | A DVB-T tuner module. Designed for mobile usage. Say Y when you want |
173 | to support this frontend. | 173 | to support this frontend. |
174 | 174 | ||
175 | config DVB_DIB7000M | ||
176 | tristate "DiBcom 7000MA/MB/PA/PB/MC" | ||
177 | depends on DVB_CORE && I2C | ||
178 | default m if DVB_FE_CUSTOMISE | ||
179 | help | ||
180 | A DVB-T tuner module. Designed for mobile usage. Say Y when you want | ||
181 | to support this frontend. | ||
182 | |||
175 | comment "DVB-C (cable) frontends" | 183 | comment "DVB-C (cable) frontends" |
176 | depends on DVB_CORE | 184 | depends on DVB_CORE |
177 | 185 | ||
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index dce9cf0c75c0..244e87417b0c 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile | |||
@@ -13,6 +13,7 @@ obj-$(CONFIG_DVB_TDA8083) += tda8083.o | |||
13 | obj-$(CONFIG_DVB_L64781) += l64781.o | 13 | obj-$(CONFIG_DVB_L64781) += l64781.o |
14 | obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o | 14 | obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o |
15 | obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o | 15 | obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o |
16 | obj-$(CONFIG_DVB_DIB7000M) += dib7000m.o dibx000_common.o | ||
16 | obj-$(CONFIG_DVB_MT312) += mt312.o | 17 | obj-$(CONFIG_DVB_MT312) += mt312.o |
17 | obj-$(CONFIG_DVB_VES1820) += ves1820.o | 18 | obj-$(CONFIG_DVB_VES1820) += ves1820.o |
18 | obj-$(CONFIG_DVB_VES1X93) += ves1x93.o | 19 | obj-$(CONFIG_DVB_VES1X93) += ves1x93.o |
diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c index c9a57678fa34..a85190319cf4 100644 --- a/drivers/media/dvb/frontends/dib7000m.c +++ b/drivers/media/dvb/frontends/dib7000m.c | |||
@@ -19,7 +19,7 @@ static int debug; | |||
19 | module_param(debug, int, 0644); | 19 | module_param(debug, int, 0644); |
20 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | 20 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); |
21 | 21 | ||
22 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB3000MC/P:"); printk(args); } } while (0) | 22 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000M:"); printk(args); } } while (0) |
23 | 23 | ||
24 | struct dib7000m_state { | 24 | struct dib7000m_state { |
25 | struct dvb_frontend demod; | 25 | struct dvb_frontend demod; |
@@ -38,11 +38,21 @@ struct dib7000m_state { | |||
38 | u8 current_band; | 38 | u8 current_band; |
39 | fe_bandwidth_t current_bandwidth; | 39 | fe_bandwidth_t current_bandwidth; |
40 | struct dibx000_agc_config *current_agc; | 40 | struct dibx000_agc_config *current_agc; |
41 | u32 timf[9]; | 41 | u32 timf; |
42 | 42 | ||
43 | u16 revision; | 43 | u16 revision; |
44 | }; | 44 | }; |
45 | 45 | ||
46 | enum dib7000m_power_mode { | ||
47 | DIB7000M_POWER_ALL = 0, | ||
48 | |||
49 | DIB7000M_POWER_NO, | ||
50 | DIB7000M_POWER_INTERF_ANALOG_AGC, | ||
51 | DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD, | ||
52 | DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD, | ||
53 | DIB7000M_POWER_INTERFACE_ONLY, | ||
54 | }; | ||
55 | |||
46 | static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) | 56 | static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) |
47 | { | 57 | { |
48 | u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff }; | 58 | u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff }; |
@@ -58,7 +68,6 @@ static u16 dib7000m_read_word(struct dib7000m_state *state, u16 reg) | |||
58 | return (rb[0] << 8) | rb[1]; | 68 | return (rb[0] << 8) | rb[1]; |
59 | } | 69 | } |
60 | 70 | ||
61 | /* | ||
62 | static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) | 71 | static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) |
63 | { | 72 | { |
64 | u8 b[4] = { | 73 | u8 b[4] = { |
@@ -70,7 +79,835 @@ static int dib7000m_write_word(struct dib7000m_state *state, u16 reg, u16 val) | |||
70 | }; | 79 | }; |
71 | return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; | 80 | return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; |
72 | } | 81 | } |
73 | */ | 82 | static int dib7000m_set_output_mode(struct dib7000m_state *state, int mode) |
83 | { | ||
84 | int ret = 0; | ||
85 | u16 outreg, fifo_threshold, smo_mode, | ||
86 | sram = 0x0005; /* by default SRAM output is disabled */ | ||
87 | |||
88 | outreg = 0; | ||
89 | fifo_threshold = 1792; | ||
90 | smo_mode = (dib7000m_read_word(state, 294 + state->reg_offs) & 0x0010) | (1 << 1); | ||
91 | |||
92 | dprintk("-I- Setting output mode for demod %p to %d\n", | ||
93 | &state->demod, mode); | ||
94 | |||
95 | switch (mode) { | ||
96 | case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock | ||
97 | outreg = (1 << 10); /* 0x0400 */ | ||
98 | break; | ||
99 | case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock | ||
100 | outreg = (1 << 10) | (1 << 6); /* 0x0440 */ | ||
101 | break; | ||
102 | case OUTMODE_MPEG2_SERIAL: // STBs with serial input | ||
103 | outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0482 */ | ||
104 | break; | ||
105 | case OUTMODE_DIVERSITY: | ||
106 | if (state->cfg.hostbus_diversity) | ||
107 | outreg = (1 << 10) | (4 << 6); /* 0x0500 */ | ||
108 | else | ||
109 | sram |= 0x0c00; | ||
110 | break; | ||
111 | case OUTMODE_MPEG2_FIFO: // e.g. USB feeding | ||
112 | smo_mode |= (3 << 1); | ||
113 | fifo_threshold = 512; | ||
114 | outreg = (1 << 10) | (5 << 6); | ||
115 | break; | ||
116 | case OUTMODE_HIGH_Z: // disable | ||
117 | outreg = 0; | ||
118 | break; | ||
119 | default: | ||
120 | dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod); | ||
121 | break; | ||
122 | } | ||
123 | |||
124 | if (state->cfg.output_mpeg2_in_188_bytes) | ||
125 | smo_mode |= (1 << 5) ; | ||
126 | |||
127 | ret |= dib7000m_write_word(state, 294 + state->reg_offs, smo_mode); | ||
128 | ret |= dib7000m_write_word(state, 295 + state->reg_offs, fifo_threshold); /* synchronous fread */ | ||
129 | ret |= dib7000m_write_word(state, 1795, outreg); | ||
130 | ret |= dib7000m_write_word(state, 1805, sram); | ||
131 | |||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | static int dib7000m_set_power_mode(struct dib7000m_state *state, enum dib7000m_power_mode mode) | ||
136 | { | ||
137 | /* by default everything is going to be powered off */ | ||
138 | u16 reg_903 = 0xffff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906 = 0x3fff; | ||
139 | |||
140 | /* now, depending on the requested mode, we power on */ | ||
141 | switch (mode) { | ||
142 | /* power up everything in the demod */ | ||
143 | case DIB7000M_POWER_ALL: | ||
144 | reg_903 = 0x0000; reg_904 = 0x0000; reg_905 = 0x0000; reg_906 = 0x0000; | ||
145 | break; | ||
146 | |||
147 | /* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */ | ||
148 | case DIB7000M_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C or SRAM */ | ||
149 | reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2)); | ||
150 | break; | ||
151 | |||
152 | case DIB7000M_POWER_INTERF_ANALOG_AGC: | ||
153 | reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10)); | ||
154 | reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2)); | ||
155 | reg_906 &= ~((1 << 0)); | ||
156 | break; | ||
157 | |||
158 | case DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD: | ||
159 | reg_903 = 0x0000; reg_904 = 0x801f; reg_905 = 0x0000; reg_906 = 0x0000; | ||
160 | break; | ||
161 | |||
162 | case DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD: | ||
163 | reg_903 = 0x0000; reg_904 = 0x8000; reg_905 = 0x010b; reg_906 = 0x0000; | ||
164 | break; | ||
165 | case DIB7000M_POWER_NO: | ||
166 | break; | ||
167 | } | ||
168 | |||
169 | /* always power down unused parts */ | ||
170 | if (!state->cfg.mobile_mode) | ||
171 | reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1); | ||
172 | |||
173 | /* P_sdio_select_clk = 0 on MC */ | ||
174 | if (state->revision != 0x4000) | ||
175 | reg_906 <<= 1; | ||
176 | |||
177 | dib7000m_write_word(state, 903, reg_903); | ||
178 | dib7000m_write_word(state, 904, reg_904); | ||
179 | dib7000m_write_word(state, 905, reg_905); | ||
180 | dib7000m_write_word(state, 906, reg_906); | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static int dib7000m_set_adc_state(struct dib7000m_state *state, enum dibx000_adc_states no) | ||
186 | { | ||
187 | int ret = 0; | ||
188 | u16 reg_913 = dib7000m_read_word(state, 913), | ||
189 | reg_914 = dib7000m_read_word(state, 914); | ||
190 | |||
191 | switch (no) { | ||
192 | case DIBX000_SLOW_ADC_ON: | ||
193 | reg_914 |= (1 << 1) | (1 << 0); | ||
194 | ret |= dib7000m_write_word(state, 914, reg_914); | ||
195 | reg_914 &= ~(1 << 1); | ||
196 | break; | ||
197 | |||
198 | case DIBX000_SLOW_ADC_OFF: | ||
199 | reg_914 |= (1 << 1) | (1 << 0); | ||
200 | break; | ||
201 | |||
202 | case DIBX000_ADC_ON: | ||
203 | if (state->revision == 0x4000) { // workaround for PA/MA | ||
204 | // power-up ADC | ||
205 | dib7000m_write_word(state, 913, 0); | ||
206 | dib7000m_write_word(state, 914, reg_914 & 0x3); | ||
207 | // power-down bandgag | ||
208 | dib7000m_write_word(state, 913, (1 << 15)); | ||
209 | dib7000m_write_word(state, 914, reg_914 & 0x3); | ||
210 | } | ||
211 | |||
212 | reg_913 &= 0x0fff; | ||
213 | reg_914 &= 0x0003; | ||
214 | break; | ||
215 | |||
216 | case DIBX000_ADC_OFF: // leave the VBG voltage on | ||
217 | reg_913 |= (1 << 14) | (1 << 13) | (1 << 12); | ||
218 | reg_914 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2); | ||
219 | break; | ||
220 | |||
221 | case DIBX000_VBG_ENABLE: | ||
222 | reg_913 &= ~(1 << 15); | ||
223 | break; | ||
224 | |||
225 | case DIBX000_VBG_DISABLE: | ||
226 | reg_913 |= (1 << 15); | ||
227 | break; | ||
228 | |||
229 | default: | ||
230 | break; | ||
231 | } | ||
232 | |||
233 | // dprintk("-D- 913: %x, 914: %x\n", reg_913, reg_914); | ||
234 | |||
235 | ret |= dib7000m_write_word(state, 913, reg_913); | ||
236 | ret |= dib7000m_write_word(state, 914, reg_914); | ||
237 | |||
238 | return ret; | ||
239 | } | ||
240 | |||
241 | static int dib7000m_set_bandwidth(struct dvb_frontend *demod, u8 bw_idx) | ||
242 | { | ||
243 | struct dib7000m_state *state = demod->demodulator_priv; | ||
244 | u32 timf; | ||
245 | |||
246 | // store the current bandwidth for later use | ||
247 | state->current_bandwidth = bw_idx; | ||
248 | |||
249 | if (state->timf == 0) { | ||
250 | dprintk("-D- Using default timf\n"); | ||
251 | timf = state->cfg.bw->timf; | ||
252 | } else { | ||
253 | dprintk("-D- Using updated timf\n"); | ||
254 | timf = state->timf; | ||
255 | } | ||
256 | |||
257 | timf = timf * (BW_INDEX_TO_KHZ(bw_idx) / 100) / 80; | ||
258 | |||
259 | dib7000m_write_word(state, 23, (timf >> 16) & 0xffff); | ||
260 | dib7000m_write_word(state, 24, (timf ) & 0xffff); | ||
261 | |||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | static int dib7000m_sad_calib(struct dib7000m_state *state) | ||
266 | { | ||
267 | |||
268 | /* internal */ | ||
269 | // dib7000m_write_word(state, 928, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth | ||
270 | dib7000m_write_word(state, 929, (0 << 1) | (0 << 0)); | ||
271 | dib7000m_write_word(state, 930, 776); // 0.625*3.3 / 4096 | ||
272 | |||
273 | /* do the calibration */ | ||
274 | dib7000m_write_word(state, 929, (1 << 0)); | ||
275 | dib7000m_write_word(state, 929, (0 << 0)); | ||
276 | |||
277 | msleep(1); | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | static void dib7000m_reset_pll_common(struct dib7000m_state *state, const struct dibx000_bandwidth_config *bw) | ||
283 | { | ||
284 | dib7000m_write_word(state, 18, ((bw->internal*1000) >> 16) & 0xffff); | ||
285 | dib7000m_write_word(state, 19, (bw->internal*1000) & 0xffff); | ||
286 | dib7000m_write_word(state, 21, (bw->ifreq >> 16) & 0xffff); | ||
287 | dib7000m_write_word(state, 22, bw->ifreq & 0xffff); | ||
288 | |||
289 | dib7000m_write_word(state, 928, bw->sad_cfg); | ||
290 | } | ||
291 | |||
292 | static void dib7000m_reset_pll(struct dib7000m_state *state) | ||
293 | { | ||
294 | const struct dibx000_bandwidth_config *bw = state->cfg.bw; | ||
295 | u16 reg_907,reg_910; | ||
296 | |||
297 | /* default */ | ||
298 | reg_907 = (bw->pll_bypass << 15) | (bw->modulo << 7) | | ||
299 | (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | | ||
300 | (bw->enable_refdiv << 1) | (0 << 0); | ||
301 | reg_910 = (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset; | ||
302 | |||
303 | // for this oscillator frequency should be 30 MHz for the Master (default values in the board_parameters give that value) | ||
304 | // this is only working only for 30 MHz crystals | ||
305 | if (!state->cfg.quartz_direct) { | ||
306 | reg_910 |= (1 << 5); // forcing the predivider to 1 | ||
307 | |||
308 | // if the previous front-end is baseband, its output frequency is 15 MHz (prev freq divided by 2) | ||
309 | if(state->cfg.input_clk_is_div_2) | ||
310 | reg_907 |= (16 << 9); | ||
311 | else // otherwise the previous front-end puts out its input (default 30MHz) - no extra division necessary | ||
312 | reg_907 |= (8 << 9); | ||
313 | } else { | ||
314 | reg_907 |= (bw->pll_ratio & 0x3f) << 9; | ||
315 | reg_910 |= (bw->pll_prediv << 5); | ||
316 | } | ||
317 | |||
318 | dib7000m_write_word(state, 910, reg_910); // pll cfg | ||
319 | dib7000m_write_word(state, 907, reg_907); // clk cfg0 | ||
320 | dib7000m_write_word(state, 908, 0x0006); // clk_cfg1 | ||
321 | |||
322 | dib7000m_reset_pll_common(state, bw); | ||
323 | } | ||
324 | |||
325 | static void dib7000mc_reset_pll(struct dib7000m_state *state) | ||
326 | { | ||
327 | const struct dibx000_bandwidth_config *bw = state->cfg.bw; | ||
328 | |||
329 | // clk_cfg0 | ||
330 | dib7000m_write_word(state, 907, (bw->pll_prediv << 8) | (bw->pll_ratio << 0)); | ||
331 | |||
332 | // clk_cfg1 | ||
333 | //dib7000m_write_word(state, 908, (1 << 14) | (3 << 12) |(0 << 11) | | ||
334 | dib7000m_write_word(state, 908, (0 << 14) | (3 << 12) |(0 << 11) | | ||
335 | (bw->IO_CLK_en_core << 10) | (bw->bypclk_div << 5) | (bw->enable_refdiv << 4) | | ||
336 | (bw->pll_bypass << 3) | (bw->pll_range << 1) | (bw->pll_reset << 0)); | ||
337 | |||
338 | // smpl_cfg | ||
339 | dib7000m_write_word(state, 910, (1 << 12) | (2 << 10) | (bw->modulo << 8) | (bw->ADClkSrc << 7)); | ||
340 | |||
341 | dib7000m_reset_pll_common(state, bw); | ||
342 | } | ||
343 | |||
344 | static int dib7000m_reset_gpio(struct dib7000m_state *st) | ||
345 | { | ||
346 | /* reset the GPIOs */ | ||
347 | dprintk("-D- gpio dir: %x: gpio val: %x, gpio pwm pos: %x\n", | ||
348 | st->cfg.gpio_dir, st->cfg.gpio_val,st->cfg.gpio_pwm_pos); | ||
349 | |||
350 | dib7000m_write_word(st, 773, st->cfg.gpio_dir); | ||
351 | dib7000m_write_word(st, 774, st->cfg.gpio_val); | ||
352 | |||
353 | /* TODO 782 is P_gpio_od */ | ||
354 | |||
355 | dib7000m_write_word(st, 775, st->cfg.gpio_pwm_pos); | ||
356 | |||
357 | dib7000m_write_word(st, 780, st->cfg.pwm_freq_div); | ||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | static int dib7000m_demod_reset(struct dib7000m_state *state) | ||
362 | { | ||
363 | dib7000m_set_power_mode(state, DIB7000M_POWER_ALL); | ||
364 | |||
365 | /* always leave the VBG voltage on - it consumes almost nothing but takes a long time to start */ | ||
366 | dib7000m_set_adc_state(state, DIBX000_VBG_ENABLE); | ||
367 | |||
368 | /* restart all parts */ | ||
369 | dib7000m_write_word(state, 898, 0xffff); | ||
370 | dib7000m_write_word(state, 899, 0xffff); | ||
371 | dib7000m_write_word(state, 900, 0xff0f); | ||
372 | dib7000m_write_word(state, 901, 0xfffc); | ||
373 | |||
374 | dib7000m_write_word(state, 898, 0); | ||
375 | dib7000m_write_word(state, 899, 0); | ||
376 | dib7000m_write_word(state, 900, 0); | ||
377 | dib7000m_write_word(state, 901, 0); | ||
378 | |||
379 | if (state->revision == 0x4000) | ||
380 | dib7000m_reset_pll(state); | ||
381 | else | ||
382 | dib7000mc_reset_pll(state); | ||
383 | |||
384 | if (dib7000m_reset_gpio(state) != 0) | ||
385 | dprintk("-E- GPIO reset was not successful.\n"); | ||
386 | |||
387 | if (dib7000m_set_output_mode(state, OUTMODE_HIGH_Z) != 0) | ||
388 | dprintk("-E- OUTPUT_MODE could not be resetted.\n"); | ||
389 | |||
390 | /* unforce divstr regardless whether i2c enumeration was done or not */ | ||
391 | dib7000m_write_word(state, 1794, dib7000m_read_word(state, 1794) & ~(1 << 1) ); | ||
392 | |||
393 | dib7000m_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ); | ||
394 | |||
395 | dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON); | ||
396 | dib7000m_sad_calib(state); | ||
397 | dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_OFF); | ||
398 | |||
399 | dib7000m_set_power_mode(state, DIB7000M_POWER_INTERFACE_ONLY); | ||
400 | |||
401 | return 0; | ||
402 | } | ||
403 | |||
404 | static void dib7000m_restart_agc(struct dib7000m_state *state) | ||
405 | { | ||
406 | // P_restart_iqc & P_restart_agc | ||
407 | dib7000m_write_word(state, 898, 0x0c00); | ||
408 | dib7000m_write_word(state, 898, 0x0000); | ||
409 | } | ||
410 | |||
411 | static int dib7000m_agc_soft_split(struct dib7000m_state *state) | ||
412 | { | ||
413 | u16 agc,split_offset; | ||
414 | |||
415 | if(!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0) | ||
416 | return 0; | ||
417 | |||
418 | // n_agc_global | ||
419 | agc = dib7000m_read_word(state, 390); | ||
420 | |||
421 | if (agc > state->current_agc->split.min_thres) | ||
422 | split_offset = state->current_agc->split.min; | ||
423 | else if (agc < state->current_agc->split.max_thres) | ||
424 | split_offset = state->current_agc->split.max; | ||
425 | else | ||
426 | split_offset = state->current_agc->split.max * | ||
427 | (agc - state->current_agc->split.min_thres) / | ||
428 | (state->current_agc->split.max_thres - state->current_agc->split.min_thres); | ||
429 | |||
430 | dprintk("AGC split_offset: %d\n",split_offset); | ||
431 | |||
432 | // P_agc_force_split and P_agc_split_offset | ||
433 | return dib7000m_write_word(state, 103, (dib7000m_read_word(state, 103) & 0xff00) | split_offset); | ||
434 | } | ||
435 | |||
436 | static int dib7000m_update_lna(struct dib7000m_state *state) | ||
437 | { | ||
438 | int i; | ||
439 | u16 dyn_gain; | ||
440 | |||
441 | // when there is no LNA to program return immediatly | ||
442 | if (state->cfg.update_lna == NULL) | ||
443 | return 0; | ||
444 | |||
445 | msleep(60); | ||
446 | for (i = 0; i < 20; i++) { | ||
447 | // read dyn_gain here (because it is demod-dependent and not tuner) | ||
448 | dyn_gain = dib7000m_read_word(state, 390); | ||
449 | |||
450 | dprintk("agc global: %d\n", dyn_gain); | ||
451 | |||
452 | if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed | ||
453 | dib7000m_restart_agc(state); | ||
454 | msleep(60); | ||
455 | } else | ||
456 | break; | ||
457 | } | ||
458 | return 0; | ||
459 | } | ||
460 | |||
461 | static void dib7000m_set_agc_config(struct dib7000m_state *state, u8 band) | ||
462 | { | ||
463 | struct dibx000_agc_config *agc = NULL; | ||
464 | int i; | ||
465 | if (state->current_band == band) | ||
466 | return; | ||
467 | state->current_band = band; | ||
468 | |||
469 | for (i = 0; i < state->cfg.agc_config_count; i++) | ||
470 | if (state->cfg.agc[i].band_caps & band) { | ||
471 | agc = &state->cfg.agc[i]; | ||
472 | break; | ||
473 | } | ||
474 | |||
475 | if (agc == NULL) { | ||
476 | dprintk("-E- No valid AGC configuration found for band 0x%02x\n",band); | ||
477 | return; | ||
478 | } | ||
479 | |||
480 | state->current_agc = agc; | ||
481 | |||
482 | /* AGC */ | ||
483 | dib7000m_write_word(state, 72 , agc->setup); | ||
484 | dib7000m_write_word(state, 73 , agc->inv_gain); | ||
485 | dib7000m_write_word(state, 74 , agc->time_stabiliz); | ||
486 | dib7000m_write_word(state, 97 , (agc->alpha_level << 12) | agc->thlock); | ||
487 | |||
488 | // Demod AGC loop configuration | ||
489 | dib7000m_write_word(state, 98, (agc->alpha_mant << 5) | agc->alpha_exp); | ||
490 | dib7000m_write_word(state, 99, (agc->beta_mant << 6) | agc->beta_exp); | ||
491 | |||
492 | dprintk("-D- WBD: ref: %d, sel: %d, active: %d, alpha: %d\n", | ||
493 | state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel); | ||
494 | |||
495 | /* AGC continued */ | ||
496 | if (state->wbd_ref != 0) | ||
497 | dib7000m_write_word(state, 102, state->wbd_ref); | ||
498 | else // use default | ||
499 | dib7000m_write_word(state, 102, agc->wbd_ref); | ||
500 | |||
501 | dib7000m_write_word(state, 103, (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8) ); | ||
502 | dib7000m_write_word(state, 104, agc->agc1_max); | ||
503 | dib7000m_write_word(state, 105, agc->agc1_min); | ||
504 | dib7000m_write_word(state, 106, agc->agc2_max); | ||
505 | dib7000m_write_word(state, 107, agc->agc2_min); | ||
506 | dib7000m_write_word(state, 108, (agc->agc1_pt1 << 8) | agc->agc1_pt2 ); | ||
507 | dib7000m_write_word(state, 109, (agc->agc1_slope1 << 8) | agc->agc1_slope2); | ||
508 | dib7000m_write_word(state, 110, (agc->agc2_pt1 << 8) | agc->agc2_pt2); | ||
509 | dib7000m_write_word(state, 111, (agc->agc2_slope1 << 8) | agc->agc2_slope2); | ||
510 | |||
511 | if (state->revision > 0x4000) { // settings for the MC | ||
512 | dib7000m_write_word(state, 71, agc->agc1_pt3); | ||
513 | // dprintk("-D- 929: %x %d %d\n", | ||
514 | // (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2), agc->wbd_inv, agc->wbd_sel); | ||
515 | dib7000m_write_word(state, 929, (dib7000m_read_word(state, 929) & 0xffe3) | (agc->wbd_inv << 4) | (agc->wbd_sel << 2)); | ||
516 | } else { | ||
517 | // wrong default values | ||
518 | u16 b[9] = { 676, 696, 717, 737, 758, 778, 799, 819, 840 }; | ||
519 | for (i = 0; i < 9; i++) | ||
520 | dib7000m_write_word(state, 88 + i, b[i]); | ||
521 | } | ||
522 | } | ||
523 | |||
524 | static void dib7000m_update_timf_freq(struct dib7000m_state *state) | ||
525 | { | ||
526 | u32 timf = (dib7000m_read_word(state, 436) << 16) | dib7000m_read_word(state, 437); | ||
527 | state->timf = timf * 80 / (BW_INDEX_TO_KHZ(state->current_bandwidth) / 100); | ||
528 | dib7000m_write_word(state, 23, (u16) (timf >> 16)); | ||
529 | dib7000m_write_word(state, 24, (u16) (timf & 0xffff)); | ||
530 | dprintk("-D- Updated timf_frequency: %d (default: %d)\n",state->timf, state->cfg.bw->timf); | ||
531 | } | ||
532 | |||
533 | static void dib7000m_set_channel(struct dib7000m_state *state, struct dibx000_ofdm_channel *ch, u8 seq) | ||
534 | { | ||
535 | u16 value, est[4]; | ||
536 | |||
537 | dib7000m_set_agc_config(state, BAND_OF_FREQUENCY(ch->RF_kHz)); | ||
538 | |||
539 | /* nfft, guard, qam, alpha */ | ||
540 | dib7000m_write_word(state, 0, (ch->nfft << 7) | (ch->guard << 5) | (ch->nqam << 3) | (ch->vit_alpha)); | ||
541 | dib7000m_write_word(state, 5, (seq << 4)); | ||
542 | |||
543 | /* P_dintl_native, P_dintlv_inv, P_vit_hrch, P_vit_code_rate, P_vit_select_hp */ | ||
544 | value = (ch->intlv_native << 6) | (ch->vit_hrch << 4) | (ch->vit_select_hp & 0x1); | ||
545 | if (ch->vit_hrch == 0 || ch->vit_select_hp == 1) | ||
546 | value |= (ch->vit_code_rate_hp << 1); | ||
547 | else | ||
548 | value |= (ch->vit_code_rate_lp << 1); | ||
549 | dib7000m_write_word(state, 267 + state->reg_offs, value); | ||
550 | |||
551 | /* offset loop parameters */ | ||
552 | |||
553 | /* P_timf_alpha = 6, P_corm_alpha=6, P_corm_thres=0x80 */ | ||
554 | dib7000m_write_word(state, 26, (6 << 12) | (6 << 8) | 0x80); | ||
555 | |||
556 | /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=1, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ | ||
557 | dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (1 << 9) | (3 << 5) | (1 << 4) | (0x3)); | ||
558 | |||
559 | /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max=3 */ | ||
560 | dib7000m_write_word(state, 32, (0 << 4) | 0x3); | ||
561 | |||
562 | /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step=5 */ | ||
563 | dib7000m_write_word(state, 33, (0 << 4) | 0x5); | ||
564 | |||
565 | /* P_dvsy_sync_wait */ | ||
566 | switch (ch->nfft) { | ||
567 | case 1: value = 256; break; | ||
568 | case 2: value = 128; break; | ||
569 | case 0: | ||
570 | default: value = 64; break; | ||
571 | } | ||
572 | value *= ((1 << (ch->guard)) * 3 / 2); // add 50% SFN margin | ||
573 | value <<= 4; | ||
574 | |||
575 | /* deactive the possibility of diversity reception if extended interleave - not for 7000MC */ | ||
576 | /* P_dvsy_sync_mode = 0, P_dvsy_sync_enable=1, P_dvcb_comb_mode=2 */ | ||
577 | if (ch->intlv_native || state->revision > 0x4000) | ||
578 | value |= (1 << 2) | (2 << 0); | ||
579 | else | ||
580 | value |= 0; | ||
581 | dib7000m_write_word(state, 266 + state->reg_offs, value); | ||
582 | |||
583 | /* channel estimation fine configuration */ | ||
584 | switch (ch->nqam) { | ||
585 | case 2: | ||
586 | est[0] = 0x0148; /* P_adp_regul_cnt 0.04 */ | ||
587 | est[1] = 0xfff0; /* P_adp_noise_cnt -0.002 */ | ||
588 | est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ | ||
589 | est[3] = 0xfff8; /* P_adp_noise_ext -0.001 */ | ||
590 | break; | ||
591 | case 1: | ||
592 | est[0] = 0x023d; /* P_adp_regul_cnt 0.07 */ | ||
593 | est[1] = 0xffdf; /* P_adp_noise_cnt -0.004 */ | ||
594 | est[2] = 0x00a4; /* P_adp_regul_ext 0.02 */ | ||
595 | est[3] = 0xfff0; /* P_adp_noise_ext -0.002 */ | ||
596 | break; | ||
597 | default: | ||
598 | est[0] = 0x099a; /* P_adp_regul_cnt 0.3 */ | ||
599 | est[1] = 0xffae; /* P_adp_noise_cnt -0.01 */ | ||
600 | est[2] = 0x0333; /* P_adp_regul_ext 0.1 */ | ||
601 | est[3] = 0xfff8; /* P_adp_noise_ext -0.002 */ | ||
602 | break; | ||
603 | } | ||
604 | for (value = 0; value < 4; value++) | ||
605 | dib7000m_write_word(state, 214 + value + state->reg_offs, est[value]); | ||
606 | |||
607 | // set power-up level: interf+analog+AGC | ||
608 | dib7000m_set_power_mode(state, DIB7000M_POWER_INTERF_ANALOG_AGC); | ||
609 | dib7000m_set_adc_state(state, DIBX000_ADC_ON); | ||
610 | |||
611 | msleep(7); | ||
612 | |||
613 | //AGC initialization | ||
614 | if (state->cfg.agc_control) | ||
615 | state->cfg.agc_control(&state->demod, 1); | ||
616 | |||
617 | dib7000m_restart_agc(state); | ||
618 | |||
619 | // wait AGC rough lock time | ||
620 | msleep(5); | ||
621 | |||
622 | dib7000m_update_lna(state); | ||
623 | dib7000m_agc_soft_split(state); | ||
624 | |||
625 | // wait AGC accurate lock time | ||
626 | msleep(7); | ||
627 | |||
628 | if (state->cfg.agc_control) | ||
629 | state->cfg.agc_control(&state->demod, 0); | ||
630 | |||
631 | // set power-up level: autosearch | ||
632 | dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD); | ||
633 | } | ||
634 | |||
635 | static int dib7000m_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) | ||
636 | { | ||
637 | struct dib7000m_state *state = demod->demodulator_priv; | ||
638 | struct dibx000_ofdm_channel auto_ch; | ||
639 | int ret = 0; | ||
640 | u8 seq; | ||
641 | u32 value; | ||
642 | |||
643 | INIT_OFDM_CHANNEL(&auto_ch); | ||
644 | auto_ch.RF_kHz = ch->RF_kHz; | ||
645 | auto_ch.Bw = ch->Bw; | ||
646 | auto_ch.nqam = 2; | ||
647 | auto_ch.guard = ch->guard == GUARD_INTERVAL_AUTO ? 0 : ch->guard; | ||
648 | auto_ch.nfft = ch->nfft == -1 ? 1 : ch->nfft; | ||
649 | auto_ch.vit_alpha = 1; | ||
650 | auto_ch.vit_select_hp = 1; | ||
651 | auto_ch.vit_code_rate_hp = 2; | ||
652 | auto_ch.vit_code_rate_lp = 3; | ||
653 | auto_ch.vit_hrch = 0; | ||
654 | auto_ch.intlv_native = 1; | ||
655 | |||
656 | seq = 0; | ||
657 | if (ch->nfft == -1 && ch->guard == GUARD_INTERVAL_AUTO) seq = 7; | ||
658 | if (ch->nfft == -1 && ch->guard != GUARD_INTERVAL_AUTO) seq = 2; | ||
659 | if (ch->nfft != -1 && ch->guard == GUARD_INTERVAL_AUTO) seq = 3; | ||
660 | dib7000m_set_channel(state, &auto_ch, seq); | ||
661 | |||
662 | // always use the setting for 8MHz here lock_time for 7,6 MHz are longer | ||
663 | value = 30 * state->cfg.bw[BANDWIDTH_8_MHZ].internal; | ||
664 | ret |= dib7000m_write_word(state, 6, (u16) ((value >> 16) & 0xffff)); // lock0 wait time | ||
665 | ret |= dib7000m_write_word(state, 7, (u16) (value & 0xffff)); // lock0 wait time | ||
666 | value = 100 * state->cfg.bw[BANDWIDTH_8_MHZ].internal; | ||
667 | ret |= dib7000m_write_word(state, 8, (u16) ((value >> 16) & 0xffff)); // lock1 wait time | ||
668 | ret |= dib7000m_write_word(state, 9, (u16) (value & 0xffff)); // lock1 wait time | ||
669 | value = 500 * state->cfg.bw[BANDWIDTH_8_MHZ].internal; | ||
670 | ret |= dib7000m_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time | ||
671 | ret |= dib7000m_write_word(state, 11, (u16) (value & 0xffff)); // lock2 wait time | ||
672 | |||
673 | // start search | ||
674 | value = dib7000m_read_word(state, 0); | ||
675 | ret |= dib7000m_write_word(state, 0, value | (1 << 9)); | ||
676 | |||
677 | /* clear n_irq_pending */ | ||
678 | if (state->revision == 0x4000) | ||
679 | dib7000m_write_word(state, 1793, 0); | ||
680 | else | ||
681 | dib7000m_read_word(state, 537); | ||
682 | |||
683 | ret |= dib7000m_write_word(state, 0, (u16) value); | ||
684 | |||
685 | return ret; | ||
686 | } | ||
687 | |||
688 | static int dib7000m_autosearch_irq(struct dib7000m_state *state, u16 reg) | ||
689 | { | ||
690 | u16 irq_pending = dib7000m_read_word(state, reg); | ||
691 | |||
692 | if (irq_pending & 0x1) { // failed | ||
693 | dprintk("#\n"); | ||
694 | return 1; | ||
695 | } | ||
696 | |||
697 | if (irq_pending & 0x2) { // succeeded | ||
698 | dprintk("!\n"); | ||
699 | return 2; | ||
700 | } | ||
701 | return 0; // still pending | ||
702 | } | ||
703 | |||
704 | static int dib7000m_autosearch_is_irq(struct dvb_frontend *demod) | ||
705 | { | ||
706 | struct dib7000m_state *state = demod->demodulator_priv; | ||
707 | if (state->revision == 0x4000) | ||
708 | return dib7000m_autosearch_irq(state, 1793); | ||
709 | else | ||
710 | return dib7000m_autosearch_irq(state, 537); | ||
711 | } | ||
712 | |||
713 | static int dib7000m_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) | ||
714 | { | ||
715 | struct dib7000m_state *state = demod->demodulator_priv; | ||
716 | int ret = 0; | ||
717 | u16 value; | ||
718 | |||
719 | // we are already tuned - just resuming from suspend | ||
720 | if (ch != NULL) | ||
721 | dib7000m_set_channel(state, ch, 0); | ||
722 | else | ||
723 | return -EINVAL; | ||
724 | |||
725 | // restart demod | ||
726 | ret |= dib7000m_write_word(state, 898, 0x4000); | ||
727 | ret |= dib7000m_write_word(state, 898, 0x0000); | ||
728 | msleep(45); | ||
729 | |||
730 | ret |= dib7000m_set_power_mode(state, DIB7000M_POWER_COR4_CRY_ESRAM_MOUT_NUD); | ||
731 | /* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */ | ||
732 | ret |= dib7000m_write_word(state, 29, (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3)); | ||
733 | |||
734 | // never achieved a lock with that bandwidth so far - wait for timfreq to update | ||
735 | if (state->timf == 0) | ||
736 | msleep(200); | ||
737 | |||
738 | //dump_reg(state); | ||
739 | /* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */ | ||
740 | value = (6 << 8) | 0x80; | ||
741 | switch (ch->nfft) { | ||
742 | case 0: value |= (7 << 12); break; | ||
743 | case 1: value |= (9 << 12); break; | ||
744 | case 2: value |= (8 << 12); break; | ||
745 | } | ||
746 | ret |= dib7000m_write_word(state, 26, value); | ||
747 | |||
748 | /* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */ | ||
749 | value = (0 << 4); | ||
750 | switch (ch->nfft) { | ||
751 | case 0: value |= 0x6; break; | ||
752 | case 1: value |= 0x8; break; | ||
753 | case 2: value |= 0x7; break; | ||
754 | } | ||
755 | ret |= dib7000m_write_word(state, 32, value); | ||
756 | |||
757 | /* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */ | ||
758 | value = (0 << 4); | ||
759 | switch (ch->nfft) { | ||
760 | case 0: value |= 0x6; break; | ||
761 | case 1: value |= 0x8; break; | ||
762 | case 2: value |= 0x7; break; | ||
763 | } | ||
764 | ret |= dib7000m_write_word(state, 33, value); | ||
765 | |||
766 | // we achieved a lock - it's time to update the osc freq | ||
767 | if ((dib7000m_read_word(state, 535) >> 6) & 0x1) | ||
768 | dib7000m_update_timf_freq(state); | ||
769 | |||
770 | return ret; | ||
771 | } | ||
772 | |||
773 | static int dib7000m_init(struct dvb_frontend *demod) | ||
774 | { | ||
775 | struct dib7000m_state *state = demod->demodulator_priv; | ||
776 | int ret = 0; | ||
777 | u8 o = state->reg_offs; | ||
778 | |||
779 | dib7000m_set_power_mode(state, DIB7000M_POWER_ALL); | ||
780 | |||
781 | if (dib7000m_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0) | ||
782 | dprintk("-E- could not start Slow ADC\n"); | ||
783 | |||
784 | if (state->cfg.dvbt_mode) | ||
785 | dib7000m_write_word(state, 1796, 0x0); // select DVB-T output | ||
786 | |||
787 | if (state->cfg.mobile_mode) | ||
788 | ret |= dib7000m_write_word(state, 261 + o, 2); | ||
789 | else | ||
790 | ret |= dib7000m_write_word(state, 224 + o, 1); | ||
791 | |||
792 | ret |= dib7000m_write_word(state, 173 + o, 0); | ||
793 | ret |= dib7000m_write_word(state, 174 + o, 0); | ||
794 | ret |= dib7000m_write_word(state, 175 + o, 0); | ||
795 | ret |= dib7000m_write_word(state, 176 + o, 0); | ||
796 | ret |= dib7000m_write_word(state, 177 + o, 0); | ||
797 | ret |= dib7000m_write_word(state, 178 + o, 0); | ||
798 | ret |= dib7000m_write_word(state, 179 + o, 0); | ||
799 | ret |= dib7000m_write_word(state, 180 + o, 0); | ||
800 | |||
801 | // P_corm_thres Lock algorithms configuration | ||
802 | ret |= dib7000m_write_word(state, 26, 0x6680); | ||
803 | |||
804 | // P_palf_alpha_regul, P_palf_filter_freeze, P_palf_filter_on | ||
805 | ret |= dib7000m_write_word(state, 170 + o, 0x0410); | ||
806 | // P_fft_nb_to_cut | ||
807 | ret |= dib7000m_write_word(state, 182 + o, 8192); | ||
808 | // P_pha3_thres | ||
809 | ret |= dib7000m_write_word(state, 195 + o, 0x0ccd); | ||
810 | // P_cti_use_cpe, P_cti_use_prog | ||
811 | ret |= dib7000m_write_word(state, 196 + o, 0); | ||
812 | // P_cspu_regul, P_cspu_win_cut | ||
813 | ret |= dib7000m_write_word(state, 205 + o, 0x200f); | ||
814 | // P_adp_regul_cnt | ||
815 | ret |= dib7000m_write_word(state, 214 + o, 0x023d); | ||
816 | // P_adp_noise_cnt | ||
817 | ret |= dib7000m_write_word(state, 215 + o, 0x00a4); | ||
818 | // P_adp_regul_ext | ||
819 | ret |= dib7000m_write_word(state, 216 + o, 0x00a4); | ||
820 | // P_adp_noise_ext | ||
821 | ret |= dib7000m_write_word(state, 217 + o, 0x7ff0); | ||
822 | // P_adp_fil | ||
823 | ret |= dib7000m_write_word(state, 218 + o, 0x3ccc); | ||
824 | |||
825 | // P_2d_byp_ti_num | ||
826 | ret |= dib7000m_write_word(state, 226 + o, 0); | ||
827 | |||
828 | // P_fec_* | ||
829 | ret |= dib7000m_write_word(state, 281 + o, 0x0010); | ||
830 | // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard | ||
831 | ret |= dib7000m_write_word(state, 294 + o,0x0062); | ||
832 | |||
833 | // P_iqc_alpha_pha, P_iqc_alpha_amp, P_iqc_dcc_alpha, ... | ||
834 | if(state->cfg.tuner_is_baseband) | ||
835 | ret |= dib7000m_write_word(state, 36, 0x0755); | ||
836 | else | ||
837 | ret |= dib7000m_write_word(state, 36, 0x1f55); | ||
838 | |||
839 | // auto search configuration | ||
840 | ret |= dib7000m_write_word(state, 2, 0x0004); | ||
841 | ret |= dib7000m_write_word(state, 3, 0x1000); | ||
842 | ret |= dib7000m_write_word(state, 4, 0x0814); | ||
843 | ret |= dib7000m_write_word(state, 6, 0x001b); | ||
844 | ret |= dib7000m_write_word(state, 7, 0x7740); | ||
845 | ret |= dib7000m_write_word(state, 8, 0x005b); | ||
846 | ret |= dib7000m_write_word(state, 9, 0x8d80); | ||
847 | ret |= dib7000m_write_word(state, 10, 0x01c9); | ||
848 | ret |= dib7000m_write_word(state, 11, 0xc380); | ||
849 | ret |= dib7000m_write_word(state, 12, 0x0000); | ||
850 | ret |= dib7000m_write_word(state, 13, 0x0080); | ||
851 | ret |= dib7000m_write_word(state, 14, 0x0000); | ||
852 | ret |= dib7000m_write_word(state, 15, 0x0090); | ||
853 | ret |= dib7000m_write_word(state, 16, 0x0001); | ||
854 | ret |= dib7000m_write_word(state, 17, 0xd4c0); | ||
855 | ret |= dib7000m_write_word(state, 263 + o,0x0001); | ||
856 | |||
857 | // P_divclksel=3 P_divbitsel=1 | ||
858 | if (state->revision == 0x4000) | ||
859 | dib7000m_write_word(state, 909, (3 << 10) | (1 << 6)); | ||
860 | else | ||
861 | dib7000m_write_word(state, 909, (3 << 4) | 1); | ||
862 | |||
863 | // Tuner IO bank: max drive (14mA) | ||
864 | ret |= dib7000m_write_word(state, 912 ,0x2c8a); | ||
865 | |||
866 | ret |= dib7000m_write_word(state, 1817, 1); | ||
867 | |||
868 | return ret; | ||
869 | } | ||
870 | |||
871 | static int dib7000m_sleep(struct dvb_frontend *demod) | ||
872 | { | ||
873 | struct dib7000m_state *st = demod->demodulator_priv; | ||
874 | dib7000m_set_output_mode(st, OUTMODE_HIGH_Z); | ||
875 | return dib7000m_set_power_mode(st, DIB7000M_POWER_INTERFACE_ONLY) | | ||
876 | dib7000m_set_adc_state(st, DIBX000_SLOW_ADC_OFF) | | ||
877 | dib7000m_set_adc_state(st, DIBX000_ADC_OFF); | ||
878 | } | ||
879 | |||
880 | static int dib7000m_identify(struct dib7000m_state *state) | ||
881 | { | ||
882 | u16 value; | ||
883 | if ((value = dib7000m_read_word(state, 896)) != 0x01b3) { | ||
884 | dprintk("-E- DiB7000M: wrong Vendor ID (read=0x%x)\n",value); | ||
885 | return -EREMOTEIO; | ||
886 | } | ||
887 | |||
888 | state->revision = dib7000m_read_word(state, 897); | ||
889 | if (state->revision != 0x4000 && | ||
890 | state->revision != 0x4001 && | ||
891 | state->revision != 0x4002) { | ||
892 | dprintk("-E- DiB7000M: wrong Device ID (%x)\n",value); | ||
893 | return -EREMOTEIO; | ||
894 | } | ||
895 | |||
896 | /* protect this driver to be used with 7000PC */ | ||
897 | if (state->revision == 0x4000 && dib7000m_read_word(state, 769) == 0x4000) { | ||
898 | dprintk("-E- DiB7000M: this driver does not work with DiB7000PC\n"); | ||
899 | return -EREMOTEIO; | ||
900 | } | ||
901 | |||
902 | switch (state->revision) { | ||
903 | case 0x4000: dprintk("-I- found DiB7000MA/PA/MB/PB\n"); break; | ||
904 | case 0x4001: state->reg_offs = 1; dprintk("-I- found DiB7000HC\n"); break; | ||
905 | case 0x4002: state->reg_offs = 1; dprintk("-I- found DiB7000MC\n"); break; | ||
906 | } | ||
907 | |||
908 | return 0; | ||
909 | } | ||
910 | |||
74 | 911 | ||
75 | static int dib7000m_get_frontend(struct dvb_frontend* fe, | 912 | static int dib7000m_get_frontend(struct dvb_frontend* fe, |
76 | struct dvb_frontend_parameters *fep) | 913 | struct dvb_frontend_parameters *fep) |
@@ -133,13 +970,48 @@ static int dib7000m_get_frontend(struct dvb_frontend* fe, | |||
133 | static int dib7000m_set_frontend(struct dvb_frontend* fe, | 970 | static int dib7000m_set_frontend(struct dvb_frontend* fe, |
134 | struct dvb_frontend_parameters *fep) | 971 | struct dvb_frontend_parameters *fep) |
135 | { | 972 | { |
136 | return 0; | 973 | struct dib7000m_state *state = fe->demodulator_priv; |
974 | struct dibx000_ofdm_channel ch; | ||
975 | |||
976 | INIT_OFDM_CHANNEL(&ch); | ||
977 | FEP2DIB(fep,&ch); | ||
978 | |||
979 | state->current_bandwidth = fep->u.ofdm.bandwidth; | ||
980 | dib7000m_set_bandwidth(fe, fep->u.ofdm.bandwidth); | ||
981 | |||
982 | if (fe->ops.tuner_ops.set_params) | ||
983 | fe->ops.tuner_ops.set_params(fe, fep); | ||
984 | |||
985 | if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO || | ||
986 | fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || | ||
987 | fep->u.ofdm.constellation == QAM_AUTO || | ||
988 | fep->u.ofdm.code_rate_HP == FEC_AUTO) { | ||
989 | int i = 800, found; | ||
990 | |||
991 | dib7000m_autosearch_start(fe, &ch); | ||
992 | do { | ||
993 | msleep(1); | ||
994 | found = dib7000m_autosearch_is_irq(fe); | ||
995 | } while (found == 0 && i--); | ||
996 | |||
997 | dprintk("autosearch returns: %d\n",found); | ||
998 | if (found == 0 || found == 1) | ||
999 | return 0; // no channel found | ||
1000 | |||
1001 | dib7000m_get_frontend(fe, fep); | ||
1002 | FEP2DIB(fep, &ch); | ||
1003 | } | ||
1004 | |||
1005 | /* make this a config parameter */ | ||
1006 | dib7000m_set_output_mode(state, OUTMODE_MPEG2_FIFO); | ||
1007 | |||
1008 | return dib7000m_tune(fe, &ch); | ||
137 | } | 1009 | } |
138 | 1010 | ||
139 | static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat) | 1011 | static int dib7000m_read_status(struct dvb_frontend *fe, fe_status_t *stat) |
140 | { | 1012 | { |
141 | struct dib7000m_state *state = fe->demodulator_priv; | 1013 | struct dib7000m_state *state = fe->demodulator_priv; |
142 | u16 lock = dib7000m_read_word(state, 509); | 1014 | u16 lock = dib7000m_read_word(state, 535); |
143 | 1015 | ||
144 | *stat = 0; | 1016 | *stat = 0; |
145 | 1017 | ||
@@ -191,18 +1063,100 @@ static int dib7000m_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_fro | |||
191 | return 0; | 1063 | return 0; |
192 | } | 1064 | } |
193 | 1065 | ||
194 | static int dib7000m_init(struct dvb_frontend *fe) | 1066 | static void dib7000m_release(struct dvb_frontend *demod) |
195 | { | 1067 | { |
196 | return 0; | 1068 | struct dib7000m_state *st = demod->demodulator_priv; |
1069 | dibx000_exit_i2c_master(&st->i2c_master); | ||
1070 | kfree(st); | ||
1071 | } | ||
1072 | |||
1073 | struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating) | ||
1074 | { | ||
1075 | struct dib7000m_state *st = demod->demodulator_priv; | ||
1076 | return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating); | ||
197 | } | 1077 | } |
1078 | EXPORT_SYMBOL(dib7000m_get_i2c_master); | ||
198 | 1079 | ||
199 | static int dib7000m_sleep(struct dvb_frontend *fe) | 1080 | int dib7000m_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000m_config cfg[]) |
200 | { | 1081 | { |
1082 | struct dib7000m_state st = { .i2c_adap = i2c }; | ||
1083 | int k = 0; | ||
1084 | u8 new_addr = 0; | ||
1085 | |||
1086 | for (k = no_of_demods-1; k >= 0; k--) { | ||
1087 | st.cfg = cfg[k]; | ||
1088 | |||
1089 | /* designated i2c address */ | ||
1090 | new_addr = (0x40 + k) << 1; | ||
1091 | st.i2c_addr = new_addr; | ||
1092 | if (dib7000m_identify(&st) != 0) { | ||
1093 | st.i2c_addr = default_addr; | ||
1094 | if (dib7000m_identify(&st) != 0) { | ||
1095 | dprintk("DiB7000M #%d: not identified\n", k); | ||
1096 | return -EIO; | ||
1097 | } | ||
1098 | } | ||
1099 | |||
1100 | /* start diversity to pull_down div_str - just for i2c-enumeration */ | ||
1101 | dib7000m_set_output_mode(&st, OUTMODE_DIVERSITY); | ||
1102 | |||
1103 | dib7000m_write_word(&st, 1796, 0x0); // select DVB-T output | ||
1104 | |||
1105 | /* set new i2c address and force divstart */ | ||
1106 | dib7000m_write_word(&st, 1794, (new_addr << 2) | 0x2); | ||
1107 | |||
1108 | dprintk("IC %d initialized (to i2c_address 0x%x)\n", k, new_addr); | ||
1109 | } | ||
1110 | |||
1111 | for (k = 0; k < no_of_demods; k++) { | ||
1112 | st.cfg = cfg[k]; | ||
1113 | st.i2c_addr = (0x40 + k) << 1; | ||
1114 | |||
1115 | // unforce divstr | ||
1116 | dib7000m_write_word(&st,1794, st.i2c_addr << 2); | ||
1117 | |||
1118 | /* deactivate div - it was just for i2c-enumeration */ | ||
1119 | dib7000m_set_output_mode(&st, OUTMODE_HIGH_Z); | ||
1120 | } | ||
1121 | |||
201 | return 0; | 1122 | return 0; |
202 | } | 1123 | } |
1124 | EXPORT_SYMBOL(dib7000m_i2c_enumeration); | ||
203 | 1125 | ||
204 | static void dib7000m_release(struct dvb_frontend *fe) | 1126 | static struct dvb_frontend_ops dib7000m_ops; |
205 | { } | 1127 | struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg) |
1128 | { | ||
1129 | struct dvb_frontend *demod; | ||
1130 | struct dib7000m_state *st; | ||
1131 | st = kzalloc(sizeof(struct dib7000m_state), GFP_KERNEL); | ||
1132 | if (st == NULL) | ||
1133 | return NULL; | ||
1134 | |||
1135 | memcpy(&st->cfg, cfg, sizeof(struct dib7000m_config)); | ||
1136 | st->i2c_adap = i2c_adap; | ||
1137 | st->i2c_addr = i2c_addr; | ||
1138 | |||
1139 | demod = &st->demod; | ||
1140 | demod->demodulator_priv = st; | ||
1141 | memcpy(&st->demod.ops, &dib7000m_ops, sizeof(struct dvb_frontend_ops)); | ||
1142 | |||
1143 | if (dib7000m_identify(st) != 0) | ||
1144 | goto error; | ||
1145 | |||
1146 | if (st->revision == 0x4000) | ||
1147 | dibx000_init_i2c_master(&st->i2c_master, DIB7000, st->i2c_adap, st->i2c_addr); | ||
1148 | else | ||
1149 | dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c_adap, st->i2c_addr); | ||
1150 | |||
1151 | dib7000m_demod_reset(st); | ||
1152 | |||
1153 | return demod; | ||
1154 | |||
1155 | error: | ||
1156 | kfree(st); | ||
1157 | return NULL; | ||
1158 | } | ||
1159 | EXPORT_SYMBOL(dib7000m_attach); | ||
206 | 1160 | ||
207 | static struct dvb_frontend_ops dib7000m_ops = { | 1161 | static struct dvb_frontend_ops dib7000m_ops = { |
208 | .info = { | 1162 | .info = { |
diff --git a/drivers/media/dvb/frontends/dib7000m.h b/drivers/media/dvb/frontends/dib7000m.h index 45990e3a5cee..597e9cc2da62 100644 --- a/drivers/media/dvb/frontends/dib7000m.h +++ b/drivers/media/dvb/frontends/dib7000m.h | |||
@@ -32,12 +32,13 @@ struct dib7000m_config { | |||
32 | u8 quartz_direct; | 32 | u8 quartz_direct; |
33 | 33 | ||
34 | u8 input_clk_is_div_2; | 34 | u8 input_clk_is_div_2; |
35 | |||
36 | int (*agc_control) (struct dvb_frontend *, u8 before); | ||
35 | }; | 37 | }; |
36 | 38 | ||
37 | #define DEFAULT_DIB7000M_I2C_ADDRESS 18 | 39 | #define DEFAULT_DIB7000M_I2C_ADDRESS 18 |
38 | 40 | ||
39 | extern int dib7000m_attach(struct i2c_adapter *i2c_adap, int no_of_demods, u8 default_addr , u8 do_i2c_enum, struct dib7000m_config[], struct dvb_frontend*[]); | 41 | extern struct dvb_frontend * dib7000m_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000m_config *cfg); |
40 | |||
41 | extern struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); | 42 | extern struct i2c_adapter * dib7000m_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int); |
42 | 43 | ||
43 | /* TODO | 44 | /* TODO |
diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c index a18c8f45a2ee..61d28de30305 100644 --- a/drivers/media/dvb/frontends/dibx000_common.c +++ b/drivers/media/dvb/frontends/dibx000_common.c | |||
@@ -63,7 +63,7 @@ static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c | |||
63 | struct i2c_msg m[2 + num]; | 63 | struct i2c_msg m[2 + num]; |
64 | u8 tx_open[4], tx_close[4]; | 64 | u8 tx_open[4], tx_close[4]; |
65 | 65 | ||
66 | memset(m,0, sizeof(struct i2c_msg) * (2 + num)); | 66 | memset(m,0, sizeof(struct i2c_msg) * (2 + num)), |
67 | 67 | ||
68 | dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); | 68 | dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); |
69 | 69 | ||
diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h index bb0c65f8aee8..a1df604366c3 100644 --- a/drivers/media/dvb/frontends/dibx000_common.h +++ b/drivers/media/dvb/frontends/dibx000_common.h | |||
@@ -32,6 +32,13 @@ extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst); | |||
32 | #define BAND_LBAND 0x01 | 32 | #define BAND_LBAND 0x01 |
33 | #define BAND_UHF 0x02 | 33 | #define BAND_UHF 0x02 |
34 | #define BAND_VHF 0x04 | 34 | #define BAND_VHF 0x04 |
35 | #define BAND_SBAND 0x08 | ||
36 | #define BAND_FM 0x10 | ||
37 | |||
38 | #define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 115000 ? BAND_FM : \ | ||
39 | (freq_kHz) <= 250000 ? BAND_VHF : \ | ||
40 | (freq_kHz) <= 863000 ? BAND_UHF : \ | ||
41 | (freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND ) | ||
35 | 42 | ||
36 | struct dibx000_agc_config { | 43 | struct dibx000_agc_config { |
37 | /* defines the capabilities of this AGC-setting - using the BAND_-defines*/ | 44 | /* defines the capabilities of this AGC-setting - using the BAND_-defines*/ |
@@ -129,6 +136,7 @@ enum dibx000_adc_states { | |||
129 | 136 | ||
130 | /* I hope I can get rid of the following kludge in the near future */ | 137 | /* I hope I can get rid of the following kludge in the near future */ |
131 | struct dibx000_ofdm_channel { | 138 | struct dibx000_ofdm_channel { |
139 | u32 RF_kHz; | ||
132 | u8 Bw; | 140 | u8 Bw; |
133 | s16 nfft; | 141 | s16 nfft; |
134 | s16 guard; | 142 | s16 guard; |
@@ -138,9 +146,11 @@ struct dibx000_ofdm_channel { | |||
138 | s16 vit_alpha; | 146 | s16 vit_alpha; |
139 | s16 vit_code_rate_hp; | 147 | s16 vit_code_rate_hp; |
140 | s16 vit_code_rate_lp; | 148 | s16 vit_code_rate_lp; |
149 | u8 intlv_native; | ||
141 | }; | 150 | }; |
142 | 151 | ||
143 | #define FEP2DIB(fep,ch) \ | 152 | #define FEP2DIB(fep,ch) \ |
153 | (ch)->RF_kHz = (fep)->frequency / 1000; \ | ||
144 | (ch)->Bw = (fep)->u.ofdm.bandwidth; \ | 154 | (ch)->Bw = (fep)->u.ofdm.bandwidth; \ |
145 | (ch)->nfft = (fep)->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ? -1 : (fep)->u.ofdm.transmission_mode; \ | 155 | (ch)->nfft = (fep)->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ? -1 : (fep)->u.ofdm.transmission_mode; \ |
146 | (ch)->guard = (fep)->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ? -1 : (fep)->u.ofdm.guard_interval; \ | 156 | (ch)->guard = (fep)->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO ? -1 : (fep)->u.ofdm.guard_interval; \ |
@@ -149,7 +159,8 @@ struct dibx000_ofdm_channel { | |||
149 | (ch)->vit_select_hp = 1; \ | 159 | (ch)->vit_select_hp = 1; \ |
150 | (ch)->vit_alpha = 1; \ | 160 | (ch)->vit_alpha = 1; \ |
151 | (ch)->vit_code_rate_hp = (fep)->u.ofdm.code_rate_HP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_HP; \ | 161 | (ch)->vit_code_rate_hp = (fep)->u.ofdm.code_rate_HP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_HP; \ |
152 | (ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP; | 162 | (ch)->vit_code_rate_lp = (fep)->u.ofdm.code_rate_LP == FEC_AUTO ? -1 : (fep)->u.ofdm.code_rate_LP; \ |
163 | (ch)->intlv_native = 1; | ||
153 | 164 | ||
154 | #define INIT_OFDM_CHANNEL(ch) do {\ | 165 | #define INIT_OFDM_CHANNEL(ch) do {\ |
155 | (ch)->Bw = 0; \ | 166 | (ch)->Bw = 0; \ |