diff options
author | Olivier Grenie <Olivier.Grenie@dibcom.fr> | 2009-12-04 11:27:57 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-12-15 21:18:16 -0500 |
commit | 03245a5ee69a5faa99b020fe1aca9bafe10c46a9 (patch) | |
tree | 0937b4966ff1f5e09bfcd38fd38bc55e7ac2abef /drivers/media/dvb/frontends | |
parent | 20232c4791507189d4e9499f81632a1ce434f2a4 (diff) |
V4L/DVB (13583): DiB8090: Add the DiB0090 tuner driver and STK8096GP-board
This patchs adds support for the DiBcom DiB0090 RF tuner and for
DiBcom's reference design STK8096GP. Small extracts of the DiB0070 and
the DiB8000-driver into a common codebase.
Signed-off-by: Patrick Boettcher <pboettcher@kernellabs.com>
Signed-off-by: Olivier Grenie <Olivier.Grenie@dibcom.fr>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/frontends')
-rw-r--r-- | drivers/media/dvb/frontends/Kconfig | 9 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/dib0070.c | 654 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/dib0070.h | 4 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/dib0090.c | 1525 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/dib0090.h | 114 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/dib8000.c | 64 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/dib8000.h | 32 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/dibx000_common.c | 15 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/dibx000_common.h | 71 |
10 files changed, 2150 insertions, 339 deletions
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 58aac018f109..a3b8b697349b 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig | |||
@@ -526,6 +526,15 @@ config DVB_TUNER_DIB0070 | |||
526 | This device is only used inside a SiP called together with a | 526 | This device is only used inside a SiP called together with a |
527 | demodulator for now. | 527 | demodulator for now. |
528 | 528 | ||
529 | config DVB_TUNER_DIB0090 | ||
530 | tristate "DiBcom DiB0090 silicon base-band tuner" | ||
531 | depends on I2C | ||
532 | default m if DVB_FE_CUSTOMISE | ||
533 | help | ||
534 | A driver for the silicon baseband tuner DiB0090 from DiBcom. | ||
535 | This device is only used inside a SiP called together with a | ||
536 | demodulator for now. | ||
537 | |||
529 | comment "SEC control devices for DVB-S" | 538 | comment "SEC control devices for DVB-S" |
530 | depends on DVB_CORE | 539 | depends on DVB_CORE |
531 | 540 | ||
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 823482535d11..47575cc7b699 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile | |||
@@ -55,6 +55,7 @@ obj-$(CONFIG_DVB_TDA10086) += tda10086.o | |||
55 | obj-$(CONFIG_DVB_TDA826X) += tda826x.o | 55 | obj-$(CONFIG_DVB_TDA826X) += tda826x.o |
56 | obj-$(CONFIG_DVB_TDA8261) += tda8261.o | 56 | obj-$(CONFIG_DVB_TDA8261) += tda8261.o |
57 | obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o | 57 | obj-$(CONFIG_DVB_TUNER_DIB0070) += dib0070.o |
58 | obj-$(CONFIG_DVB_TUNER_DIB0090) += dib0090.o | ||
58 | obj-$(CONFIG_DVB_TUA6100) += tua6100.o | 59 | obj-$(CONFIG_DVB_TUA6100) += tua6100.o |
59 | obj-$(CONFIG_DVB_S5H1409) += s5h1409.o | 60 | obj-$(CONFIG_DVB_S5H1409) += s5h1409.o |
60 | obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o | 61 | obj-$(CONFIG_DVB_TUNER_ITD1000) += itd1000.o |
diff --git a/drivers/media/dvb/frontends/dib0070.c b/drivers/media/dvb/frontends/dib0070.c index 2be17b93e0bd..81860b2cfe98 100644 --- a/drivers/media/dvb/frontends/dib0070.c +++ b/drivers/media/dvb/frontends/dib0070.c | |||
@@ -49,21 +49,6 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | |||
49 | #define DIB0070_P1G 0x03 | 49 | #define DIB0070_P1G 0x03 |
50 | #define DIB0070S_P1A 0x02 | 50 | #define DIB0070S_P1A 0x02 |
51 | 51 | ||
52 | enum frontend_tune_state { | ||
53 | CT_TUNER_START = 10, | ||
54 | CT_TUNER_STEP_0, | ||
55 | CT_TUNER_STEP_1, | ||
56 | CT_TUNER_STEP_2, | ||
57 | CT_TUNER_STEP_3, | ||
58 | CT_TUNER_STEP_4, | ||
59 | CT_TUNER_STEP_5, | ||
60 | CT_TUNER_STEP_6, | ||
61 | CT_TUNER_STEP_7, | ||
62 | CT_TUNER_STOP, | ||
63 | }; | ||
64 | |||
65 | #define FE_CALLBACK_TIME_NEVER 0xffffffff | ||
66 | |||
67 | struct dib0070_state { | 52 | struct dib0070_state { |
68 | struct i2c_adapter *i2c; | 53 | struct i2c_adapter *i2c; |
69 | struct dvb_frontend *fe; | 54 | struct dvb_frontend *fe; |
@@ -71,10 +56,10 @@ struct dib0070_state { | |||
71 | u16 wbd_ff_offset; | 56 | u16 wbd_ff_offset; |
72 | u8 revision; | 57 | u8 revision; |
73 | 58 | ||
74 | enum frontend_tune_state tune_state; | 59 | enum frontend_tune_state tune_state; |
75 | u32 current_rf; | 60 | u32 current_rf; |
76 | 61 | ||
77 | /* for the captrim binary search */ | 62 | /* for the captrim binary search */ |
78 | s8 step; | 63 | s8 step; |
79 | u16 adc_diff; | 64 | u16 adc_diff; |
80 | 65 | ||
@@ -85,7 +70,7 @@ struct dib0070_state { | |||
85 | const struct dib0070_tuning *current_tune_table_index; | 70 | const struct dib0070_tuning *current_tune_table_index; |
86 | const struct dib0070_lna_match *lna_match; | 71 | const struct dib0070_lna_match *lna_match; |
87 | 72 | ||
88 | u8 wbd_gain_current; | 73 | u8 wbd_gain_current; |
89 | u16 wbd_offset_3_3[2]; | 74 | u16 wbd_offset_3_3[2]; |
90 | }; | 75 | }; |
91 | 76 | ||
@@ -93,8 +78,8 @@ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) | |||
93 | { | 78 | { |
94 | u8 b[2]; | 79 | u8 b[2]; |
95 | struct i2c_msg msg[2] = { | 80 | struct i2c_msg msg[2] = { |
96 | {.addr = state->cfg->i2c_address,.flags = 0,.buf = ®,.len = 1}, | 81 | { .addr = state->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 }, |
97 | {.addr = state->cfg->i2c_address,.flags = I2C_M_RD,.buf = b,.len = 2}, | 82 | { .addr = state->cfg->i2c_address, .flags = I2C_M_RD, .buf = b, .len = 2 }, |
98 | }; | 83 | }; |
99 | if (i2c_transfer(state->i2c, msg, 2) != 2) { | 84 | if (i2c_transfer(state->i2c, msg, 2) != 2) { |
100 | printk(KERN_WARNING "DiB0070 I2C read failed\n"); | 85 | printk(KERN_WARNING "DiB0070 I2C read failed\n"); |
@@ -106,7 +91,7 @@ static uint16_t dib0070_read_reg(struct dib0070_state *state, u8 reg) | |||
106 | static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) | 91 | static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) |
107 | { | 92 | { |
108 | u8 b[3] = { reg, val >> 8, val & 0xff }; | 93 | u8 b[3] = { reg, val >> 8, val & 0xff }; |
109 | struct i2c_msg msg = {.addr = state->cfg->i2c_address,.flags = 0,.buf = b,.len = 3 }; | 94 | struct i2c_msg msg = { .addr = state->cfg->i2c_address, .flags = 0, .buf = b, .len = 3 }; |
110 | if (i2c_transfer(state->i2c, &msg, 1) != 1) { | 95 | if (i2c_transfer(state->i2c, &msg, 1) != 1) { |
111 | printk(KERN_WARNING "DiB0070 I2C write failed\n"); | 96 | printk(KERN_WARNING "DiB0070 I2C write failed\n"); |
112 | return -EREMOTEIO; | 97 | return -EREMOTEIO; |
@@ -124,30 +109,30 @@ static int dib0070_write_reg(struct dib0070_state *state, u8 reg, u16 val) | |||
124 | 109 | ||
125 | static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) | 110 | static int dib0070_set_bandwidth(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) |
126 | { | 111 | { |
127 | struct dib0070_state *state = fe->tuner_priv; | 112 | struct dib0070_state *state = fe->tuner_priv; |
128 | u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff; | 113 | u16 tmp = dib0070_read_reg(state, 0x02) & 0x3fff; |
129 | 114 | ||
130 | if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 7000) | 115 | if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 7000) |
131 | tmp |= (0 << 14); | 116 | tmp |= (0 << 14); |
132 | else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 6000) | 117 | else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 6000) |
133 | tmp |= (1 << 14); | 118 | tmp |= (1 << 14); |
134 | else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 > 5000) | 119 | else if (state->fe->dtv_property_cache.bandwidth_hz/1000 > 5000) |
135 | tmp |= (2 << 14); | 120 | tmp |= (2 << 14); |
136 | else | 121 | else |
137 | tmp |= (3 << 14); | 122 | tmp |= (3 << 14); |
138 | 123 | ||
139 | dib0070_write_reg(state, 0x02, tmp); | 124 | dib0070_write_reg(state, 0x02, tmp); |
140 | 125 | ||
141 | /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */ | 126 | /* sharpen the BB filter in ISDB-T to have higher immunity to adjacent channels */ |
142 | if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) { | 127 | if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) { |
143 | u16 value = dib0070_read_reg(state, 0x17); | 128 | u16 value = dib0070_read_reg(state, 0x17); |
144 | 129 | ||
145 | dib0070_write_reg(state, 0x17, value & 0xfffc); | 130 | dib0070_write_reg(state, 0x17, value & 0xfffc); |
146 | tmp = dib0070_read_reg(state, 0x01) & 0x01ff; | 131 | tmp = dib0070_read_reg(state, 0x01) & 0x01ff; |
147 | dib0070_write_reg(state, 0x01, tmp | (60 << 9)); | 132 | dib0070_write_reg(state, 0x01, tmp | (60 << 9)); |
148 | 133 | ||
149 | dib0070_write_reg(state, 0x17, value); | 134 | dib0070_write_reg(state, 0x17, value); |
150 | } | 135 | } |
151 | return 0; | 136 | return 0; |
152 | } | 137 | } |
153 | 138 | ||
@@ -160,14 +145,14 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state | |||
160 | if (*tune_state == CT_TUNER_STEP_0) { | 145 | if (*tune_state == CT_TUNER_STEP_0) { |
161 | 146 | ||
162 | dib0070_write_reg(state, 0x0f, 0xed10); | 147 | dib0070_write_reg(state, 0x0f, 0xed10); |
163 | dib0070_write_reg(state, 0x17, 0x0034); | 148 | dib0070_write_reg(state, 0x17, 0x0034); |
164 | 149 | ||
165 | dib0070_write_reg(state, 0x18, 0x0032); | 150 | dib0070_write_reg(state, 0x18, 0x0032); |
166 | state->step = state->captrim = state->fcaptrim = 64; | 151 | state->step = state->captrim = state->fcaptrim = 64; |
167 | state->adc_diff = 3000; | 152 | state->adc_diff = 3000; |
168 | ret = 20; | 153 | ret = 20; |
169 | 154 | ||
170 | *tune_state = CT_TUNER_STEP_1; | 155 | *tune_state = CT_TUNER_STEP_1; |
171 | } else if (*tune_state == CT_TUNER_STEP_1) { | 156 | } else if (*tune_state == CT_TUNER_STEP_1) { |
172 | state->step /= 2; | 157 | state->step /= 2; |
173 | dib0070_write_reg(state, 0x14, state->lo4 | state->captrim); | 158 | dib0070_write_reg(state, 0x14, state->lo4 | state->captrim); |
@@ -178,7 +163,7 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state | |||
178 | 163 | ||
179 | adc = dib0070_read_reg(state, 0x19); | 164 | adc = dib0070_read_reg(state, 0x19); |
180 | 165 | ||
181 | dprintk("CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc * (u32) 1800 / (u32) 1024); | 166 | dprintk( "CAPTRIM=%hd; ADC = %hd (ADC) & %dmV", state->captrim, adc, (u32) adc*(u32)1800/(u32)1024); |
182 | 167 | ||
183 | if (adc >= 400) { | 168 | if (adc >= 400) { |
184 | adc -= 400; | 169 | adc -= 400; |
@@ -189,10 +174,12 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state | |||
189 | } | 174 | } |
190 | 175 | ||
191 | if (adc < state->adc_diff) { | 176 | if (adc < state->adc_diff) { |
192 | dprintk("CAPTRIM=%hd is closer to target (%hd/%hd)", state->captrim, adc, state->adc_diff); | 177 | dprintk( "CAPTRIM=%hd is closer to target (%hd/%hd)", state->captrim, adc, state->adc_diff); |
193 | state->adc_diff = adc; | 178 | state->adc_diff = adc; |
194 | state->fcaptrim = state->captrim; | 179 | state->fcaptrim = state->captrim; |
195 | 180 | ||
181 | |||
182 | |||
196 | } | 183 | } |
197 | state->captrim += (step_sign * state->step); | 184 | state->captrim += (step_sign * state->step); |
198 | 185 | ||
@@ -213,8 +200,8 @@ static int dib0070_captrim(struct dib0070_state *state, enum frontend_tune_state | |||
213 | static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt) | 200 | static int dib0070_set_ctrl_lo5(struct dvb_frontend *fe, u8 vco_bias_trim, u8 hf_div_trim, u8 cp_current, u8 third_order_filt) |
214 | { | 201 | { |
215 | struct dib0070_state *state = fe->tuner_priv; | 202 | struct dib0070_state *state = fe->tuner_priv; |
216 | u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0); | 203 | u16 lo5 = (third_order_filt << 14) | (0 << 13) | (1 << 12) | (3 << 9) | (cp_current << 6) | (hf_div_trim << 3) | (vco_bias_trim << 0); |
217 | dprintk("CTRL_LO5: 0x%x", lo5); | 204 | dprintk( "CTRL_LO5: 0x%x", lo5); |
218 | return dib0070_write_reg(state, 0x15, lo5); | 205 | return dib0070_write_reg(state, 0x15, lo5); |
219 | } | 206 | } |
220 | 207 | ||
@@ -227,171 +214,175 @@ void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open) | |||
227 | dib0070_write_reg(state, 0x1a, 0x0000); | 214 | dib0070_write_reg(state, 0x1a, 0x0000); |
228 | } else { | 215 | } else { |
229 | dib0070_write_reg(state, 0x1b, 0x4112); | 216 | dib0070_write_reg(state, 0x1b, 0x4112); |
230 | if (state->cfg->vga_filter != 0) { | 217 | if (state->cfg->vga_filter != 0) { |
231 | dib0070_write_reg(state, 0x1a, state->cfg->vga_filter); | 218 | dib0070_write_reg(state, 0x1a, state->cfg->vga_filter); |
232 | dprintk("vga filter register is set to %x", state->cfg->vga_filter); | 219 | dprintk( "vga filter register is set to %x", state->cfg->vga_filter); |
233 | } else | 220 | } else |
234 | dib0070_write_reg(state, 0x1a, 0x0009); | 221 | dib0070_write_reg(state, 0x1a, 0x0009); |
235 | } | 222 | } |
236 | } | 223 | } |
237 | 224 | ||
238 | EXPORT_SYMBOL(dib0070_ctrl_agc_filter); | 225 | EXPORT_SYMBOL(dib0070_ctrl_agc_filter); |
239 | struct dib0070_tuning { | 226 | struct dib0070_tuning { |
240 | u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ | 227 | u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ |
241 | u8 switch_trim; | 228 | u8 switch_trim; |
242 | u8 vco_band; | 229 | u8 vco_band; |
243 | u8 hfdiv; | 230 | u8 hfdiv; |
244 | u8 vco_multi; | 231 | u8 vco_multi; |
245 | u8 presc; | 232 | u8 presc; |
246 | u8 wbdmux; | 233 | u8 wbdmux; |
247 | u16 tuner_enable; | 234 | u16 tuner_enable; |
248 | }; | 235 | }; |
249 | 236 | ||
250 | struct dib0070_lna_match { | 237 | struct dib0070_lna_match { |
251 | u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ | 238 | u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ |
252 | u8 lna_band; | 239 | u8 lna_band; |
253 | }; | 240 | }; |
254 | 241 | ||
255 | static const struct dib0070_tuning dib0070s_tuning_table[] = { | 242 | static const struct dib0070_tuning dib0070s_tuning_table[] = { |
256 | {570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800}, /* UHF */ | 243 | { 570000, 2, 1, 3, 6, 6, 2, 0x4000 | 0x0800 }, /* UHF */ |
257 | {700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800}, | 244 | { 700000, 2, 0, 2, 4, 2, 2, 0x4000 | 0x0800 }, |
258 | {863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800}, | 245 | { 863999, 2, 1, 2, 4, 2, 2, 0x4000 | 0x0800 }, |
259 | {1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400}, /* LBAND */ | 246 | { 1500000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND */ |
260 | {1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400}, | 247 | { 1600000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, |
261 | {2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400}, | 248 | { 2000000, 0, 1, 1, 2, 2, 4, 0x2000 | 0x0400 }, |
262 | {0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000}, /* SBAND */ | 249 | { 0xffffffff, 0, 0, 8, 1, 2, 1, 0x8000 | 0x1000 }, /* SBAND */ |
263 | }; | 250 | }; |
264 | 251 | ||
265 | static const struct dib0070_tuning dib0070_tuning_table[] = { | 252 | static const struct dib0070_tuning dib0070_tuning_table[] = { |
266 | {115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000}, /* FM below 92MHz cannot be tuned */ | 253 | { 115000, 1, 0, 7, 24, 2, 1, 0x8000 | 0x1000 }, /* FM below 92MHz cannot be tuned */ |
267 | {179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000}, /* VHF */ | 254 | { 179500, 1, 0, 3, 16, 2, 1, 0x8000 | 0x1000 }, /* VHF */ |
268 | {189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000}, | 255 | { 189999, 1, 1, 3, 16, 2, 1, 0x8000 | 0x1000 }, |
269 | {250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000}, | 256 | { 250000, 1, 0, 6, 12, 2, 1, 0x8000 | 0x1000 }, |
270 | {569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800}, /* UHF */ | 257 | { 569999, 2, 1, 5, 6, 2, 2, 0x4000 | 0x0800 }, /* UHF */ |
271 | {699999, 2, 0, 1, 4, 2, 2, 0x4000 | 0x0800}, | 258 | { 699999, 2, 0 ,1, 4, 2, 2, 0x4000 | 0x0800 }, |
272 | {863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800}, | 259 | { 863999, 2, 1, 1, 4, 2, 2, 0x4000 | 0x0800 }, |
273 | {0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400}, /* LBAND or everything higher than UHF */ | 260 | { 0xffffffff, 0, 1, 0, 2, 2, 4, 0x2000 | 0x0400 }, /* LBAND or everything higher than UHF */ |
274 | }; | 261 | }; |
275 | 262 | ||
276 | static const struct dib0070_lna_match dib0070_lna_flip_chip[] = { | 263 | static const struct dib0070_lna_match dib0070_lna_flip_chip[] = { |
277 | {180000, 0}, /* VHF */ | 264 | { 180000, 0 }, /* VHF */ |
278 | {188000, 1}, | 265 | { 188000, 1 }, |
279 | {196400, 2}, | 266 | { 196400, 2 }, |
280 | {250000, 3}, | 267 | { 250000, 3 }, |
281 | {550000, 0}, /* UHF */ | 268 | { 550000, 0 }, /* UHF */ |
282 | {590000, 1}, | 269 | { 590000, 1 }, |
283 | {666000, 3}, | 270 | { 666000, 3 }, |
284 | {864000, 5}, | 271 | { 864000, 5 }, |
285 | {1500000, 0}, /* LBAND or everything higher than UHF */ | 272 | { 1500000, 0 }, /* LBAND or everything higher than UHF */ |
286 | {1600000, 1}, | 273 | { 1600000, 1 }, |
287 | {2000000, 3}, | 274 | { 2000000, 3 }, |
288 | {0xffffffff, 7}, | 275 | { 0xffffffff, 7 }, |
289 | }; | 276 | }; |
290 | 277 | ||
291 | static const struct dib0070_lna_match dib0070_lna[] = { | 278 | static const struct dib0070_lna_match dib0070_lna[] = { |
292 | {180000, 0}, /* VHF */ | 279 | { 180000, 0 }, /* VHF */ |
293 | {188000, 1}, | 280 | { 188000, 1 }, |
294 | {196400, 2}, | 281 | { 196400, 2 }, |
295 | {250000, 3}, | 282 | { 250000, 3 }, |
296 | {550000, 2}, /* UHF */ | 283 | { 550000, 2 }, /* UHF */ |
297 | {650000, 3}, | 284 | { 650000, 3 }, |
298 | {750000, 5}, | 285 | { 750000, 5 }, |
299 | {850000, 6}, | 286 | { 850000, 6 }, |
300 | {864000, 7}, | 287 | { 864000, 7 }, |
301 | {1500000, 0}, /* LBAND or everything higher than UHF */ | 288 | { 1500000, 0 }, /* LBAND or everything higher than UHF */ |
302 | {1600000, 1}, | 289 | { 1600000, 1 }, |
303 | {2000000, 3}, | 290 | { 2000000, 3 }, |
304 | {0xffffffff, 7}, | 291 | { 0xffffffff, 7 }, |
305 | }; | 292 | }; |
306 | 293 | ||
307 | #define LPF 100 // define for the loop filter 100kHz by default 16-07-06 | 294 | #define LPF 100 // define for the loop filter 100kHz by default 16-07-06 |
308 | static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) | 295 | static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch) |
309 | { | 296 | { |
310 | struct dib0070_state *state = fe->tuner_priv; | 297 | struct dib0070_state *state = fe->tuner_priv; |
311 | 298 | ||
312 | const struct dib0070_tuning *tune; | 299 | const struct dib0070_tuning *tune; |
313 | const struct dib0070_lna_match *lna_match; | 300 | const struct dib0070_lna_match *lna_match; |
314 | 301 | ||
315 | enum frontend_tune_state *tune_state = &state->tune_state; | 302 | enum frontend_tune_state *tune_state = &state->tune_state; |
316 | int ret = 10; /* 1ms is the default delay most of the time */ | 303 | int ret = 10; /* 1ms is the default delay most of the time */ |
317 | 304 | ||
318 | u8 band = (u8) BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000); | 305 | u8 band = (u8)BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency/1000); |
319 | u32 freq = fe->dtv_property_cache.frequency / 1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf); | 306 | u32 freq = fe->dtv_property_cache.frequency/1000 + (band == BAND_VHF ? state->cfg->freq_offset_khz_vhf : state->cfg->freq_offset_khz_uhf); |
320 | 307 | ||
321 | #ifdef CONFIG_SYS_ISDBT | 308 | #ifdef CONFIG_SYS_ISDBT |
322 | if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1) | 309 | if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1) |
323 | if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) | 310 | if (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) |
324 | && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))) | 311 | && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1))) |
325 | || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) | 312 | || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) |
326 | && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2))) | 313 | && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == (state->fe->dtv_property_cache.isdbt_sb_segment_count / 2))) |
327 | || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) | 314 | || (((state->fe->dtv_property_cache.isdbt_sb_segment_count % 2) == 0) |
328 | && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))) | 315 | && (state->fe->dtv_property_cache.isdbt_sb_segment_idx == ((state->fe->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))) |
329 | freq += 850; | 316 | freq += 850; |
330 | #endif | 317 | #endif |
318 | if (state->current_rf != freq) { | ||
319 | |||
320 | switch (state->revision) { | ||
321 | case DIB0070S_P1A: | ||
322 | tune = dib0070s_tuning_table; | ||
323 | lna_match = dib0070_lna; | ||
324 | break; | ||
325 | default: | ||
326 | tune = dib0070_tuning_table; | ||
327 | if (state->cfg->flip_chip) | ||
328 | lna_match = dib0070_lna_flip_chip; | ||
329 | else | ||
330 | lna_match = dib0070_lna; | ||
331 | break; | ||
332 | } | ||
333 | while (freq > tune->max_freq) /* find the right one */ | ||
334 | tune++; | ||
335 | while (freq > lna_match->max_freq) /* find the right one */ | ||
336 | lna_match++; | ||
337 | |||
338 | state->current_tune_table_index = tune; | ||
339 | state->lna_match = lna_match; | ||
340 | } | ||
341 | |||
342 | if (*tune_state == CT_TUNER_START) { | ||
343 | dprintk( "Tuning for Band: %hd (%d kHz)", band, freq); | ||
331 | if (state->current_rf != freq) { | 344 | if (state->current_rf != freq) { |
345 | u8 REFDIV; | ||
346 | u32 FBDiv, Rest, FREF, VCOF_kHz; | ||
347 | u8 Den; | ||
332 | 348 | ||
333 | switch (state->revision) { | 349 | state->current_rf = freq; |
334 | case DIB0070S_P1A: | 350 | state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7); |
335 | tune = dib0070s_tuning_table; | ||
336 | lna_match = dib0070_lna; | ||
337 | break; | ||
338 | default: | ||
339 | tune = dib0070_tuning_table; | ||
340 | if (state->cfg->flip_chip) | ||
341 | lna_match = dib0070_lna_flip_chip; | ||
342 | else | ||
343 | lna_match = dib0070_lna; | ||
344 | break; | ||
345 | } | ||
346 | while (freq > tune->max_freq) /* find the right one */ | ||
347 | tune++; | ||
348 | while (freq > lna_match->max_freq) /* find the right one */ | ||
349 | lna_match++; | ||
350 | 351 | ||
351 | state->current_tune_table_index = tune; | ||
352 | state->lna_match = lna_match; | ||
353 | } | ||
354 | 352 | ||
355 | if (*tune_state == CT_TUNER_START) { | 353 | dib0070_write_reg(state, 0x17, 0x30); |
356 | dprintk("Tuning for Band: %hd (%d kHz)", band, freq); | 354 | |
357 | if (state->current_rf != freq) { | 355 | |
358 | u8 REFDIV; | 356 | VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2; |
359 | u32 FBDiv, Rest, FREF, VCOF_kHz; | 357 | |
360 | u8 Den; | 358 | switch (band) { |
361 | 359 | case BAND_VHF: | |
362 | state->current_rf = freq; | 360 | REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000); |
363 | state->lo4 = (state->current_tune_table_index->vco_band << 11) | (state->current_tune_table_index->hfdiv << 7); | 361 | break; |
364 | 362 | case BAND_FM: | |
365 | dib0070_write_reg(state, 0x17, 0x30); | 363 | REFDIV = (u8) ((state->cfg->clock_khz) / 1000); |
366 | 364 | break; | |
367 | VCOF_kHz = state->current_tune_table_index->vco_multi * freq * 2; | 365 | default: |
368 | 366 | REFDIV = (u8) ( state->cfg->clock_khz / 10000); | |
369 | switch (band) { | 367 | break; |
370 | case BAND_VHF: | 368 | } |
371 | REFDIV = (u8) ((state->cfg->clock_khz + 9999) / 10000); | 369 | FREF = state->cfg->clock_khz / REFDIV; |
372 | break; | 370 | |
373 | case BAND_FM: | 371 | |
374 | REFDIV = (u8) ((state->cfg->clock_khz) / 1000); | 372 | |
375 | break; | 373 | switch (state->revision) { |
376 | default: | 374 | case DIB0070S_P1A: |
377 | REFDIV = (u8) (state->cfg->clock_khz / 10000); | 375 | FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF); |
378 | break; | 376 | Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF; |
379 | } | 377 | break; |
380 | FREF = state->cfg->clock_khz / REFDIV; | 378 | |
381 | 379 | case DIB0070_P1G: | |
382 | switch (state->revision) { | 380 | case DIB0070_P1F: |
383 | case DIB0070S_P1A: | 381 | default: |
384 | FBDiv = (VCOF_kHz / state->current_tune_table_index->presc / FREF); | 382 | FBDiv = (freq / (FREF / 2)); |
385 | Rest = (VCOF_kHz / state->current_tune_table_index->presc) - FBDiv * FREF; | 383 | Rest = 2 * freq - FBDiv * FREF; |
386 | break; | 384 | break; |
387 | 385 | } | |
388 | case DIB0070_P1G: | ||
389 | case DIB0070_P1F: | ||
390 | default: | ||
391 | FBDiv = (freq / (FREF / 2)); | ||
392 | Rest = 2 * freq - FBDiv * FREF; | ||
393 | break; | ||
394 | } | ||
395 | 386 | ||
396 | if (Rest < LPF) | 387 | if (Rest < LPF) |
397 | Rest = 0; | 388 | Rest = 0; |
@@ -402,98 +393,102 @@ static int dib0070_tune_digital(struct dvb_frontend *fe, struct dvb_frontend_par | |||
402 | FBDiv += 1; | 393 | FBDiv += 1; |
403 | } else if (Rest > (FREF - 2 * LPF)) | 394 | } else if (Rest > (FREF - 2 * LPF)) |
404 | Rest = FREF - 2 * LPF; | 395 | Rest = FREF - 2 * LPF; |
405 | Rest = (Rest * 6528) / (FREF / 10); | 396 | Rest = (Rest * 6528) / (FREF / 10); |
406 | 397 | ||
407 | Den = 1; | 398 | Den = 1; |
408 | if (Rest > 0) { | 399 | if (Rest > 0) { |
409 | state->lo4 |= (1 << 14) | (1 << 12); | 400 | state->lo4 |= (1 << 14) | (1 << 12); |
410 | Den = 255; | 401 | Den = 255; |
411 | } | 402 | } |
412 | 403 | ||
413 | dib0070_write_reg(state, 0x11, (u16) FBDiv); | ||
414 | dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV); | ||
415 | dib0070_write_reg(state, 0x13, (u16) Rest); | ||
416 | 404 | ||
417 | if (state->revision == DIB0070S_P1A) { | 405 | dib0070_write_reg(state, 0x11, (u16)FBDiv); |
406 | dib0070_write_reg(state, 0x12, (Den << 8) | REFDIV); | ||
407 | dib0070_write_reg(state, 0x13, (u16) Rest); | ||
418 | 408 | ||
419 | if (band == BAND_SBAND) { | 409 | if (state->revision == DIB0070S_P1A) { |
420 | dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); | 410 | |
421 | dib0070_write_reg(state, 0x1d, 0xFFFF); | 411 | if (band == BAND_SBAND) { |
422 | } else | 412 | dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); |
423 | dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1); | 413 | dib0070_write_reg(state, 0x1d,0xFFFF); |
424 | } | 414 | } else |
415 | dib0070_set_ctrl_lo5(fe, 5, 4, 3, 1); | ||
416 | } | ||
425 | 417 | ||
426 | dib0070_write_reg(state, 0x20, | 418 | dib0070_write_reg(state, 0x20, |
427 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable); | 419 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001 | state->current_tune_table_index->tuner_enable); |
428 | 420 | ||
429 | dprintk("REFDIV: %hd, FREF: %d", REFDIV, FREF); | 421 | dprintk( "REFDIV: %hd, FREF: %d", REFDIV, FREF); |
430 | dprintk("FBDIV: %d, Rest: %d", FBDiv, Rest); | 422 | dprintk( "FBDIV: %d, Rest: %d", FBDiv, Rest); |
431 | dprintk("Num: %hd, Den: %hd, SD: %hd", (u16) Rest, Den, (state->lo4 >> 12) & 0x1); | 423 | dprintk( "Num: %hd, Den: %hd, SD: %hd",(u16) Rest, Den, (state->lo4 >> 12) & 0x1); |
432 | dprintk("HFDIV code: %hd", state->current_tune_table_index->hfdiv); | 424 | dprintk( "HFDIV code: %hd", state->current_tune_table_index->hfdiv); |
433 | dprintk("VCO = %hd", state->current_tune_table_index->vco_band); | 425 | dprintk( "VCO = %hd", state->current_tune_table_index->vco_band); |
434 | dprintk("VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq); | 426 | dprintk( "VCOF: ((%hd*%d) << 1))", state->current_tune_table_index->vco_multi, freq); |
435 | 427 | ||
436 | *tune_state = CT_TUNER_STEP_0; | 428 | *tune_state = CT_TUNER_STEP_0; |
437 | } else { /* we are already tuned to this frequency - the configuration is correct */ | 429 | } else { /* we are already tuned to this frequency - the configuration is correct */ |
438 | ret = 50; /* wakeup time */ | 430 | ret = 50; /* wakeup time */ |
439 | *tune_state = CT_TUNER_STEP_5; | 431 | *tune_state = CT_TUNER_STEP_5; |
440 | } | 432 | } |
441 | } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) { | 433 | } else if ((*tune_state > CT_TUNER_START) && (*tune_state < CT_TUNER_STEP_4)) { |
442 | 434 | ||
443 | ret = dib0070_captrim(state, tune_state); | 435 | ret = dib0070_captrim(state, tune_state); |
444 | 436 | ||
445 | } else if (*tune_state == CT_TUNER_STEP_4) { | 437 | } else if (*tune_state == CT_TUNER_STEP_4) { |
446 | const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain; | 438 | const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain; |
447 | if (tmp != NULL) { | 439 | if (tmp != NULL) { |
448 | while (freq / 1000 > tmp->freq) /* find the right one */ | 440 | while (freq/1000 > tmp->freq) /* find the right one */ |
449 | tmp++; | 441 | tmp++; |
450 | dib0070_write_reg(state, 0x0f, | 442 | dib0070_write_reg(state, 0x0f, |
451 | (0 << 15) | (1 << 14) | (3 << 12) | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7) | (state-> | 443 | (0 << 15) | (1 << 14) | (3 << 12) | (tmp->wbd_gain_val << 9) | (0 << 8) | (1 << 7) | (state-> |
452 | current_tune_table_index-> | 444 | current_tune_table_index-> |
453 | wbdmux << 0)); | 445 | wbdmux << 0)); |
454 | state->wbd_gain_current = tmp->wbd_gain_val; | 446 | state->wbd_gain_current = tmp->wbd_gain_val; |
455 | } else { | 447 | } else { |
456 | dib0070_write_reg(state, 0x0f, | 448 | dib0070_write_reg(state, 0x0f, |
457 | (0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (state->current_tune_table_index-> | 449 | (0 << 15) | (1 << 14) | (3 << 12) | (6 << 9) | (0 << 8) | (1 << 7) | (state->current_tune_table_index-> |
458 | wbdmux << 0)); | 450 | wbdmux << 0)); |
459 | state->wbd_gain_current = 6; | 451 | state->wbd_gain_current = 6; |
460 | } | 452 | } |
461 | 453 | ||
462 | dib0070_write_reg(state, 0x06, 0x3fff); | 454 | dib0070_write_reg(state, 0x06, 0x3fff); |
463 | dib0070_write_reg(state, 0x07, | 455 | dib0070_write_reg(state, 0x07, |
464 | (state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0)); | 456 | (state->current_tune_table_index->switch_trim << 11) | (7 << 8) | (state->lna_match->lna_band << 3) | (3 << 0)); |
465 | dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127)); | 457 | dib0070_write_reg(state, 0x08, (state->lna_match->lna_band << 10) | (3 << 7) | (127)); |
466 | dib0070_write_reg(state, 0x0d, 0x0d80); | 458 | dib0070_write_reg(state, 0x0d, 0x0d80); |
467 | 459 | ||
468 | dib0070_write_reg(state, 0x18, 0x07ff); | ||
469 | dib0070_write_reg(state, 0x17, 0x0033); | ||
470 | 460 | ||
471 | *tune_state = CT_TUNER_STEP_5; | 461 | dib0070_write_reg(state, 0x18, 0x07ff); |
472 | } else if (*tune_state == CT_TUNER_STEP_5) { | 462 | dib0070_write_reg(state, 0x17, 0x0033); |
473 | dib0070_set_bandwidth(fe, ch); | 463 | |
474 | *tune_state = CT_TUNER_STOP; | 464 | |
475 | } else { | 465 | *tune_state = CT_TUNER_STEP_5; |
476 | ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */ | 466 | } else if (*tune_state == CT_TUNER_STEP_5) { |
477 | } | 467 | dib0070_set_bandwidth(fe, ch); |
478 | return ret; | 468 | *tune_state = CT_TUNER_STOP; |
469 | } else { | ||
470 | ret = FE_CALLBACK_TIME_NEVER; /* tuner finished, time to call again infinite */ | ||
471 | } | ||
472 | return ret; | ||
479 | } | 473 | } |
480 | 474 | ||
475 | |||
481 | static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) | 476 | static int dib0070_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) |
482 | { | 477 | { |
483 | struct dib0070_state *state = fe->tuner_priv; | 478 | struct dib0070_state *state = fe->tuner_priv; |
484 | uint32_t ret; | 479 | uint32_t ret; |
485 | 480 | ||
486 | state->tune_state = CT_TUNER_START; | 481 | state->tune_state = CT_TUNER_START; |
487 | 482 | ||
488 | do { | 483 | do { |
489 | ret = dib0070_tune_digital(fe, p); | 484 | ret = dib0070_tune_digital(fe, p); |
490 | if (ret != FE_CALLBACK_TIME_NEVER) | 485 | if (ret != FE_CALLBACK_TIME_NEVER) |
491 | msleep(ret / 10); | 486 | msleep(ret/10); |
492 | else | 487 | else |
493 | break; | 488 | break; |
494 | } while (state->tune_state != CT_TUNER_STOP); | 489 | } while (state->tune_state != CT_TUNER_STOP); |
495 | 490 | ||
496 | return 0; | 491 | return 0; |
497 | } | 492 | } |
498 | 493 | ||
499 | static int dib0070_wakeup(struct dvb_frontend *fe) | 494 | static int dib0070_wakeup(struct dvb_frontend *fe) |
@@ -512,92 +507,111 @@ static int dib0070_sleep(struct dvb_frontend *fe) | |||
512 | return 0; | 507 | return 0; |
513 | } | 508 | } |
514 | 509 | ||
515 | static const u16 dib0070_p1f_defaults[] = { | 510 | u8 dib0070_get_rf_output(struct dvb_frontend *fe) |
511 | { | ||
512 | struct dib0070_state *state = fe->tuner_priv; | ||
513 | return (dib0070_read_reg(state, 0x07) >> 11) & 0x3; | ||
514 | } | ||
515 | |||
516 | EXPORT_SYMBOL(dib0070_get_rf_output); | ||
517 | int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no) | ||
518 | { | ||
519 | struct dib0070_state *state = fe->tuner_priv; | ||
520 | u16 rxrf2 = dib0070_read_reg(state, 0x07) & 0xfe7ff; | ||
521 | if (no > 3) no = 3; | ||
522 | if (no < 1) no = 1; | ||
523 | return dib0070_write_reg(state, 0x07, rxrf2 | (no << 11)); | ||
524 | } | ||
525 | |||
526 | EXPORT_SYMBOL(dib0070_set_rf_output); | ||
527 | static const u16 dib0070_p1f_defaults[] = | ||
528 | |||
529 | { | ||
516 | 7, 0x02, | 530 | 7, 0x02, |
517 | 0x0008, | 531 | 0x0008, |
518 | 0x0000, | 532 | 0x0000, |
519 | 0x0000, | 533 | 0x0000, |
520 | 0x0000, | 534 | 0x0000, |
521 | 0x0000, | 535 | 0x0000, |
522 | 0x0002, | 536 | 0x0002, |
523 | 0x0100, | 537 | 0x0100, |
524 | 538 | ||
525 | 3, 0x0d, | 539 | 3, 0x0d, |
526 | 0x0d80, | 540 | 0x0d80, |
527 | 0x0001, | 541 | 0x0001, |
528 | 0x0000, | 542 | 0x0000, |
529 | 543 | ||
530 | 4, 0x11, | 544 | 4, 0x11, |
531 | 0x0000, | 545 | 0x0000, |
532 | 0x0103, | 546 | 0x0103, |
533 | 0x0000, | 547 | 0x0000, |
534 | 0x0000, | 548 | 0x0000, |
535 | 549 | ||
536 | 3, 0x16, | 550 | 3, 0x16, |
537 | 0x0004 | 0x0040, | 551 | 0x0004 | 0x0040, |
538 | 0x0030, | 552 | 0x0030, |
539 | 0x07ff, | 553 | 0x07ff, |
540 | 554 | ||
541 | 6, 0x1b, | 555 | 6, 0x1b, |
542 | 0x4112, | 556 | 0x4112, |
543 | 0xff00, | 557 | 0xff00, |
544 | 0xc07f, | 558 | 0xc07f, |
545 | 0x0000, | 559 | 0x0000, |
546 | 0x0180, | 560 | 0x0180, |
547 | 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001, | 561 | 0x4000 | 0x0800 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001, |
548 | 562 | ||
549 | 0, | 563 | 0, |
550 | }; | 564 | }; |
551 | 565 | ||
552 | static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain) | 566 | static u16 dib0070_read_wbd_offset(struct dib0070_state *state, u8 gain) |
553 | { | 567 | { |
554 | u16 tuner_en = dib0070_read_reg(state, 0x20); | 568 | u16 tuner_en = dib0070_read_reg(state, 0x20); |
555 | u16 offset; | 569 | u16 offset; |
556 | 570 | ||
557 | dib0070_write_reg(state, 0x18, 0x07ff); | 571 | dib0070_write_reg(state, 0x18, 0x07ff); |
558 | dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001); | 572 | dib0070_write_reg(state, 0x20, 0x0800 | 0x4000 | 0x0040 | 0x0020 | 0x0010 | 0x0008 | 0x0002 | 0x0001); |
559 | dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0)); | 573 | dib0070_write_reg(state, 0x0f, (1 << 14) | (2 << 12) | (gain << 9) | (1 << 8) | (1 << 7) | (0 << 0)); |
560 | msleep(9); | 574 | msleep(9); |
561 | offset = dib0070_read_reg(state, 0x19); | 575 | offset = dib0070_read_reg(state, 0x19); |
562 | dib0070_write_reg(state, 0x20, tuner_en); | 576 | dib0070_write_reg(state, 0x20, tuner_en); |
563 | return offset; | 577 | return offset; |
564 | } | 578 | } |
565 | 579 | ||
566 | static void dib0070_wbd_offset_calibration(struct dib0070_state *state) | 580 | static void dib0070_wbd_offset_calibration(struct dib0070_state *state) |
567 | { | 581 | { |
568 | u8 gain; | 582 | u8 gain; |
569 | for (gain = 6; gain < 8; gain++) { | 583 | for (gain = 6; gain < 8; gain++) { |
570 | state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2); | 584 | state->wbd_offset_3_3[gain - 6] = ((dib0070_read_wbd_offset(state, gain) * 8 * 18 / 33 + 1) / 2); |
571 | dprintk("Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain - 6]); | 585 | dprintk( "Gain: %d, WBDOffset (3.3V) = %hd", gain, state->wbd_offset_3_3[gain-6]); |
572 | } | 586 | } |
573 | } | 587 | } |
574 | 588 | ||
575 | u16 dib0070_wbd_offset(struct dvb_frontend *fe) | 589 | u16 dib0070_wbd_offset(struct dvb_frontend *fe) |
576 | { | 590 | { |
577 | struct dib0070_state *state = fe->tuner_priv; | 591 | struct dib0070_state *state = fe->tuner_priv; |
578 | const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain; | 592 | const struct dib0070_wbd_gain_cfg *tmp = state->cfg->wbd_gain; |
579 | u32 freq = fe->dtv_property_cache.frequency / 1000; | 593 | u32 freq = fe->dtv_property_cache.frequency/1000; |
580 | 594 | ||
581 | if (tmp != NULL) { | 595 | if (tmp != NULL) { |
582 | while (freq / 1000 > tmp->freq) /* find the right one */ | 596 | while (freq/1000 > tmp->freq) /* find the right one */ |
583 | tmp++; | 597 | tmp++; |
584 | state->wbd_gain_current = tmp->wbd_gain_val; | 598 | state->wbd_gain_current = tmp->wbd_gain_val; |
585 | } else | 599 | } else |
586 | state->wbd_gain_current = 6; | 600 | state->wbd_gain_current = 6; |
587 | 601 | ||
588 | return state->wbd_offset_3_3[state->wbd_gain_current - 6]; | 602 | return state->wbd_offset_3_3[state->wbd_gain_current - 6]; |
589 | } | 603 | } |
590 | |||
591 | EXPORT_SYMBOL(dib0070_wbd_offset); | 604 | EXPORT_SYMBOL(dib0070_wbd_offset); |
592 | 605 | ||
593 | #define pgm_read_word(w) (*w) | 606 | #define pgm_read_word(w) (*w) |
594 | static int dib0070_reset(struct dvb_frontend *fe) | 607 | static int dib0070_reset(struct dvb_frontend *fe) |
595 | { | 608 | { |
596 | struct dib0070_state *state = fe->tuner_priv; | 609 | struct dib0070_state *state = fe->tuner_priv; |
597 | u16 l, r, *n; | 610 | u16 l, r, *n; |
598 | 611 | ||
599 | HARD_RESET(state); | 612 | HARD_RESET(state); |
600 | 613 | ||
614 | |||
601 | #ifndef FORCE_SBAND_TUNER | 615 | #ifndef FORCE_SBAND_TUNER |
602 | if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1) | 616 | if ((dib0070_read_reg(state, 0x22) >> 9) & 0x1) |
603 | state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff; | 617 | state->revision = (dib0070_read_reg(state, 0x1f) >> 8) & 0xff; |
@@ -605,13 +619,13 @@ static int dib0070_reset(struct dvb_frontend *fe) | |||
605 | #else | 619 | #else |
606 | #warning forcing SBAND | 620 | #warning forcing SBAND |
607 | #endif | 621 | #endif |
608 | state->revision = DIB0070S_P1A; | 622 | state->revision = DIB0070S_P1A; |
609 | 623 | ||
610 | /* P1F or not */ | 624 | /* P1F or not */ |
611 | dprintk("Revision: %x", state->revision); | 625 | dprintk( "Revision: %x", state->revision); |
612 | 626 | ||
613 | if (state->revision == DIB0070_P1D) { | 627 | if (state->revision == DIB0070_P1D) { |
614 | dprintk("Error: this driver is not to be used meant for P1D or earlier"); | 628 | dprintk( "Error: this driver is not to be used meant for P1D or earlier"); |
615 | return -EINVAL; | 629 | return -EINVAL; |
616 | } | 630 | } |
617 | 631 | ||
@@ -620,7 +634,7 @@ static int dib0070_reset(struct dvb_frontend *fe) | |||
620 | while (l) { | 634 | while (l) { |
621 | r = pgm_read_word(n++); | 635 | r = pgm_read_word(n++); |
622 | do { | 636 | do { |
623 | dib0070_write_reg(state, (u8) r, pgm_read_word(n++)); | 637 | dib0070_write_reg(state, (u8)r, pgm_read_word(n++)); |
624 | r++; | 638 | r++; |
625 | } while (--l); | 639 | } while (--l); |
626 | l = pgm_read_word(n++); | 640 | l = pgm_read_word(n++); |
@@ -633,6 +647,7 @@ static int dib0070_reset(struct dvb_frontend *fe) | |||
633 | else | 647 | else |
634 | r = 2; | 648 | r = 2; |
635 | 649 | ||
650 | |||
636 | r |= state->cfg->osc_buffer_state << 3; | 651 | r |= state->cfg->osc_buffer_state << 3; |
637 | 652 | ||
638 | dib0070_write_reg(state, 0x10, r); | 653 | dib0070_write_reg(state, 0x10, r); |
@@ -643,16 +658,24 @@ static int dib0070_reset(struct dvb_frontend *fe) | |||
643 | dib0070_write_reg(state, 0x02, r | (1 << 5)); | 658 | dib0070_write_reg(state, 0x02, r | (1 << 5)); |
644 | } | 659 | } |
645 | 660 | ||
646 | if (state->revision == DIB0070S_P1A) | 661 | if (state->revision == DIB0070S_P1A) |
647 | dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); | 662 | dib0070_set_ctrl_lo5(fe, 2, 4, 3, 0); |
648 | else | 663 | else |
649 | dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter); | 664 | dib0070_set_ctrl_lo5(fe, 5, 4, state->cfg->charge_pump, state->cfg->enable_third_order_filter); |
650 | 665 | ||
651 | dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8); | 666 | dib0070_write_reg(state, 0x01, (54 << 9) | 0xc8); |
652 | 667 | ||
653 | dib0070_wbd_offset_calibration(state); | 668 | dib0070_wbd_offset_calibration(state); |
654 | 669 | ||
655 | return 0; | 670 | return 0; |
671 | } | ||
672 | |||
673 | static int dib0070_get_frequency(struct dvb_frontend *fe, u32 *frequency) | ||
674 | { | ||
675 | struct dib0070_state *state = fe->tuner_priv; | ||
676 | |||
677 | *frequency = 1000 * state->current_rf; | ||
678 | return 0; | ||
656 | } | 679 | } |
657 | 680 | ||
658 | static int dib0070_release(struct dvb_frontend *fe) | 681 | static int dib0070_release(struct dvb_frontend *fe) |
@@ -664,22 +687,22 @@ static int dib0070_release(struct dvb_frontend *fe) | |||
664 | 687 | ||
665 | static const struct dvb_tuner_ops dib0070_ops = { | 688 | static const struct dvb_tuner_ops dib0070_ops = { |
666 | .info = { | 689 | .info = { |
667 | .name = "DiBcom DiB0070", | 690 | .name = "DiBcom DiB0070", |
668 | .frequency_min = 45000000, | 691 | .frequency_min = 45000000, |
669 | .frequency_max = 860000000, | 692 | .frequency_max = 860000000, |
670 | .frequency_step = 1000, | 693 | .frequency_step = 1000, |
671 | }, | 694 | }, |
672 | .release = dib0070_release, | 695 | .release = dib0070_release, |
673 | 696 | ||
674 | .init = dib0070_wakeup, | 697 | .init = dib0070_wakeup, |
675 | .sleep = dib0070_sleep, | 698 | .sleep = dib0070_sleep, |
676 | .set_params = dib0070_tune, | 699 | .set_params = dib0070_tune, |
677 | 700 | ||
678 | // .get_frequency = dib0070_get_frequency, | 701 | .get_frequency = dib0070_get_frequency, |
679 | // .get_bandwidth = dib0070_get_bandwidth | 702 | // .get_bandwidth = dib0070_get_bandwidth |
680 | }; | 703 | }; |
681 | 704 | ||
682 | struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg) | 705 | struct dvb_frontend * dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg) |
683 | { | 706 | { |
684 | struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL); | 707 | struct dib0070_state *state = kzalloc(sizeof(struct dib0070_state), GFP_KERNEL); |
685 | if (state == NULL) | 708 | if (state == NULL) |
@@ -687,7 +710,7 @@ struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter | |||
687 | 710 | ||
688 | state->cfg = cfg; | 711 | state->cfg = cfg; |
689 | state->i2c = i2c; | 712 | state->i2c = i2c; |
690 | state->fe = fe; | 713 | state->fe = fe; |
691 | fe->tuner_priv = state; | 714 | fe->tuner_priv = state; |
692 | 715 | ||
693 | if (dib0070_reset(fe) != 0) | 716 | if (dib0070_reset(fe) != 0) |
@@ -699,12 +722,11 @@ struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter | |||
699 | fe->tuner_priv = state; | 722 | fe->tuner_priv = state; |
700 | return fe; | 723 | return fe; |
701 | 724 | ||
702 | free_mem: | 725 | free_mem: |
703 | kfree(state); | 726 | kfree(state); |
704 | fe->tuner_priv = NULL; | 727 | fe->tuner_priv = NULL; |
705 | return NULL; | 728 | return NULL; |
706 | } | 729 | } |
707 | |||
708 | EXPORT_SYMBOL(dib0070_attach); | 730 | EXPORT_SYMBOL(dib0070_attach); |
709 | 731 | ||
710 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); | 732 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); |
diff --git a/drivers/media/dvb/frontends/dib0070.h b/drivers/media/dvb/frontends/dib0070.h index eec9e52ffa75..45c31fae3967 100644 --- a/drivers/media/dvb/frontends/dib0070.h +++ b/drivers/media/dvb/frontends/dib0070.h | |||
@@ -52,6 +52,8 @@ struct dib0070_config { | |||
52 | extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg); | 52 | extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg); |
53 | extern u16 dib0070_wbd_offset(struct dvb_frontend *); | 53 | extern u16 dib0070_wbd_offset(struct dvb_frontend *); |
54 | extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, u8 open); | 54 | extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, u8 open); |
55 | extern u8 dib0070_get_rf_output(struct dvb_frontend *fe); | ||
56 | extern int dib0070_set_rf_output(struct dvb_frontend *fe, u8 no); | ||
55 | #else | 57 | #else |
56 | static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg) | 58 | static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg) |
57 | { | 59 | { |
@@ -62,7 +64,7 @@ static inline struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struc | |||
62 | static inline u16 dib0070_wbd_offset(struct dvb_frontend *fe) | 64 | static inline u16 dib0070_wbd_offset(struct dvb_frontend *fe) |
63 | { | 65 | { |
64 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | 66 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); |
65 | return -ENODEV; | 67 | return 0; |
66 | } | 68 | } |
67 | 69 | ||
68 | static inline void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open) | 70 | static inline void dib0070_ctrl_agc_filter(struct dvb_frontend *fe, u8 open) |
diff --git a/drivers/media/dvb/frontends/dib0090.c b/drivers/media/dvb/frontends/dib0090.c new file mode 100644 index 000000000000..e37d32dbd5c5 --- /dev/null +++ b/drivers/media/dvb/frontends/dib0090.c | |||
@@ -0,0 +1,1525 @@ | |||
1 | /* | ||
2 | * Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner. | ||
3 | * | ||
4 | * Copyright (C) 2005-9 DiBcom (http://www.dibcom.fr/) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation; either version 2 of the | ||
9 | * License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | * | ||
21 | * | ||
22 | * This code is more or less generated from another driver, please | ||
23 | * excuse some codingstyle oddities. | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/i2c.h> | ||
29 | |||
30 | #include "dvb_frontend.h" | ||
31 | |||
32 | #include "dib0090.h" | ||
33 | #include "dibx000_common.h" | ||
34 | |||
35 | static int debug; | ||
36 | module_param(debug, int, 0644); | ||
37 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | ||
38 | |||
39 | #define dprintk(args...) do { \ | ||
40 | if (debug) { \ | ||
41 | printk(KERN_DEBUG "DiB0090: "); \ | ||
42 | printk(args); \ | ||
43 | printk("\n"); \ | ||
44 | } \ | ||
45 | } while (0) | ||
46 | |||
47 | #define CONFIG_SYS_ISDBT | ||
48 | #define CONFIG_BAND_CBAND | ||
49 | #define CONFIG_BAND_VHF | ||
50 | #define CONFIG_BAND_UHF | ||
51 | #define CONFIG_DIB0090_USE_PWM_AGC | ||
52 | |||
53 | #define EN_LNA0 0x8000 | ||
54 | #define EN_LNA1 0x4000 | ||
55 | #define EN_LNA2 0x2000 | ||
56 | #define EN_LNA3 0x1000 | ||
57 | #define EN_MIX0 0x0800 | ||
58 | #define EN_MIX1 0x0400 | ||
59 | #define EN_MIX2 0x0200 | ||
60 | #define EN_MIX3 0x0100 | ||
61 | #define EN_IQADC 0x0040 | ||
62 | #define EN_PLL 0x0020 | ||
63 | #define EN_TX 0x0010 | ||
64 | #define EN_BB 0x0008 | ||
65 | #define EN_LO 0x0004 | ||
66 | #define EN_BIAS 0x0001 | ||
67 | |||
68 | #define EN_IQANA 0x0002 | ||
69 | #define EN_DIGCLK 0x0080 /* not in the 0x24 reg, only in 0x1b */ | ||
70 | #define EN_CRYSTAL 0x0002 | ||
71 | |||
72 | #define EN_UHF 0x22E9 | ||
73 | #define EN_VHF 0x44E9 | ||
74 | #define EN_LBD 0x11E9 | ||
75 | #define EN_SBD 0x44E9 | ||
76 | #define EN_CAB 0x88E9 | ||
77 | |||
78 | #define pgm_read_word(w) (*w) | ||
79 | |||
80 | struct dc_calibration; | ||
81 | |||
82 | struct dib0090_tuning { | ||
83 | u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ | ||
84 | u8 switch_trim; | ||
85 | u8 lna_tune; | ||
86 | u8 lna_bias; | ||
87 | u16 v2i; | ||
88 | u16 mix; | ||
89 | u16 load; | ||
90 | u16 tuner_enable; | ||
91 | }; | ||
92 | |||
93 | struct dib0090_pll { | ||
94 | u32 max_freq; /* for every frequency less than or equal to that field: this information is correct */ | ||
95 | u8 vco_band; | ||
96 | u8 hfdiv_code; | ||
97 | u8 hfdiv; | ||
98 | u8 topresc; | ||
99 | }; | ||
100 | |||
101 | struct dib0090_state { | ||
102 | struct i2c_adapter *i2c; | ||
103 | struct dvb_frontend *fe; | ||
104 | const struct dib0090_config *config; | ||
105 | |||
106 | u8 current_band; | ||
107 | u16 revision; | ||
108 | enum frontend_tune_state tune_state; | ||
109 | u32 current_rf; | ||
110 | |||
111 | u16 wbd_offset; | ||
112 | s16 wbd_target; /* in dB */ | ||
113 | |||
114 | s16 rf_gain_limit; /* take-over-point: where to split between bb and rf gain */ | ||
115 | s16 current_gain; /* keeps the currently programmed gain */ | ||
116 | u8 agc_step; /* new binary search */ | ||
117 | |||
118 | u16 gain[2]; /* for channel monitoring */ | ||
119 | |||
120 | const u16 *rf_ramp; | ||
121 | const u16 *bb_ramp; | ||
122 | |||
123 | /* for the software AGC ramps */ | ||
124 | u16 bb_1_def; | ||
125 | u16 rf_lt_def; | ||
126 | u16 gain_reg[4]; | ||
127 | |||
128 | /* for the captrim/dc-offset search */ | ||
129 | s8 step; | ||
130 | s16 adc_diff; | ||
131 | s16 min_adc_diff; | ||
132 | |||
133 | s8 captrim; | ||
134 | s8 fcaptrim; | ||
135 | |||
136 | const struct dc_calibration *dc; | ||
137 | u16 bb6, bb7; | ||
138 | |||
139 | const struct dib0090_tuning *current_tune_table_index; | ||
140 | const struct dib0090_pll *current_pll_table_index; | ||
141 | |||
142 | u8 tuner_is_tuned; | ||
143 | u8 agc_freeze; | ||
144 | |||
145 | u8 reset; | ||
146 | }; | ||
147 | |||
148 | static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg) | ||
149 | { | ||
150 | u8 b[2]; | ||
151 | struct i2c_msg msg[2] = { | ||
152 | {.addr = state->config->i2c_address,.flags = 0,.buf = ®,.len = 1}, | ||
153 | {.addr = state->config->i2c_address,.flags = I2C_M_RD,.buf = b,.len = 2}, | ||
154 | }; | ||
155 | if (i2c_transfer(state->i2c, msg, 2) != 2) { | ||
156 | printk(KERN_WARNING "DiB0090 I2C read failed\n"); | ||
157 | return 0; | ||
158 | } | ||
159 | return (b[0] << 8) | b[1]; | ||
160 | } | ||
161 | |||
162 | static int dib0090_write_reg(struct dib0090_state *state, u32 reg, u16 val) | ||
163 | { | ||
164 | u8 b[3] = { reg & 0xff, val >> 8, val & 0xff }; | ||
165 | struct i2c_msg msg = {.addr = state->config->i2c_address,.flags = 0,.buf = b,.len = 3 }; | ||
166 | if (i2c_transfer(state->i2c, &msg, 1) != 1) { | ||
167 | printk(KERN_WARNING "DiB0090 I2C write failed\n"); | ||
168 | return -EREMOTEIO; | ||
169 | } | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | #define HARD_RESET(state) do { if (cfg->reset) { if (cfg->sleep) cfg->sleep(fe, 0); msleep(10); cfg->reset(fe, 1); msleep(10); cfg->reset(fe, 0); msleep(10); } } while (0) | ||
174 | #define ADC_TARGET -220 | ||
175 | #define GAIN_ALPHA 5 | ||
176 | #define WBD_ALPHA 6 | ||
177 | #define LPF 100 | ||
178 | static void dib0090_write_regs(struct dib0090_state *state, u8 r, const u16 * b, u8 c) | ||
179 | { | ||
180 | do { | ||
181 | dib0090_write_reg(state, r++, *b++); | ||
182 | } while (--c); | ||
183 | } | ||
184 | |||
185 | static u16 dib0090_identify(struct dvb_frontend *fe) | ||
186 | { | ||
187 | struct dib0090_state *state = fe->tuner_priv; | ||
188 | u16 v; | ||
189 | |||
190 | v = dib0090_read_reg(state, 0x1a); | ||
191 | |||
192 | #ifdef FIRMWARE_FIREFLY | ||
193 | /* pll is not locked locked */ | ||
194 | if (!(v & 0x800)) | ||
195 | dprintk("FE%d : Identification : pll is not yet locked", fe->id); | ||
196 | #endif | ||
197 | |||
198 | /* without PLL lock info */ | ||
199 | v &= 0x3ff; | ||
200 | dprintk("P/V: %04x:", v); | ||
201 | |||
202 | if ((v >> 8) & 0xf) | ||
203 | dprintk("FE%d : Product ID = 0x%x : KROSUS", fe->id, (v >> 8) & 0xf); | ||
204 | else | ||
205 | return 0xff; | ||
206 | |||
207 | v &= 0xff; | ||
208 | if (((v >> 5) & 0x7) == 0x1) | ||
209 | dprintk("FE%d : MP001 : 9090/8096", fe->id); | ||
210 | else if (((v >> 5) & 0x7) == 0x4) | ||
211 | dprintk("FE%d : MP005 : Single Sband", fe->id); | ||
212 | else if (((v >> 5) & 0x7) == 0x6) | ||
213 | dprintk("FE%d : MP008 : diversity VHF-UHF-LBAND", fe->id); | ||
214 | else if (((v >> 5) & 0x7) == 0x7) | ||
215 | dprintk("FE%d : MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND", fe->id); | ||
216 | else | ||
217 | return 0xff; | ||
218 | |||
219 | /* revision only */ | ||
220 | if ((v & 0x1f) == 0x3) | ||
221 | dprintk("FE%d : P1-D/E/F detected", fe->id); | ||
222 | else if ((v & 0x1f) == 0x1) | ||
223 | dprintk("FE%d : P1C detected", fe->id); | ||
224 | else if ((v & 0x1f) == 0x0) { | ||
225 | #ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT | ||
226 | dprintk("FE%d : P1-A/B detected: using previous driver - support will be removed soon", fe->id); | ||
227 | dib0090_p1b_register(fe); | ||
228 | #else | ||
229 | dprintk("FE%d : P1-A/B detected: driver is deactivated - not available", fe->id); | ||
230 | return 0xff; | ||
231 | #endif | ||
232 | } | ||
233 | |||
234 | return v; | ||
235 | } | ||
236 | |||
237 | static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg) | ||
238 | { | ||
239 | struct dib0090_state *state = fe->tuner_priv; | ||
240 | |||
241 | HARD_RESET(state); | ||
242 | |||
243 | dib0090_write_reg(state, 0x24, EN_PLL); | ||
244 | dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */ | ||
245 | |||
246 | /* adcClkOutRatio=8->7, release reset */ | ||
247 | dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0); | ||
248 | if (cfg->clkoutdrive != 0) | ||
249 | dib0090_write_reg(state, 0x23, | ||
250 | (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 10) | (1 << 9) | (0 << 8) | (cfg->clkoutdrive << 5) | (cfg-> | ||
251 | clkouttobamse | ||
252 | << 4) | (0 | ||
253 | << | ||
254 | 2) | ||
255 | | (0)); | ||
256 | else | ||
257 | dib0090_write_reg(state, 0x23, | ||
258 | (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 10) | (1 << 9) | (0 << 8) | (7 << 5) | (cfg-> | ||
259 | clkouttobamse << 4) | (0 | ||
260 | << | ||
261 | 2) | ||
262 | | (0)); | ||
263 | |||
264 | /* enable pll, de-activate reset, ratio: 2/1 = 60MHz */ | ||
265 | dib0090_write_reg(state, 0x21, | ||
266 | (cfg->io.pll_bypass << 15) | (1 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)); | ||
267 | |||
268 | } | ||
269 | |||
270 | static int dib0090_wakeup(struct dvb_frontend *fe) | ||
271 | { | ||
272 | struct dib0090_state *state = fe->tuner_priv; | ||
273 | if (state->config->sleep) | ||
274 | state->config->sleep(fe, 0); | ||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static int dib0090_sleep(struct dvb_frontend *fe) | ||
279 | { | ||
280 | struct dib0090_state *state = fe->tuner_priv; | ||
281 | if (state->config->sleep) | ||
282 | state->config->sleep(fe, 1); | ||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast) | ||
287 | { | ||
288 | struct dib0090_state *state = fe->tuner_priv; | ||
289 | if (fast) | ||
290 | dib0090_write_reg(state, 0x04, 0); //1kHz | ||
291 | else | ||
292 | dib0090_write_reg(state, 0x04, 1); //almost frozen | ||
293 | } | ||
294 | |||
295 | EXPORT_SYMBOL(dib0090_dcc_freq); | ||
296 | static const u16 rf_ramp_pwm_cband[] = { | ||
297 | 0, /* max RF gain in 10th of dB */ | ||
298 | 0, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */ | ||
299 | 0, /* ramp_max = maximum X used on the ramp */ | ||
300 | (0 << 10) | 0, /* 0x2c, LNA 1 = 0dB */ | ||
301 | (0 << 10) | 0, /* 0x2d, LNA 1 */ | ||
302 | (0 << 10) | 0, /* 0x2e, LNA 2 = 0dB */ | ||
303 | (0 << 10) | 0, /* 0x2f, LNA 2 */ | ||
304 | (0 << 10) | 0, /* 0x30, LNA 3 = 0dB */ | ||
305 | (0 << 10) | 0, /* 0x31, LNA 3 */ | ||
306 | (0 << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */ | ||
307 | (0 << 10) | 0, /* GAIN_4_2, LNA 4 */ | ||
308 | }; | ||
309 | |||
310 | static const u16 rf_ramp_vhf[] = { | ||
311 | 412, /* max RF gain in 10th of dB */ | ||
312 | 132, 307, 127, /* LNA1, 13.2dB */ | ||
313 | 105, 412, 255, /* LNA2, 10.5dB */ | ||
314 | 50, 50, 127, /* LNA3, 5dB */ | ||
315 | 125, 175, 127, /* LNA4, 12.5dB */ | ||
316 | 0, 0, 127, /* CBAND, 0dB */ | ||
317 | }; | ||
318 | |||
319 | static const u16 rf_ramp_uhf[] = { | ||
320 | 412, /* max RF gain in 10th of dB */ | ||
321 | 132, 307, 127, /* LNA1 : total gain = 13.2dB, point on the ramp where this amp is full gain, value to write to get full gain */ | ||
322 | 105, 412, 255, /* LNA2 : 10.5 dB */ | ||
323 | 50, 50, 127, /* LNA3 : 5.0 dB */ | ||
324 | 125, 175, 127, /* LNA4 : 12.5 dB */ | ||
325 | 0, 0, 127, /* CBAND : 0.0 dB */ | ||
326 | }; | ||
327 | |||
328 | static const u16 rf_ramp_cband[] = { | ||
329 | 332, /* max RF gain in 10th of dB */ | ||
330 | 132, 252, 127, /* LNA1, dB */ | ||
331 | 80, 332, 255, /* LNA2, dB */ | ||
332 | 0, 0, 127, /* LNA3, dB */ | ||
333 | 0, 0, 127, /* LNA4, dB */ | ||
334 | 120, 120, 127, /* LT1 CBAND */ | ||
335 | }; | ||
336 | |||
337 | static const u16 rf_ramp_pwm_vhf[] = { | ||
338 | 404, /* max RF gain in 10th of dB */ | ||
339 | 25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */ | ||
340 | 1011, /* ramp_max = maximum X used on the ramp */ | ||
341 | (6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */ | ||
342 | (0 << 10) | 756, /* 0x2d, LNA 1 */ | ||
343 | (16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */ | ||
344 | (0 << 10) | 1011, /* 0x2f, LNA 2 */ | ||
345 | (16 << 10) | 290, /* 0x30, LNA 3 = 5dB */ | ||
346 | (0 << 10) | 417, /* 0x31, LNA 3 */ | ||
347 | (7 << 10) | 0, /* GAIN_4_1, LNA 4 = 12.5dB */ | ||
348 | (0 << 10) | 290, /* GAIN_4_2, LNA 4 */ | ||
349 | }; | ||
350 | |||
351 | static const u16 rf_ramp_pwm_uhf[] = { | ||
352 | 404, /* max RF gain in 10th of dB */ | ||
353 | 25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */ | ||
354 | 1011, /* ramp_max = maximum X used on the ramp */ | ||
355 | (6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */ | ||
356 | (0 << 10) | 756, /* 0x2d, LNA 1 */ | ||
357 | (16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */ | ||
358 | (0 << 10) | 1011, /* 0x2f, LNA 2 */ | ||
359 | (16 << 10) | 0, /* 0x30, LNA 3 = 5dB */ | ||
360 | (0 << 10) | 127, /* 0x31, LNA 3 */ | ||
361 | (7 << 10) | 127, /* GAIN_4_1, LNA 4 = 12.5dB */ | ||
362 | (0 << 10) | 417, /* GAIN_4_2, LNA 4 */ | ||
363 | }; | ||
364 | |||
365 | static const u16 bb_ramp_boost[] = { | ||
366 | 550, /* max BB gain in 10th of dB */ | ||
367 | 260, 260, 26, /* BB1, 26dB */ | ||
368 | 290, 550, 29, /* BB2, 29dB */ | ||
369 | }; | ||
370 | |||
371 | static const u16 bb_ramp_pwm_normal[] = { | ||
372 | 500, /* max RF gain in 10th of dB */ | ||
373 | 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x34 */ | ||
374 | 400, | ||
375 | (2 << 9) | 0, /* 0x35 = 21dB */ | ||
376 | (0 << 9) | 168, /* 0x36 */ | ||
377 | (2 << 9) | 168, /* 0x37 = 29dB */ | ||
378 | (0 << 9) | 400, /* 0x38 */ | ||
379 | }; | ||
380 | |||
381 | struct slope { | ||
382 | int16_t range; | ||
383 | int16_t slope; | ||
384 | }; | ||
385 | static u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val) | ||
386 | { | ||
387 | u8 i; | ||
388 | u16 rest; | ||
389 | u16 ret = 0; | ||
390 | for (i = 0; i < num; i++) { | ||
391 | if (val > slopes[i].range) | ||
392 | rest = slopes[i].range; | ||
393 | else | ||
394 | rest = val; | ||
395 | ret += (rest * slopes[i].slope) / slopes[i].range; | ||
396 | val -= rest; | ||
397 | } | ||
398 | return ret; | ||
399 | } | ||
400 | |||
401 | static const struct slope dib0090_wbd_slopes[3] = { | ||
402 | {66, 120}, /* -64,-52: offset - 65 */ | ||
403 | {600, 170}, /* -52,-35: 65 - 665 */ | ||
404 | {170, 250}, /* -45,-10: 665 - 835 */ | ||
405 | }; | ||
406 | |||
407 | static s16 dib0090_wbd_to_db(struct dib0090_state *state, u16 wbd) | ||
408 | { | ||
409 | wbd &= 0x3ff; | ||
410 | if (wbd < state->wbd_offset) | ||
411 | wbd = 0; | ||
412 | else | ||
413 | wbd -= state->wbd_offset; | ||
414 | /* -64dB is the floor */ | ||
415 | return -640 + (s16) slopes_to_scale(dib0090_wbd_slopes, ARRAY_SIZE(dib0090_wbd_slopes), wbd); | ||
416 | } | ||
417 | |||
418 | static void dib0090_wbd_target(struct dib0090_state *state, u32 rf) | ||
419 | { | ||
420 | u16 offset = 250; | ||
421 | |||
422 | /* TODO : DAB digital N+/-1 interferer perfs : offset = 10 */ | ||
423 | |||
424 | if (state->current_band == BAND_VHF) | ||
425 | offset = 650; | ||
426 | #ifndef FIRMWARE_FIREFLY | ||
427 | if (state->current_band == BAND_VHF) | ||
428 | offset = state->config->wbd_vhf_offset; | ||
429 | if (state->current_band == BAND_CBAND) | ||
430 | offset = state->config->wbd_cband_offset; | ||
431 | #endif | ||
432 | |||
433 | state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + offset); | ||
434 | dprintk("wbd-target: %d dB", (u32) state->wbd_target); | ||
435 | } | ||
436 | |||
437 | static const int gain_reg_addr[4] = { | ||
438 | 0x08, 0x0a, 0x0f, 0x01 | ||
439 | }; | ||
440 | |||
441 | static void dib0090_gain_apply(struct dib0090_state *state, s16 gain_delta, s16 top_delta, u8 force) | ||
442 | { | ||
443 | u16 rf, bb, ref; | ||
444 | u16 i, v, gain_reg[4] = { 0 }, gain; | ||
445 | const u16 *g; | ||
446 | |||
447 | if (top_delta < -511) | ||
448 | top_delta = -511; | ||
449 | if (top_delta > 511) | ||
450 | top_delta = 511; | ||
451 | |||
452 | if (force) { | ||
453 | top_delta *= (1 << WBD_ALPHA); | ||
454 | gain_delta *= (1 << GAIN_ALPHA); | ||
455 | } | ||
456 | |||
457 | if (top_delta >= ((s16) (state->rf_ramp[0] << WBD_ALPHA) - state->rf_gain_limit)) /* overflow */ | ||
458 | state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA; | ||
459 | else | ||
460 | state->rf_gain_limit += top_delta; | ||
461 | |||
462 | if (state->rf_gain_limit < 0) /*underflow */ | ||
463 | state->rf_gain_limit = 0; | ||
464 | |||
465 | /* use gain as a temporary variable and correct current_gain */ | ||
466 | gain = ((state->rf_gain_limit >> WBD_ALPHA) + state->bb_ramp[0]) << GAIN_ALPHA; | ||
467 | if (gain_delta >= ((s16) gain - state->current_gain)) /* overflow */ | ||
468 | state->current_gain = gain; | ||
469 | else | ||
470 | state->current_gain += gain_delta; | ||
471 | /* cannot be less than 0 (only if gain_delta is less than 0 we can have current_gain < 0) */ | ||
472 | if (state->current_gain < 0) | ||
473 | state->current_gain = 0; | ||
474 | |||
475 | /* now split total gain to rf and bb gain */ | ||
476 | gain = state->current_gain >> GAIN_ALPHA; | ||
477 | |||
478 | /* requested gain is bigger than rf gain limit - ACI/WBD adjustment */ | ||
479 | if (gain > (state->rf_gain_limit >> WBD_ALPHA)) { | ||
480 | rf = state->rf_gain_limit >> WBD_ALPHA; | ||
481 | bb = gain - rf; | ||
482 | if (bb > state->bb_ramp[0]) | ||
483 | bb = state->bb_ramp[0]; | ||
484 | } else { /* high signal level -> all gains put on RF */ | ||
485 | rf = gain; | ||
486 | bb = 0; | ||
487 | } | ||
488 | |||
489 | state->gain[0] = rf; | ||
490 | state->gain[1] = bb; | ||
491 | |||
492 | /* software ramp */ | ||
493 | /* Start with RF gains */ | ||
494 | g = state->rf_ramp + 1; /* point on RF LNA1 max gain */ | ||
495 | ref = rf; | ||
496 | for (i = 0; i < 7; i++) { /* Go over all amplifiers => 5RF amps + 2 BB amps = 7 amps */ | ||
497 | if (g[0] == 0 || ref < (g[1] - g[0])) /* if total gain of the current amp is null or this amp is not concerned because it starts to work from an higher gain value */ | ||
498 | v = 0; /* force the gain to write for the current amp to be null */ | ||
499 | else if (ref >= g[1]) /* Gain to set is higher than the high working point of this amp */ | ||
500 | v = g[2]; /* force this amp to be full gain */ | ||
501 | else /* compute the value to set to this amp because we are somewhere in his range */ | ||
502 | v = ((ref - (g[1] - g[0])) * g[2]) / g[0]; | ||
503 | |||
504 | if (i == 0) /* LNA 1 reg mapping */ | ||
505 | gain_reg[0] = v; | ||
506 | else if (i == 1) /* LNA 2 reg mapping */ | ||
507 | gain_reg[0] |= v << 7; | ||
508 | else if (i == 2) /* LNA 3 reg mapping */ | ||
509 | gain_reg[1] = v; | ||
510 | else if (i == 3) /* LNA 4 reg mapping */ | ||
511 | gain_reg[1] |= v << 7; | ||
512 | else if (i == 4) /* CBAND LNA reg mapping */ | ||
513 | gain_reg[2] = v | state->rf_lt_def; | ||
514 | else if (i == 5) /* BB gain 1 reg mapping */ | ||
515 | gain_reg[3] = v << 3; | ||
516 | else if (i == 6) /* BB gain 2 reg mapping */ | ||
517 | gain_reg[3] |= v << 8; | ||
518 | |||
519 | g += 3; /* go to next gain bloc */ | ||
520 | |||
521 | /* When RF is finished, start with BB */ | ||
522 | if (i == 4) { | ||
523 | g = state->bb_ramp + 1; /* point on BB gain 1 max gain */ | ||
524 | ref = bb; | ||
525 | } | ||
526 | } | ||
527 | gain_reg[3] |= state->bb_1_def; | ||
528 | gain_reg[3] |= ((bb % 10) * 100) / 125; | ||
529 | |||
530 | #ifdef DEBUG_AGC | ||
531 | dprintk("GA CALC: DB: %3d(rf) + %3d(bb) = %3d gain_reg[0]=%04x gain_reg[1]=%04x gain_reg[2]=%04x gain_reg[0]=%04x", rf, bb, rf + bb, | ||
532 | gain_reg[0], gain_reg[1], gain_reg[2], gain_reg[3]); | ||
533 | #endif | ||
534 | |||
535 | /* Write the amplifier regs */ | ||
536 | for (i = 0; i < 4; i++) { | ||
537 | v = gain_reg[i]; | ||
538 | if (force || state->gain_reg[i] != v) { | ||
539 | state->gain_reg[i] = v; | ||
540 | dib0090_write_reg(state, gain_reg_addr[i], v); | ||
541 | } | ||
542 | } | ||
543 | } | ||
544 | |||
545 | static void dib0090_set_boost(struct dib0090_state *state, int onoff) | ||
546 | { | ||
547 | state->bb_1_def &= 0xdfff; | ||
548 | state->bb_1_def |= onoff << 13; | ||
549 | } | ||
550 | |||
551 | static void dib0090_set_rframp(struct dib0090_state *state, const u16 * cfg) | ||
552 | { | ||
553 | state->rf_ramp = cfg; | ||
554 | } | ||
555 | |||
556 | static void dib0090_set_rframp_pwm(struct dib0090_state *state, const u16 * cfg) | ||
557 | { | ||
558 | state->rf_ramp = cfg; | ||
559 | |||
560 | dib0090_write_reg(state, 0x2a, 0xffff); | ||
561 | |||
562 | dprintk("total RF gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x2a)); | ||
563 | |||
564 | dib0090_write_regs(state, 0x2c, cfg + 3, 6); | ||
565 | dib0090_write_regs(state, 0x3e, cfg + 9, 2); | ||
566 | } | ||
567 | |||
568 | static void dib0090_set_bbramp(struct dib0090_state *state, const u16 * cfg) | ||
569 | { | ||
570 | state->bb_ramp = cfg; | ||
571 | dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */ | ||
572 | } | ||
573 | |||
574 | static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg) | ||
575 | { | ||
576 | state->bb_ramp = cfg; | ||
577 | |||
578 | dib0090_set_boost(state, cfg[0] > 500); /* we want the boost if the gain is higher that 50dB */ | ||
579 | |||
580 | dib0090_write_reg(state, 0x33, 0xffff); | ||
581 | dprintk("total BB gain: %ddB, step: %d", (u32) cfg[0], dib0090_read_reg(state, 0x33)); | ||
582 | dib0090_write_regs(state, 0x35, cfg + 3, 4); | ||
583 | } | ||
584 | |||
585 | void dib0090_pwm_gain_reset(struct dvb_frontend *fe) | ||
586 | { | ||
587 | struct dib0090_state *state = fe->tuner_priv; | ||
588 | /* reset the AGC */ | ||
589 | |||
590 | if (state->config->use_pwm_agc) { | ||
591 | #ifdef CONFIG_BAND_SBAND | ||
592 | if (state->current_band == BAND_SBAND) { | ||
593 | dib0090_set_rframp_pwm(state, rf_ramp_pwm_sband); | ||
594 | dib0090_set_bbramp_pwm(state, bb_ramp_pwm_boost); | ||
595 | } else | ||
596 | #endif | ||
597 | #ifdef CONFIG_BAND_CBAND | ||
598 | if (state->current_band == BAND_CBAND) { | ||
599 | dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband); | ||
600 | dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal); | ||
601 | } else | ||
602 | #endif | ||
603 | #ifdef CONFIG_BAND_VHF | ||
604 | if (state->current_band == BAND_VHF) { | ||
605 | dib0090_set_rframp_pwm(state, rf_ramp_pwm_vhf); | ||
606 | dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal); | ||
607 | } else | ||
608 | #endif | ||
609 | { | ||
610 | dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf); | ||
611 | dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal); | ||
612 | } | ||
613 | |||
614 | if (state->rf_ramp[0] != 0) | ||
615 | dib0090_write_reg(state, 0x32, (3 << 11)); | ||
616 | else | ||
617 | dib0090_write_reg(state, 0x32, (0 << 11)); | ||
618 | |||
619 | dib0090_write_reg(state, 0x39, (1 << 10)); // 0 gain by default | ||
620 | } | ||
621 | } | ||
622 | |||
623 | EXPORT_SYMBOL(dib0090_pwm_gain_reset); | ||
624 | int dib0090_gain_control(struct dvb_frontend *fe) | ||
625 | { | ||
626 | struct dib0090_state *state = fe->tuner_priv; | ||
627 | enum frontend_tune_state *tune_state = &state->tune_state; | ||
628 | int ret = 10; | ||
629 | |||
630 | u16 wbd_val = 0; | ||
631 | u8 apply_gain_immediatly = 1; | ||
632 | s16 wbd_error = 0, adc_error = 0; | ||
633 | |||
634 | if (*tune_state == CT_AGC_START) { | ||
635 | state->agc_freeze = 0; | ||
636 | dib0090_write_reg(state, 0x04, 0x0); | ||
637 | |||
638 | #ifdef CONFIG_BAND_SBAND | ||
639 | if (state->current_band == BAND_SBAND) { | ||
640 | dib0090_set_rframp(state, rf_ramp_sband); | ||
641 | dib0090_set_bbramp(state, bb_ramp_boost); | ||
642 | } else | ||
643 | #endif | ||
644 | #ifdef CONFIG_BAND_VHF | ||
645 | if (state->current_band == BAND_VHF) { | ||
646 | dib0090_set_rframp(state, rf_ramp_vhf); | ||
647 | dib0090_set_bbramp(state, bb_ramp_boost); | ||
648 | } else | ||
649 | #endif | ||
650 | #ifdef CONFIG_BAND_CBAND | ||
651 | if (state->current_band == BAND_CBAND) { | ||
652 | dib0090_set_rframp(state, rf_ramp_cband); | ||
653 | dib0090_set_bbramp(state, bb_ramp_boost); | ||
654 | } else | ||
655 | #endif | ||
656 | { | ||
657 | dib0090_set_rframp(state, rf_ramp_uhf); | ||
658 | dib0090_set_bbramp(state, bb_ramp_boost); | ||
659 | } | ||
660 | |||
661 | dib0090_write_reg(state, 0x32, 0); | ||
662 | dib0090_write_reg(state, 0x39, 0); | ||
663 | |||
664 | dib0090_wbd_target(state, state->current_rf); | ||
665 | |||
666 | state->rf_gain_limit = state->rf_ramp[0] << WBD_ALPHA; | ||
667 | state->current_gain = ((state->rf_ramp[0] + state->bb_ramp[0]) / 2) << GAIN_ALPHA; | ||
668 | |||
669 | *tune_state = CT_AGC_STEP_0; | ||
670 | } else if (!state->agc_freeze) { | ||
671 | s16 wbd; | ||
672 | |||
673 | int adc; | ||
674 | wbd_val = dib0090_read_reg(state, 0x1d); | ||
675 | |||
676 | /* read and calc the wbd power */ | ||
677 | wbd = dib0090_wbd_to_db(state, wbd_val); | ||
678 | wbd_error = state->wbd_target - wbd; | ||
679 | |||
680 | if (*tune_state == CT_AGC_STEP_0) { | ||
681 | if (wbd_error < 0 && state->rf_gain_limit > 0) { | ||
682 | #ifdef CONFIG_BAND_CBAND | ||
683 | /* in case of CBAND tune reduce first the lt_gain2 before adjusting the RF gain */ | ||
684 | u8 ltg2 = (state->rf_lt_def >> 10) & 0x7; | ||
685 | if (state->current_band == BAND_CBAND && ltg2) { | ||
686 | ltg2 >>= 1; | ||
687 | state->rf_lt_def &= ltg2 << 10; /* reduce in 3 steps from 7 to 0 */ | ||
688 | } | ||
689 | #endif | ||
690 | } else { | ||
691 | state->agc_step = 0; | ||
692 | *tune_state = CT_AGC_STEP_1; | ||
693 | } | ||
694 | } else { | ||
695 | /* calc the adc power */ | ||
696 | adc = state->config->get_adc_power(fe); | ||
697 | adc = (adc * ((s32) 355774) + (((s32) 1) << 20)) >> 21; /* included in [0:-700] */ | ||
698 | |||
699 | adc_error = (s16) (((s32) ADC_TARGET) - adc); | ||
700 | #ifdef CONFIG_STANDARD_DAB | ||
701 | if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) | ||
702 | adc_error += 130; | ||
703 | #endif | ||
704 | #ifdef CONFIG_STANDARD_DVBT | ||
705 | if (state->fe->dtv_property_cache.delivery_system == STANDARD_DVBT && | ||
706 | (state->fe->dtv_property_cache.modulation == QAM_64 || state->fe->dtv_property_cache.modulation == QAM_16)) | ||
707 | adc_error += 60; | ||
708 | #endif | ||
709 | #ifdef CONFIG_SYS_ISDBT | ||
710 | if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) && (((state->fe->dtv_property_cache.layer[0].segment_count > | ||
711 | 0) | ||
712 | && | ||
713 | ((state->fe->dtv_property_cache.layer[0].modulation == | ||
714 | QAM_64) | ||
715 | || (state->fe->dtv_property_cache.layer[0]. | ||
716 | modulation == QAM_16))) | ||
717 | || | ||
718 | ((state->fe->dtv_property_cache.layer[1].segment_count > | ||
719 | 0) | ||
720 | && | ||
721 | ((state->fe->dtv_property_cache.layer[1].modulation == | ||
722 | QAM_64) | ||
723 | || (state->fe->dtv_property_cache.layer[1]. | ||
724 | modulation == QAM_16))) | ||
725 | || | ||
726 | ((state->fe->dtv_property_cache.layer[2].segment_count > | ||
727 | 0) | ||
728 | && | ||
729 | ((state->fe->dtv_property_cache.layer[2].modulation == | ||
730 | QAM_64) | ||
731 | || (state->fe->dtv_property_cache.layer[2]. | ||
732 | modulation == QAM_16))) | ||
733 | ) | ||
734 | ) | ||
735 | adc_error += 60; | ||
736 | #endif | ||
737 | |||
738 | if (*tune_state == CT_AGC_STEP_1) { /* quickly go to the correct range of the ADC power */ | ||
739 | if (ABS(adc_error) < 50 || state->agc_step++ > 5) { | ||
740 | |||
741 | #ifdef CONFIG_STANDARD_DAB | ||
742 | if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) { | ||
743 | dib0090_write_reg(state, 0x02, (1 << 15) | (15 << 11) | (31 << 6) | (63)); /* cap value = 63 : narrow BB filter : Fc = 1.8MHz */ | ||
744 | dib0090_write_reg(state, 0x04, 0x0); | ||
745 | } else | ||
746 | #endif | ||
747 | { | ||
748 | dib0090_write_reg(state, 0x02, (1 << 15) | (3 << 11) | (6 << 6) | (32)); | ||
749 | dib0090_write_reg(state, 0x04, 0x01); /*0 = 1KHz ; 1 = 150Hz ; 2 = 50Hz ; 3 = 50KHz ; 4 = servo fast */ | ||
750 | } | ||
751 | |||
752 | *tune_state = CT_AGC_STOP; | ||
753 | } | ||
754 | } else { | ||
755 | /* everything higher than or equal to CT_AGC_STOP means tracking */ | ||
756 | ret = 100; /* 10ms interval */ | ||
757 | apply_gain_immediatly = 0; | ||
758 | } | ||
759 | } | ||
760 | #ifdef DEBUG_AGC | ||
761 | dprintk | ||
762 | ("FE: %d, tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm", | ||
763 | (u32) fe->id, (u32) * tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val, | ||
764 | (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA)); | ||
765 | #endif | ||
766 | } | ||
767 | |||
768 | /* apply gain */ | ||
769 | if (!state->agc_freeze) | ||
770 | dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly); | ||
771 | return ret; | ||
772 | } | ||
773 | |||
774 | EXPORT_SYMBOL(dib0090_gain_control); | ||
775 | void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt) | ||
776 | { | ||
777 | struct dib0090_state *state = fe->tuner_priv; | ||
778 | if (rf) | ||
779 | *rf = state->gain[0]; | ||
780 | if (bb) | ||
781 | *bb = state->gain[1]; | ||
782 | if (rf_gain_limit) | ||
783 | *rf_gain_limit = state->rf_gain_limit; | ||
784 | if (rflt) | ||
785 | *rflt = (state->rf_lt_def >> 10) & 0x7; | ||
786 | } | ||
787 | |||
788 | EXPORT_SYMBOL(dib0090_get_current_gain); | ||
789 | u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner) | ||
790 | { | ||
791 | struct dib0090_state *st = tuner->tuner_priv; | ||
792 | return st->wbd_offset; | ||
793 | } | ||
794 | |||
795 | EXPORT_SYMBOL(dib0090_get_wbd_offset); | ||
796 | static const u16 dib0090_defaults[] = { | ||
797 | |||
798 | 25, 0x01, | ||
799 | 0x0000, | ||
800 | 0x99a0, | ||
801 | 0x6008, | ||
802 | 0x0000, | ||
803 | 0x8acb, | ||
804 | 0x0000, | ||
805 | 0x0405, | ||
806 | 0x0000, | ||
807 | 0x0000, | ||
808 | 0x0000, | ||
809 | 0xb802, | ||
810 | 0x0300, | ||
811 | 0x2d12, | ||
812 | 0xbac0, | ||
813 | 0x7c00, | ||
814 | 0xdbb9, | ||
815 | 0x0954, | ||
816 | 0x0743, | ||
817 | 0x8000, | ||
818 | 0x0001, | ||
819 | 0x0040, | ||
820 | 0x0100, | ||
821 | 0x0000, | ||
822 | 0xe910, | ||
823 | 0x149e, | ||
824 | |||
825 | 1, 0x1c, | ||
826 | 0xff2d, | ||
827 | |||
828 | 1, 0x39, | ||
829 | 0x0000, | ||
830 | |||
831 | 1, 0x1b, | ||
832 | EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL, | ||
833 | 2, 0x1e, | ||
834 | 0x07FF, | ||
835 | 0x0007, | ||
836 | |||
837 | 1, 0x24, | ||
838 | EN_UHF | EN_CRYSTAL, | ||
839 | |||
840 | 2, 0x3c, | ||
841 | 0x3ff, | ||
842 | 0x111, | ||
843 | 0 | ||
844 | }; | ||
845 | |||
846 | static int dib0090_reset(struct dvb_frontend *fe) | ||
847 | { | ||
848 | struct dib0090_state *state = fe->tuner_priv; | ||
849 | u16 l, r, *n; | ||
850 | |||
851 | dib0090_reset_digital(fe, state->config); | ||
852 | state->revision = dib0090_identify(fe); | ||
853 | |||
854 | /* Revision definition */ | ||
855 | if (state->revision == 0xff) | ||
856 | return -EINVAL; | ||
857 | #ifdef EFUSE | ||
858 | else if ((state->revision & 0x1f) >= 3) /* Update the efuse : Only available for KROSUS > P1C */ | ||
859 | dib0090_set_EFUSE(state); | ||
860 | #endif | ||
861 | |||
862 | #ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT | ||
863 | if (!(state->revision & 0x1)) /* it is P1B - reset is already done */ | ||
864 | return 0; | ||
865 | #endif | ||
866 | |||
867 | /* Upload the default values */ | ||
868 | n = (u16 *) dib0090_defaults; | ||
869 | l = pgm_read_word(n++); | ||
870 | while (l) { | ||
871 | r = pgm_read_word(n++); | ||
872 | do { | ||
873 | /* DEBUG_TUNER */ | ||
874 | /* dprintk("%d, %d, %d", l, r, pgm_read_word(n)); */ | ||
875 | dib0090_write_reg(state, r, pgm_read_word(n++)); | ||
876 | r++; | ||
877 | } while (--l); | ||
878 | l = pgm_read_word(n++); | ||
879 | } | ||
880 | |||
881 | /* Congigure in function of the crystal */ | ||
882 | if (state->config->io.clock_khz >= 24000) | ||
883 | l = 1; | ||
884 | else | ||
885 | l = 2; | ||
886 | dib0090_write_reg(state, 0x14, l); | ||
887 | dprintk("Pll lock : %d", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1); | ||
888 | |||
889 | state->reset = 3; /* enable iq-offset-calibration and wbd-calibration when tuning next time */ | ||
890 | |||
891 | return 0; | ||
892 | } | ||
893 | |||
894 | #define steps(u) (((u)>15)?((u)-16):(u)) | ||
895 | #define INTERN_WAIT 10 | ||
896 | static int dib0090_get_offset(struct dib0090_state *state, enum frontend_tune_state *tune_state) | ||
897 | { | ||
898 | int ret = INTERN_WAIT * 10; | ||
899 | |||
900 | switch (*tune_state) { | ||
901 | case CT_TUNER_STEP_2: | ||
902 | /* Turns to positive */ | ||
903 | dib0090_write_reg(state, 0x1f, 0x7); | ||
904 | *tune_state = CT_TUNER_STEP_3; | ||
905 | break; | ||
906 | |||
907 | case CT_TUNER_STEP_3: | ||
908 | state->adc_diff = dib0090_read_reg(state, 0x1d); | ||
909 | |||
910 | /* Turns to negative */ | ||
911 | dib0090_write_reg(state, 0x1f, 0x4); | ||
912 | *tune_state = CT_TUNER_STEP_4; | ||
913 | break; | ||
914 | |||
915 | case CT_TUNER_STEP_4: | ||
916 | state->adc_diff -= dib0090_read_reg(state, 0x1d); | ||
917 | *tune_state = CT_TUNER_STEP_5; | ||
918 | ret = 0; | ||
919 | break; | ||
920 | |||
921 | default: | ||
922 | break; | ||
923 | } | ||
924 | |||
925 | return ret; | ||
926 | } | ||
927 | |||
928 | struct dc_calibration { | ||
929 | uint8_t addr; | ||
930 | uint8_t offset; | ||
931 | uint8_t pga:1; | ||
932 | uint16_t bb1; | ||
933 | uint8_t i:1; | ||
934 | }; | ||
935 | |||
936 | static const struct dc_calibration dc_table[] = { | ||
937 | /* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */ | ||
938 | {0x06, 5, 1, (1 << 13) | (0 << 8) | (26 << 3), 1}, | ||
939 | {0x07, 11, 1, (1 << 13) | (0 << 8) | (26 << 3), 0}, | ||
940 | /* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */ | ||
941 | {0x06, 0, 0, (1 << 13) | (29 << 8) | (26 << 3), 1}, | ||
942 | {0x06, 10, 0, (1 << 13) | (29 << 8) | (26 << 3), 0}, | ||
943 | {0}, | ||
944 | }; | ||
945 | |||
946 | static void dib0090_set_trim(struct dib0090_state *state) | ||
947 | { | ||
948 | u16 *val; | ||
949 | |||
950 | if (state->dc->addr == 0x07) | ||
951 | val = &state->bb7; | ||
952 | else | ||
953 | val = &state->bb6; | ||
954 | |||
955 | *val &= ~(0x1f << state->dc->offset); | ||
956 | *val |= state->step << state->dc->offset; | ||
957 | |||
958 | dib0090_write_reg(state, state->dc->addr, *val); | ||
959 | } | ||
960 | |||
961 | static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state) | ||
962 | { | ||
963 | int ret = 0; | ||
964 | |||
965 | switch (*tune_state) { | ||
966 | |||
967 | case CT_TUNER_START: | ||
968 | /* init */ | ||
969 | dprintk("Internal DC calibration"); | ||
970 | |||
971 | /* the LNA is off */ | ||
972 | dib0090_write_reg(state, 0x24, 0x02ed); | ||
973 | |||
974 | /* force vcm2 = 0.8V */ | ||
975 | state->bb6 = 0; | ||
976 | state->bb7 = 0x040d; | ||
977 | |||
978 | state->dc = dc_table; | ||
979 | |||
980 | *tune_state = CT_TUNER_STEP_0; | ||
981 | |||
982 | /* fall through */ | ||
983 | |||
984 | case CT_TUNER_STEP_0: | ||
985 | dib0090_write_reg(state, 0x01, state->dc->bb1); | ||
986 | dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7)); | ||
987 | |||
988 | state->step = 0; | ||
989 | |||
990 | state->min_adc_diff = 1023; | ||
991 | |||
992 | *tune_state = CT_TUNER_STEP_1; | ||
993 | ret = 50; | ||
994 | break; | ||
995 | |||
996 | case CT_TUNER_STEP_1: | ||
997 | dib0090_set_trim(state); | ||
998 | |||
999 | *tune_state = CT_TUNER_STEP_2; | ||
1000 | break; | ||
1001 | |||
1002 | case CT_TUNER_STEP_2: | ||
1003 | case CT_TUNER_STEP_3: | ||
1004 | case CT_TUNER_STEP_4: | ||
1005 | ret = dib0090_get_offset(state, tune_state); | ||
1006 | break; | ||
1007 | |||
1008 | case CT_TUNER_STEP_5: /* found an offset */ | ||
1009 | dprintk("FE%d: IQC read=%d, current=%x", state->fe->id, (u32) state->adc_diff, state->step); | ||
1010 | |||
1011 | /* first turn for this frequency */ | ||
1012 | if (state->step == 0) { | ||
1013 | if (state->dc->pga && state->adc_diff < 0) | ||
1014 | state->step = 0x10; | ||
1015 | if (state->dc->pga == 0 && state->adc_diff > 0) | ||
1016 | state->step = 0x10; | ||
1017 | } | ||
1018 | |||
1019 | state->adc_diff = ABS(state->adc_diff); | ||
1020 | |||
1021 | if (state->adc_diff < state->min_adc_diff && steps(state->step) < 15) { /* stop search when the delta to 0 is increasing */ | ||
1022 | state->step++; | ||
1023 | state->min_adc_diff = state->adc_diff; | ||
1024 | *tune_state = CT_TUNER_STEP_1; | ||
1025 | } else { | ||
1026 | |||
1027 | /* the minimum was what we have seen in the step before */ | ||
1028 | state->step--; | ||
1029 | dib0090_set_trim(state); | ||
1030 | |||
1031 | dprintk("FE%d: BB Offset Cal, BBreg=%hd,Offset=%hd,Value Set=%hd", state->fe->id, state->dc->addr, state->adc_diff, | ||
1032 | state->step); | ||
1033 | |||
1034 | state->dc++; | ||
1035 | if (state->dc->addr == 0) /* done */ | ||
1036 | *tune_state = CT_TUNER_STEP_6; | ||
1037 | else | ||
1038 | *tune_state = CT_TUNER_STEP_0; | ||
1039 | |||
1040 | } | ||
1041 | break; | ||
1042 | |||
1043 | case CT_TUNER_STEP_6: | ||
1044 | dib0090_write_reg(state, 0x07, state->bb7 & ~0x0008); | ||
1045 | dib0090_write_reg(state, 0x1f, 0x7); | ||
1046 | *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */ | ||
1047 | state->reset &= ~0x1; | ||
1048 | default: | ||
1049 | break; | ||
1050 | } | ||
1051 | return ret; | ||
1052 | } | ||
1053 | |||
1054 | static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state) | ||
1055 | { | ||
1056 | switch (*tune_state) { | ||
1057 | case CT_TUNER_START: | ||
1058 | /* WBD-mode=log, Bias=2, Gain=6, Testmode=1, en=1, WBDMUX=1 */ | ||
1059 | dib0090_write_reg(state, 0x10, 0xdb09 | (1 << 10)); | ||
1060 | dib0090_write_reg(state, 0x24, EN_UHF & 0x0fff); | ||
1061 | |||
1062 | *tune_state = CT_TUNER_STEP_0; | ||
1063 | return 90; /* wait for the WBDMUX to switch and for the ADC to sample */ | ||
1064 | case CT_TUNER_STEP_0: | ||
1065 | state->wbd_offset = dib0090_read_reg(state, 0x1d); | ||
1066 | dprintk("WBD calibration offset = %d", state->wbd_offset); | ||
1067 | |||
1068 | *tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */ | ||
1069 | state->reset &= ~0x2; | ||
1070 | break; | ||
1071 | default: | ||
1072 | break; | ||
1073 | } | ||
1074 | return 0; | ||
1075 | } | ||
1076 | |||
1077 | static void dib0090_set_bandwidth(struct dib0090_state *state) | ||
1078 | { | ||
1079 | u16 tmp; | ||
1080 | |||
1081 | if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 5000) | ||
1082 | tmp = (3 << 14); | ||
1083 | else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 6000) | ||
1084 | tmp = (2 << 14); | ||
1085 | else if (state->fe->dtv_property_cache.bandwidth_hz / 1000 <= 7000) | ||
1086 | tmp = (1 << 14); | ||
1087 | else | ||
1088 | tmp = (0 << 14); | ||
1089 | |||
1090 | state->bb_1_def &= 0x3fff; | ||
1091 | state->bb_1_def |= tmp; | ||
1092 | |||
1093 | dib0090_write_reg(state, 0x01, state->bb_1_def); /* be sure that we have the right bb-filter */ | ||
1094 | } | ||
1095 | |||
1096 | static const struct dib0090_pll dib0090_pll_table[] = { | ||
1097 | #ifdef CONFIG_BAND_CBAND | ||
1098 | {56000, 0, 9, 48, 6}, | ||
1099 | {70000, 1, 9, 48, 6}, | ||
1100 | {87000, 0, 8, 32, 4}, | ||
1101 | {105000, 1, 8, 32, 4}, | ||
1102 | {115000, 0, 7, 24, 6}, | ||
1103 | {140000, 1, 7, 24, 6}, | ||
1104 | {170000, 0, 6, 16, 4}, | ||
1105 | #endif | ||
1106 | #ifdef CONFIG_BAND_VHF | ||
1107 | {200000, 1, 6, 16, 4}, | ||
1108 | {230000, 0, 5, 12, 6}, | ||
1109 | {280000, 1, 5, 12, 6}, | ||
1110 | {340000, 0, 4, 8, 4}, | ||
1111 | {380000, 1, 4, 8, 4}, | ||
1112 | {450000, 0, 3, 6, 6}, | ||
1113 | #endif | ||
1114 | #ifdef CONFIG_BAND_UHF | ||
1115 | {580000, 1, 3, 6, 6}, | ||
1116 | {700000, 0, 2, 4, 4}, | ||
1117 | {860000, 1, 2, 4, 4}, | ||
1118 | #endif | ||
1119 | #ifdef CONFIG_BAND_LBAND | ||
1120 | {1800000, 1, 0, 2, 4}, | ||
1121 | #endif | ||
1122 | #ifdef CONFIG_BAND_SBAND | ||
1123 | {2900000, 0, 14, 1, 4}, | ||
1124 | #endif | ||
1125 | }; | ||
1126 | |||
1127 | static const struct dib0090_tuning dib0090_tuning_table_fm_vhf_on_cband[] = { | ||
1128 | |||
1129 | #ifdef CONFIG_BAND_CBAND | ||
1130 | {184000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB}, | ||
1131 | {227000, 4, 3, 15, 0x280, 0x2912, 0xb94e, EN_CAB}, | ||
1132 | {380000, 4, 7, 15, 0x280, 0x2912, 0xb94e, EN_CAB}, | ||
1133 | #endif | ||
1134 | #ifdef CONFIG_BAND_UHF | ||
1135 | {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1136 | {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1137 | {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1138 | {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1139 | {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1140 | {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1141 | #endif | ||
1142 | #ifdef CONFIG_BAND_LBAND | ||
1143 | {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, | ||
1144 | {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, | ||
1145 | {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, | ||
1146 | #endif | ||
1147 | #ifdef CONFIG_BAND_SBAND | ||
1148 | {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD}, | ||
1149 | {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD}, | ||
1150 | #endif | ||
1151 | }; | ||
1152 | |||
1153 | static const struct dib0090_tuning dib0090_tuning_table[] = { | ||
1154 | |||
1155 | #ifdef CONFIG_BAND_CBAND | ||
1156 | {170000, 4, 1, 15, 0x280, 0x2912, 0xb94e, EN_CAB}, | ||
1157 | #endif | ||
1158 | #ifdef CONFIG_BAND_VHF | ||
1159 | {184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF}, | ||
1160 | {227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF}, | ||
1161 | {380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF}, | ||
1162 | #endif | ||
1163 | #ifdef CONFIG_BAND_UHF | ||
1164 | {520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1165 | {550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1166 | {650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1167 | {750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1168 | {850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1169 | {900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF}, | ||
1170 | #endif | ||
1171 | #ifdef CONFIG_BAND_LBAND | ||
1172 | {1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, | ||
1173 | {1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, | ||
1174 | {1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD}, | ||
1175 | #endif | ||
1176 | #ifdef CONFIG_BAND_SBAND | ||
1177 | {2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD}, | ||
1178 | {2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD}, | ||
1179 | #endif | ||
1180 | }; | ||
1181 | |||
1182 | #define WBD 0x781 /* 1 1 1 1 0000 0 0 1 */ | ||
1183 | static int dib0090_tune(struct dvb_frontend *fe) | ||
1184 | { | ||
1185 | struct dib0090_state *state = fe->tuner_priv; | ||
1186 | const struct dib0090_tuning *tune = state->current_tune_table_index; | ||
1187 | const struct dib0090_pll *pll = state->current_pll_table_index; | ||
1188 | enum frontend_tune_state *tune_state = &state->tune_state; | ||
1189 | |||
1190 | u32 rf; | ||
1191 | u16 lo4 = 0xe900, lo5, lo6, Den; | ||
1192 | u32 FBDiv, Rest, FREF, VCOF_kHz = 0; | ||
1193 | u16 tmp, adc; | ||
1194 | int8_t step_sign; | ||
1195 | int ret = 10; /* 1ms is the default delay most of the time */ | ||
1196 | u8 c, i; | ||
1197 | |||
1198 | state->current_band = (u8) BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000); | ||
1199 | rf = fe->dtv_property_cache.frequency / 1000 + (state->current_band == | ||
1200 | BAND_UHF ? state->config->freq_offset_khz_uhf : state->config->freq_offset_khz_vhf); | ||
1201 | /* in any case we first need to do a reset if needed */ | ||
1202 | if (state->reset & 0x1) | ||
1203 | return dib0090_dc_offset_calibration(state, tune_state); | ||
1204 | else if (state->reset & 0x2) | ||
1205 | return dib0090_wbd_calibration(state, tune_state); | ||
1206 | |||
1207 | /************************* VCO ***************************/ | ||
1208 | /* Default values for FG */ | ||
1209 | /* from these are needed : */ | ||
1210 | /* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv */ | ||
1211 | |||
1212 | #ifdef CONFIG_SYS_ISDBT | ||
1213 | if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1) | ||
1214 | rf += 850; | ||
1215 | #endif | ||
1216 | |||
1217 | if (state->current_rf != rf) { | ||
1218 | state->tuner_is_tuned = 0; | ||
1219 | |||
1220 | tune = dib0090_tuning_table; | ||
1221 | |||
1222 | tmp = (state->revision >> 5) & 0x7; | ||
1223 | if (tmp == 0x4 || tmp == 0x7) { | ||
1224 | /* CBAND tuner version for VHF */ | ||
1225 | if (state->current_band == BAND_FM || state->current_band == BAND_VHF) { | ||
1226 | /* Force CBAND */ | ||
1227 | state->current_band = BAND_CBAND; | ||
1228 | tune = dib0090_tuning_table_fm_vhf_on_cband; | ||
1229 | } | ||
1230 | } | ||
1231 | |||
1232 | pll = dib0090_pll_table; | ||
1233 | /* Look for the interval */ | ||
1234 | while (rf > tune->max_freq) | ||
1235 | tune++; | ||
1236 | while (rf > pll->max_freq) | ||
1237 | pll++; | ||
1238 | state->current_tune_table_index = tune; | ||
1239 | state->current_pll_table_index = pll; | ||
1240 | } | ||
1241 | |||
1242 | if (*tune_state == CT_TUNER_START) { | ||
1243 | |||
1244 | if (state->tuner_is_tuned == 0) | ||
1245 | state->current_rf = 0; | ||
1246 | |||
1247 | if (state->current_rf != rf) { | ||
1248 | |||
1249 | dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim)); | ||
1250 | |||
1251 | /* external loop filter, otherwise: | ||
1252 | * lo5 = (0 << 15) | (0 << 12) | (0 << 11) | (3 << 9) | (4 << 6) | (3 << 4) | 4; | ||
1253 | * lo6 = 0x0e34 */ | ||
1254 | if (pll->vco_band) | ||
1255 | lo5 = 0x049e; | ||
1256 | else if (state->config->analog_output) | ||
1257 | lo5 = 0x041d; | ||
1258 | else | ||
1259 | lo5 = 0x041c; | ||
1260 | |||
1261 | lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7); /* bit 15 is the split to the slave, we do not do it here */ | ||
1262 | |||
1263 | if (!state->config->io.pll_int_loop_filt) | ||
1264 | lo6 = 0xff28; | ||
1265 | else | ||
1266 | lo6 = (state->config->io.pll_int_loop_filt << 3); | ||
1267 | |||
1268 | VCOF_kHz = (pll->hfdiv * rf) * 2; | ||
1269 | |||
1270 | FREF = state->config->io.clock_khz; | ||
1271 | |||
1272 | FBDiv = (VCOF_kHz / pll->topresc / FREF); | ||
1273 | Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF; | ||
1274 | |||
1275 | if (Rest < LPF) | ||
1276 | Rest = 0; | ||
1277 | else if (Rest < 2 * LPF) | ||
1278 | Rest = 2 * LPF; | ||
1279 | else if (Rest > (FREF - LPF)) { | ||
1280 | Rest = 0; | ||
1281 | FBDiv += 1; | ||
1282 | } else if (Rest > (FREF - 2 * LPF)) | ||
1283 | Rest = FREF - 2 * LPF; | ||
1284 | Rest = (Rest * 6528) / (FREF / 10); | ||
1285 | |||
1286 | Den = 1; | ||
1287 | |||
1288 | dprintk(" ***** ******* Rest value = %d", Rest); | ||
1289 | |||
1290 | if (Rest > 0) { | ||
1291 | if (state->config->analog_output) | ||
1292 | lo6 |= (1 << 2) | 2; | ||
1293 | else | ||
1294 | lo6 |= (1 << 2) | 1; | ||
1295 | Den = 255; | ||
1296 | } | ||
1297 | #ifdef CONFIG_BAND_SBAND | ||
1298 | if (state->current_band == BAND_SBAND) | ||
1299 | lo6 &= 0xfffb; | ||
1300 | #endif | ||
1301 | |||
1302 | dib0090_write_reg(state, 0x15, (u16) FBDiv); | ||
1303 | |||
1304 | dib0090_write_reg(state, 0x16, (Den << 8) | 1); | ||
1305 | |||
1306 | dib0090_write_reg(state, 0x17, (u16) Rest); | ||
1307 | |||
1308 | dib0090_write_reg(state, 0x19, lo5); | ||
1309 | |||
1310 | dib0090_write_reg(state, 0x1c, lo6); | ||
1311 | |||
1312 | lo6 = tune->tuner_enable; | ||
1313 | if (state->config->analog_output) | ||
1314 | lo6 = (lo6 & 0xff9f) | 0x2; | ||
1315 | |||
1316 | dib0090_write_reg(state, 0x24, lo6 | EN_LO | ||
1317 | #ifdef CONFIG_DIB0090_USE_PWM_AGC | ||
1318 | | state->config->use_pwm_agc * EN_CRYSTAL | ||
1319 | #endif | ||
1320 | ); | ||
1321 | |||
1322 | state->current_rf = rf; | ||
1323 | |||
1324 | /* prepare a complete captrim */ | ||
1325 | state->step = state->captrim = state->fcaptrim = 64; | ||
1326 | |||
1327 | } else { /* we are already tuned to this frequency - the configuration is correct */ | ||
1328 | |||
1329 | /* do a minimal captrim even if the frequency has not changed */ | ||
1330 | state->step = 4; | ||
1331 | state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f; | ||
1332 | } | ||
1333 | state->adc_diff = 3000; | ||
1334 | |||
1335 | dib0090_write_reg(state, 0x10, 0x2B1); | ||
1336 | |||
1337 | dib0090_write_reg(state, 0x1e, 0x0032); | ||
1338 | |||
1339 | ret = 20; | ||
1340 | *tune_state = CT_TUNER_STEP_1; | ||
1341 | } else if (*tune_state == CT_TUNER_STEP_0) { | ||
1342 | /* nothing */ | ||
1343 | } else if (*tune_state == CT_TUNER_STEP_1) { | ||
1344 | state->step /= 2; | ||
1345 | dib0090_write_reg(state, 0x18, lo4 | state->captrim); | ||
1346 | *tune_state = CT_TUNER_STEP_2; | ||
1347 | } else if (*tune_state == CT_TUNER_STEP_2) { | ||
1348 | |||
1349 | adc = dib0090_read_reg(state, 0x1d); | ||
1350 | dprintk("FE %d CAPTRIM=%d; ADC = %d (ADC) & %dmV", (u32) fe->id, (u32) state->captrim, (u32) adc, | ||
1351 | (u32) (adc) * (u32) 1800 / (u32) 1024); | ||
1352 | |||
1353 | if (adc >= 400) { | ||
1354 | adc -= 400; | ||
1355 | step_sign = -1; | ||
1356 | } else { | ||
1357 | adc = 400 - adc; | ||
1358 | step_sign = 1; | ||
1359 | } | ||
1360 | |||
1361 | if (adc < state->adc_diff) { | ||
1362 | dprintk("FE %d CAPTRIM=%d is closer to target (%d/%d)", (u32) fe->id, (u32) state->captrim, (u32) adc, (u32) state->adc_diff); | ||
1363 | state->adc_diff = adc; | ||
1364 | state->fcaptrim = state->captrim; | ||
1365 | |||
1366 | } | ||
1367 | |||
1368 | state->captrim += step_sign * state->step; | ||
1369 | if (state->step >= 1) | ||
1370 | *tune_state = CT_TUNER_STEP_1; | ||
1371 | else | ||
1372 | *tune_state = CT_TUNER_STEP_3; | ||
1373 | |||
1374 | ret = 15; | ||
1375 | } else if (*tune_state == CT_TUNER_STEP_3) { | ||
1376 | /*write the final cptrim config */ | ||
1377 | dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim); | ||
1378 | |||
1379 | #ifdef CONFIG_TUNER_DIB0090_CAPTRIM_MEMORY | ||
1380 | state->memory[state->memory_index].cap = state->fcaptrim; | ||
1381 | #endif | ||
1382 | |||
1383 | *tune_state = CT_TUNER_STEP_4; | ||
1384 | } else if (*tune_state == CT_TUNER_STEP_4) { | ||
1385 | dib0090_write_reg(state, 0x1e, 0x07ff); | ||
1386 | |||
1387 | dprintk("FE %d Final Captrim: %d", (u32) fe->id, (u32) state->fcaptrim); | ||
1388 | dprintk("FE %d HFDIV code: %d", (u32) fe->id, (u32) pll->hfdiv_code); | ||
1389 | dprintk("FE %d VCO = %d", (u32) fe->id, (u32) pll->vco_band); | ||
1390 | dprintk("FE %d VCOF in kHz: %d ((%d*%d) << 1))", (u32) fe->id, (u32) ((pll->hfdiv * rf) * 2), (u32) pll->hfdiv, (u32) rf); | ||
1391 | dprintk("FE %d REFDIV: %d, FREF: %d", (u32) fe->id, (u32) 1, (u32) state->config->io.clock_khz); | ||
1392 | dprintk("FE %d FBDIV: %d, Rest: %d", (u32) fe->id, (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17)); | ||
1393 | dprintk("FE %d Num: %d, Den: %d, SD: %d", (u32) fe->id, (u32) dib0090_read_reg(state, 0x17), | ||
1394 | (u32) (dib0090_read_reg(state, 0x16) >> 8), (u32) dib0090_read_reg(state, 0x1c) & 0x3); | ||
1395 | |||
1396 | c = 4; | ||
1397 | i = 3; | ||
1398 | #if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND) | ||
1399 | if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND)) { | ||
1400 | c = 2; | ||
1401 | i = 2; | ||
1402 | } | ||
1403 | #endif | ||
1404 | dib0090_write_reg(state, 0x10, (c << 13) | (i << 11) | (WBD | ||
1405 | #ifdef CONFIG_DIB0090_USE_PWM_AGC | ||
1406 | | (state->config->use_pwm_agc << 1) | ||
1407 | #endif | ||
1408 | )); | ||
1409 | dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | (tune->lna_bias << 0)); | ||
1410 | dib0090_write_reg(state, 0x0c, tune->v2i); | ||
1411 | dib0090_write_reg(state, 0x0d, tune->mix); | ||
1412 | dib0090_write_reg(state, 0x0e, tune->load); | ||
1413 | |||
1414 | *tune_state = CT_TUNER_STEP_5; | ||
1415 | } else if (*tune_state == CT_TUNER_STEP_5) { | ||
1416 | |||
1417 | /* initialize the lt gain register */ | ||
1418 | state->rf_lt_def = 0x7c00; | ||
1419 | dib0090_write_reg(state, 0x0f, state->rf_lt_def); | ||
1420 | |||
1421 | dib0090_set_bandwidth(state); | ||
1422 | state->tuner_is_tuned = 1; | ||
1423 | *tune_state = CT_TUNER_STOP; | ||
1424 | } else | ||
1425 | ret = FE_CALLBACK_TIME_NEVER; | ||
1426 | return ret; | ||
1427 | } | ||
1428 | |||
1429 | static int dib0090_release(struct dvb_frontend *fe) | ||
1430 | { | ||
1431 | kfree(fe->tuner_priv); | ||
1432 | fe->tuner_priv = NULL; | ||
1433 | return 0; | ||
1434 | } | ||
1435 | |||
1436 | enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe) | ||
1437 | { | ||
1438 | struct dib0090_state *state = fe->tuner_priv; | ||
1439 | |||
1440 | return state->tune_state; | ||
1441 | } | ||
1442 | |||
1443 | EXPORT_SYMBOL(dib0090_get_tune_state); | ||
1444 | |||
1445 | int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) | ||
1446 | { | ||
1447 | struct dib0090_state *state = fe->tuner_priv; | ||
1448 | |||
1449 | state->tune_state = tune_state; | ||
1450 | return 0; | ||
1451 | } | ||
1452 | |||
1453 | EXPORT_SYMBOL(dib0090_set_tune_state); | ||
1454 | |||
1455 | static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency) | ||
1456 | { | ||
1457 | struct dib0090_state *state = fe->tuner_priv; | ||
1458 | |||
1459 | *frequency = 1000 * state->current_rf; | ||
1460 | return 0; | ||
1461 | } | ||
1462 | |||
1463 | static int dib0090_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) | ||
1464 | { | ||
1465 | struct dib0090_state *state = fe->tuner_priv; | ||
1466 | uint32_t ret; | ||
1467 | |||
1468 | state->tune_state = CT_TUNER_START; | ||
1469 | |||
1470 | do { | ||
1471 | ret = dib0090_tune(fe); | ||
1472 | if (ret != FE_CALLBACK_TIME_NEVER) | ||
1473 | msleep(ret / 10); | ||
1474 | else | ||
1475 | break; | ||
1476 | } while (state->tune_state != CT_TUNER_STOP); | ||
1477 | |||
1478 | return 0; | ||
1479 | } | ||
1480 | |||
1481 | static const struct dvb_tuner_ops dib0090_ops = { | ||
1482 | .info = { | ||
1483 | .name = "DiBcom DiB0090", | ||
1484 | .frequency_min = 45000000, | ||
1485 | .frequency_max = 860000000, | ||
1486 | .frequency_step = 1000, | ||
1487 | }, | ||
1488 | .release = dib0090_release, | ||
1489 | |||
1490 | .init = dib0090_wakeup, | ||
1491 | .sleep = dib0090_sleep, | ||
1492 | .set_params = dib0090_set_params, | ||
1493 | .get_frequency = dib0090_get_frequency, | ||
1494 | }; | ||
1495 | |||
1496 | struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config) | ||
1497 | { | ||
1498 | struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL); | ||
1499 | if (st == NULL) | ||
1500 | return NULL; | ||
1501 | |||
1502 | st->config = config; | ||
1503 | st->i2c = i2c; | ||
1504 | st->fe = fe; | ||
1505 | fe->tuner_priv = st; | ||
1506 | |||
1507 | if (dib0090_reset(fe) != 0) | ||
1508 | goto free_mem; | ||
1509 | |||
1510 | printk(KERN_INFO "DiB0090: successfully identified\n"); | ||
1511 | memcpy(&fe->ops.tuner_ops, &dib0090_ops, sizeof(struct dvb_tuner_ops)); | ||
1512 | |||
1513 | return fe; | ||
1514 | free_mem: | ||
1515 | kfree(st); | ||
1516 | fe->tuner_priv = NULL; | ||
1517 | return NULL; | ||
1518 | } | ||
1519 | |||
1520 | EXPORT_SYMBOL(dib0090_register); | ||
1521 | |||
1522 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); | ||
1523 | MODULE_AUTHOR("Olivier Grenie <olivier.grenie@dibcom.fr>"); | ||
1524 | MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner"); | ||
1525 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/frontends/dib0090.h b/drivers/media/dvb/frontends/dib0090.h new file mode 100644 index 000000000000..d72b7d758aa6 --- /dev/null +++ b/drivers/media/dvb/frontends/dib0090.h | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | * Linux-DVB Driver for DiBcom's DiB0090 base-band RF Tuner. | ||
3 | * | ||
4 | * Copyright (C) 2005-7 DiBcom (http://www.dibcom.fr/) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation, version 2. | ||
9 | */ | ||
10 | #ifndef DIB0090_H | ||
11 | #define DIB0090_H | ||
12 | |||
13 | struct dvb_frontend; | ||
14 | struct i2c_adapter; | ||
15 | |||
16 | #define DEFAULT_DIB0090_I2C_ADDRESS 0x60 | ||
17 | |||
18 | struct dib0090_io_config { | ||
19 | u32 clock_khz; | ||
20 | |||
21 | u8 pll_bypass:1; | ||
22 | u8 pll_range:1; | ||
23 | u8 pll_prediv:6; | ||
24 | u8 pll_loopdiv:6; | ||
25 | |||
26 | u8 adc_clock_ratio; /* valid is 8, 7 ,6 */ | ||
27 | u16 pll_int_loop_filt; // internal loop filt value. If not fill in , default is 8165 | ||
28 | }; | ||
29 | |||
30 | struct dib0090_config { | ||
31 | struct dib0090_io_config io; | ||
32 | int (*reset) (struct dvb_frontend *, int); | ||
33 | int (*sleep) (struct dvb_frontend *, int); | ||
34 | |||
35 | /* offset in kHz */ | ||
36 | int freq_offset_khz_uhf; | ||
37 | int freq_offset_khz_vhf; | ||
38 | |||
39 | int (*get_adc_power) (struct dvb_frontend *); | ||
40 | |||
41 | u8 clkouttobamse:1; /* activate or deactivate clock output */ | ||
42 | u8 analog_output; | ||
43 | |||
44 | u8 i2c_address; | ||
45 | /* add drives and other things if necessary */ | ||
46 | u16 wbd_vhf_offset; | ||
47 | u16 wbd_cband_offset; | ||
48 | u8 use_pwm_agc; | ||
49 | u8 clkoutdrive; | ||
50 | }; | ||
51 | |||
52 | #if defined(CONFIG_DVB_TUNER_DIB0090) || (defined(CONFIG_DVB_TUNER_DIB0090_MODULE) && defined(MODULE)) | ||
53 | extern struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config); | ||
54 | extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast); | ||
55 | extern void dib0090_pwm_gain_reset(struct dvb_frontend *fe); | ||
56 | extern u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner); | ||
57 | extern int dib0090_gain_control(struct dvb_frontend *fe); | ||
58 | extern enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe); | ||
59 | extern int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state); | ||
60 | extern enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe); | ||
61 | extern void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt); | ||
62 | #else | ||
63 | static inline struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0090_config *config) | ||
64 | { | ||
65 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
66 | return NULL; | ||
67 | } | ||
68 | |||
69 | static inline void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast) | ||
70 | { | ||
71 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
72 | } | ||
73 | |||
74 | static inline void dib0090_pwm_gain_reset(struct dvb_frontend *fe) | ||
75 | { | ||
76 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
77 | } | ||
78 | |||
79 | static inline u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner) | ||
80 | { | ||
81 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | static inline int dib0090_gain_control(struct dvb_frontend *fe) | ||
86 | { | ||
87 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
88 | return -ENODEV; | ||
89 | } | ||
90 | |||
91 | static inline enum frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe) | ||
92 | { | ||
93 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
94 | return CT_DONE; | ||
95 | } | ||
96 | |||
97 | static inline int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state) | ||
98 | { | ||
99 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
100 | return -ENODEV; | ||
101 | } | ||
102 | |||
103 | static inline num frontend_tune_state dib0090_get_tune_state(struct dvb_frontend *fe) | ||
104 | { | ||
105 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
106 | return CT_SHUTDOWN,} | ||
107 | |||
108 | static inline void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt) | ||
109 | { | ||
110 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
111 | } | ||
112 | #endif | ||
113 | |||
114 | #endif | ||
diff --git a/drivers/media/dvb/frontends/dib8000.c b/drivers/media/dvb/frontends/dib8000.c index 898400d331a3..b924e7eec5ac 100644 --- a/drivers/media/dvb/frontends/dib8000.c +++ b/drivers/media/dvb/frontends/dib8000.c | |||
@@ -28,18 +28,6 @@ MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | |||
28 | 28 | ||
29 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB8000: "); printk(args); printk("\n"); } } while (0) | 29 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB8000: "); printk(args); printk("\n"); } } while (0) |
30 | 30 | ||
31 | enum frontend_tune_state { | ||
32 | CT_AGC_START = 20, | ||
33 | CT_AGC_STEP_0, | ||
34 | CT_AGC_STEP_1, | ||
35 | CT_AGC_STEP_2, | ||
36 | CT_AGC_STEP_3, | ||
37 | CT_AGC_STEP_4, | ||
38 | CT_AGC_STOP, | ||
39 | |||
40 | CT_DEMOD_START = 30, | ||
41 | }; | ||
42 | |||
43 | #define FE_STATUS_TUNE_FAILED 0 | 31 | #define FE_STATUS_TUNE_FAILED 0 |
44 | 32 | ||
45 | struct i2c_device { | 33 | struct i2c_device { |
@@ -852,6 +840,14 @@ static int dib8000_set_agc_config(struct dib8000_state *state, u8 band) | |||
852 | return 0; | 840 | return 0; |
853 | } | 841 | } |
854 | 842 | ||
843 | void dib8000_pwm_agc_reset(struct dvb_frontend *fe) | ||
844 | { | ||
845 | struct dib8000_state *state = fe->demodulator_priv; | ||
846 | dib8000_set_adc_state(state, DIBX000_ADC_ON); | ||
847 | dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000))); | ||
848 | } | ||
849 | EXPORT_SYMBOL(dib8000_pwm_agc_reset); | ||
850 | |||
855 | static int dib8000_agc_soft_split(struct dib8000_state *state) | 851 | static int dib8000_agc_soft_split(struct dib8000_state *state) |
856 | { | 852 | { |
857 | u16 agc, split_offset; | 853 | u16 agc, split_offset; |
@@ -939,6 +935,32 @@ static int dib8000_agc_startup(struct dvb_frontend *fe) | |||
939 | 935 | ||
940 | } | 936 | } |
941 | 937 | ||
938 | static const int32_t lut_1000ln_mant[] = | ||
939 | { | ||
940 | 908,7003,7090,7170,7244,7313,7377,7438,7495,7549,7600 | ||
941 | }; | ||
942 | |||
943 | int32_t dib8000_get_adc_power(struct dvb_frontend *fe, uint8_t mode) | ||
944 | { | ||
945 | struct dib8000_state *state = fe->demodulator_priv; | ||
946 | uint32_t ix =0, tmp_val =0, exp = 0, mant = 0; | ||
947 | int32_t val; | ||
948 | |||
949 | val = dib8000_read32(state, 384); | ||
950 | /* mode = 1 : ln_agcpower calc using mant-exp conversion and mantis look up table */ | ||
951 | if(mode) { | ||
952 | tmp_val = val; | ||
953 | while(tmp_val>>=1) | ||
954 | exp++; | ||
955 | mant = (val * 1000 / (1<<exp)); | ||
956 | ix = (uint8_t)((mant-1000)/100); /* index of the LUT */ | ||
957 | val = (lut_1000ln_mant[ix] + 693*(exp-20) - 6908); /* 1000 * ln(adcpower_real) ; 693 = 1000ln(2) ; 6908 = 1000*ln(1000) ; 20 comes from adc_real = adc_pow_int / 2**20 */ | ||
958 | val = (val*256)/1000; | ||
959 | } | ||
960 | return val; | ||
961 | } | ||
962 | EXPORT_SYMBOL(dib8000_get_adc_power); | ||
963 | |||
942 | static void dib8000_update_timf(struct dib8000_state *state) | 964 | static void dib8000_update_timf(struct dib8000_state *state) |
943 | { | 965 | { |
944 | u32 timf = state->timf = dib8000_read32(state, 435); | 966 | u32 timf = state->timf = dib8000_read32(state, 435); |
@@ -1854,6 +1876,24 @@ static int dib8000_sleep(struct dvb_frontend *fe) | |||
1854 | } | 1876 | } |
1855 | } | 1877 | } |
1856 | 1878 | ||
1879 | enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend* fe) | ||
1880 | { | ||
1881 | struct dib8000_state *state = fe->demodulator_priv; | ||
1882 | return state->tune_state; | ||
1883 | } | ||
1884 | EXPORT_SYMBOL(dib8000_get_tune_state); | ||
1885 | |||
1886 | int dib8000_set_tune_state(struct dvb_frontend* fe, enum frontend_tune_state tune_state) | ||
1887 | { | ||
1888 | struct dib8000_state *state = fe->demodulator_priv; | ||
1889 | state->tune_state = tune_state; | ||
1890 | return 0; | ||
1891 | } | ||
1892 | EXPORT_SYMBOL(dib8000_set_tune_state); | ||
1893 | |||
1894 | |||
1895 | |||
1896 | |||
1857 | static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) | 1897 | static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep) |
1858 | { | 1898 | { |
1859 | struct dib8000_state *state = fe->demodulator_priv; | 1899 | struct dib8000_state *state = fe->demodulator_priv; |
diff --git a/drivers/media/dvb/frontends/dib8000.h b/drivers/media/dvb/frontends/dib8000.h index 8c89482b738a..de05a0ae9d98 100644 --- a/drivers/media/dvb/frontends/dib8000.h +++ b/drivers/media/dvb/frontends/dib8000.h | |||
@@ -46,6 +46,10 @@ extern int dib8000_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val); | |||
46 | extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value); | 46 | extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value); |
47 | extern int dib8000_pid_filter_ctrl(struct dvb_frontend *, u8 onoff); | 47 | extern int dib8000_pid_filter_ctrl(struct dvb_frontend *, u8 onoff); |
48 | extern int dib8000_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff); | 48 | extern int dib8000_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff); |
49 | extern int dib8000_set_tune_state(struct dvb_frontend* fe, enum frontend_tune_state tune_state); | ||
50 | extern enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend* fe); | ||
51 | extern void dib8000_pwm_agc_reset(struct dvb_frontend *fe); | ||
52 | extern s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode); | ||
49 | #else | 53 | #else |
50 | static inline struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg) | 54 | static inline struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg) |
51 | { | 55 | { |
@@ -59,35 +63,53 @@ static inline struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe | |||
59 | return NULL; | 63 | return NULL; |
60 | } | 64 | } |
61 | 65 | ||
62 | int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr) | 66 | static inline int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr) |
63 | { | 67 | { |
64 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | 68 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); |
65 | return -ENODEV; | 69 | return -ENODEV; |
66 | } | 70 | } |
67 | 71 | ||
68 | int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val) | 72 | static inline int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val) |
69 | { | 73 | { |
70 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | 74 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); |
71 | return -ENODEV; | 75 | return -ENODEV; |
72 | } | 76 | } |
73 | 77 | ||
74 | int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value) | 78 | static inline int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value) |
75 | { | 79 | { |
76 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | 80 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); |
77 | return -ENODEV; | 81 | return -ENODEV; |
78 | } | 82 | } |
79 | 83 | ||
80 | int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) | 84 | static inline int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff) |
81 | { | 85 | { |
82 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | 86 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); |
83 | return -ENODEV; | 87 | return -ENODEV; |
84 | } | 88 | } |
85 | 89 | ||
86 | int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) | 90 | static inline int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff) |
87 | { | 91 | { |
88 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | 92 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); |
89 | return -ENODEV; | 93 | return -ENODEV; |
90 | } | 94 | } |
95 | static inline int dib8000_set_tune_state(struct dvb_frontend* fe, enum frontend_tune_state tune_state) | ||
96 | { | ||
97 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
98 | return -ENODEV; | ||
99 | } | ||
100 | static inline enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend* fe) | ||
101 | { | ||
102 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
103 | return CT_SHUTDOWN, | ||
104 | } | ||
105 | static inline void dib8000_pwm_agc_reset(struct dvb_frontend *fe) | ||
106 | { | ||
107 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
108 | } | ||
109 | static inline s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode) | ||
110 | { | ||
111 | printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); | ||
112 | } | ||
91 | #endif | 113 | #endif |
92 | 114 | ||
93 | #endif | 115 | #endif |
diff --git a/drivers/media/dvb/frontends/dibx000_common.c b/drivers/media/dvb/frontends/dibx000_common.c index 4efca30d2127..e6f3d73db9d3 100644 --- a/drivers/media/dvb/frontends/dibx000_common.c +++ b/drivers/media/dvb/frontends/dibx000_common.c | |||
@@ -6,7 +6,7 @@ static int debug; | |||
6 | module_param(debug, int, 0644); | 6 | module_param(debug, int, 0644); |
7 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); | 7 | MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); |
8 | 8 | ||
9 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); } } while (0) | 9 | #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); printk("\n"); } } while (0) |
10 | 10 | ||
11 | static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) | 11 | static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) |
12 | { | 12 | { |
@@ -25,7 +25,7 @@ static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst, | |||
25 | enum dibx000_i2c_interface intf) | 25 | enum dibx000_i2c_interface intf) |
26 | { | 26 | { |
27 | if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) { | 27 | if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) { |
28 | dprintk("selecting interface: %d\n", intf); | 28 | dprintk("selecting interface: %d", intf); |
29 | mst->selected_interface = intf; | 29 | mst->selected_interface = intf; |
30 | return dibx000_write_word(mst, mst->base_reg + 4, intf); | 30 | return dibx000_write_word(mst, mst->base_reg + 4, intf); |
31 | } | 31 | } |
@@ -171,9 +171,18 @@ void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst) | |||
171 | { | 171 | { |
172 | i2c_del_adapter(&mst->gated_tuner_i2c_adap); | 172 | i2c_del_adapter(&mst->gated_tuner_i2c_adap); |
173 | } | 173 | } |
174 | |||
175 | EXPORT_SYMBOL(dibx000_exit_i2c_master); | 174 | EXPORT_SYMBOL(dibx000_exit_i2c_master); |
176 | 175 | ||
176 | |||
177 | u32 systime() | ||
178 | { | ||
179 | struct timespec t; | ||
180 | |||
181 | t = current_kernel_time(); | ||
182 | return (t.tv_sec * 10000) + (t.tv_nsec / 100000); | ||
183 | } | ||
184 | EXPORT_SYMBOL(systime); | ||
185 | |||
177 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); | 186 | MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); |
178 | MODULE_DESCRIPTION("Common function the DiBcom demodulator family"); | 187 | MODULE_DESCRIPTION("Common function the DiBcom demodulator family"); |
179 | MODULE_LICENSE("GPL"); | 188 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/media/dvb/frontends/dibx000_common.h b/drivers/media/dvb/frontends/dibx000_common.h index 5be10eca07c0..06328d8742f8 100644 --- a/drivers/media/dvb/frontends/dibx000_common.h +++ b/drivers/media/dvb/frontends/dibx000_common.h | |||
@@ -36,13 +36,17 @@ extern struct i2c_adapter *dibx000_get_i2c_adapter(struct dibx000_i2c_master | |||
36 | extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst); | 36 | extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst); |
37 | extern void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst); | 37 | extern void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst); |
38 | 38 | ||
39 | extern u32 systime(void); | ||
40 | |||
39 | #define BAND_LBAND 0x01 | 41 | #define BAND_LBAND 0x01 |
40 | #define BAND_UHF 0x02 | 42 | #define BAND_UHF 0x02 |
41 | #define BAND_VHF 0x04 | 43 | #define BAND_VHF 0x04 |
42 | #define BAND_SBAND 0x08 | 44 | #define BAND_SBAND 0x08 |
43 | #define BAND_FM 0x10 | 45 | #define BAND_FM 0x10 |
46 | #define BAND_CBAND 0x20 | ||
44 | 47 | ||
45 | #define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 115000 ? BAND_FM : \ | 48 | #define BAND_OF_FREQUENCY(freq_kHz) ( (freq_kHz) <= 170000 ? BAND_CBAND : \ |
49 | (freq_kHz) <= 115000 ? BAND_FM : \ | ||
46 | (freq_kHz) <= 250000 ? BAND_VHF : \ | 50 | (freq_kHz) <= 250000 ? BAND_VHF : \ |
47 | (freq_kHz) <= 863000 ? BAND_UHF : \ | 51 | (freq_kHz) <= 863000 ? BAND_UHF : \ |
48 | (freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND ) | 52 | (freq_kHz) <= 2000000 ? BAND_LBAND : BAND_SBAND ) |
@@ -149,4 +153,67 @@ enum dibx000_adc_states { | |||
149 | #define OUTMODE_MPEG2_FIFO 5 | 153 | #define OUTMODE_MPEG2_FIFO 5 |
150 | #define OUTMODE_ANALOG_ADC 6 | 154 | #define OUTMODE_ANALOG_ADC 6 |
151 | 155 | ||
156 | enum frontend_tune_state { | ||
157 | CT_TUNER_START = 10, | ||
158 | CT_TUNER_STEP_0, | ||
159 | CT_TUNER_STEP_1, | ||
160 | CT_TUNER_STEP_2, | ||
161 | CT_TUNER_STEP_3, | ||
162 | CT_TUNER_STEP_4, | ||
163 | CT_TUNER_STEP_5, | ||
164 | CT_TUNER_STEP_6, | ||
165 | CT_TUNER_STEP_7, | ||
166 | CT_TUNER_STOP, | ||
167 | |||
168 | CT_AGC_START = 20, | ||
169 | CT_AGC_STEP_0, | ||
170 | CT_AGC_STEP_1, | ||
171 | CT_AGC_STEP_2, | ||
172 | CT_AGC_STEP_3, | ||
173 | CT_AGC_STEP_4, | ||
174 | CT_AGC_STOP, | ||
175 | |||
176 | CT_DEMOD_START = 30, | ||
177 | CT_DEMOD_STEP_1, | ||
178 | CT_DEMOD_STEP_2, | ||
179 | CT_DEMOD_STEP_3, | ||
180 | CT_DEMOD_STEP_4, | ||
181 | CT_DEMOD_STEP_5, | ||
182 | CT_DEMOD_STEP_6, | ||
183 | CT_DEMOD_STEP_7, | ||
184 | CT_DEMOD_STEP_8, | ||
185 | CT_DEMOD_STEP_9, | ||
186 | CT_DEMOD_STEP_10, | ||
187 | CT_DEMOD_SEARCH_NEXT = 41, | ||
188 | CT_DEMOD_STEP_LOCKED, | ||
189 | CT_DEMOD_STOP, | ||
190 | |||
191 | CT_DONE = 100, | ||
192 | CT_SHUTDOWN, | ||
193 | |||
194 | }; | ||
195 | |||
196 | struct dvb_frontend_parametersContext { | ||
197 | #define CHANNEL_STATUS_PARAMETERS_UNKNOWN 0x01 | ||
198 | #define CHANNEL_STATUS_PARAMETERS_SET 0x02 | ||
199 | u8 status; | ||
200 | u32 tune_time_estimation[2]; | ||
201 | s32 tps_available; | ||
202 | u16 tps[9]; | ||
203 | }; | ||
204 | |||
205 | #define FE_STATUS_TUNE_FAILED 0 | ||
206 | #define FE_STATUS_TUNE_TIMED_OUT -1 | ||
207 | #define FE_STATUS_TUNE_TIME_TOO_SHORT -2 | ||
208 | #define FE_STATUS_TUNE_PENDING -3 | ||
209 | #define FE_STATUS_STD_SUCCESS -4 | ||
210 | #define FE_STATUS_FFT_SUCCESS -5 | ||
211 | #define FE_STATUS_DEMOD_SUCCESS -6 | ||
212 | #define FE_STATUS_LOCKED -7 | ||
213 | #define FE_STATUS_DATA_LOCKED -8 | ||
214 | |||
215 | #define FE_CALLBACK_TIME_NEVER 0xffffffff | ||
216 | |||
217 | #define ABS(x) ((x<0)?(-x):(x)) | ||
218 | |||
152 | #endif | 219 | #endif |