diff options
author | David Wong <davidtlwong@gmail.com> | 2009-06-17 00:38:10 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-12 11:17:38 -0400 |
commit | b80dc1c673f5ff79805215eb94ff008e634e4b2d (patch) | |
tree | 80a5849fadf39d81837a8e3ad5443b58032b8382 /drivers/media/dvb/frontends | |
parent | a0d64456f765297782d34750cf4dc862f2a8bce0 (diff) |
V4L/DVB (12271): lgs8gxx: add lgs8g75 support
lgs8gxx: add lgs8g75 demodulator support
Signed-off-by: David T.L. Wong <davidtlwong@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/frontends')
-rw-r--r-- | drivers/media/dvb/frontends/lgs8gxx.c | 484 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/lgs8gxx.h | 11 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/lgs8gxx_priv.h | 12 |
3 files changed, 401 insertions, 106 deletions
diff --git a/drivers/media/dvb/frontends/lgs8gxx.c b/drivers/media/dvb/frontends/lgs8gxx.c index fde27645bbed..eabcadc425d5 100644 --- a/drivers/media/dvb/frontends/lgs8gxx.c +++ b/drivers/media/dvb/frontends/lgs8gxx.c | |||
@@ -1,9 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * Support for Legend Silicon DMB-TH demodulator | 2 | * Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator |
3 | * LGS8913, LGS8GL5 | 3 | * LGS8913, LGS8GL5, LGS8G75 |
4 | * experimental support LGS8G42, LGS8G52 | 4 | * experimental support LGS8G42, LGS8G52 |
5 | * | 5 | * |
6 | * Copyright (C) 2007,2008 David T.L. Wong <davidtlwong@gmail.com> | 6 | * Copyright (C) 2007-2009 David T.L. Wong <davidtlwong@gmail.com> |
7 | * Copyright (C) 2008 Sirius International (Hong Kong) Limited | 7 | * Copyright (C) 2008 Sirius International (Hong Kong) Limited |
8 | * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5) | 8 | * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5) |
9 | * | 9 | * |
@@ -46,6 +46,42 @@ module_param(fake_signal_str, int, 0644); | |||
46 | MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913." | 46 | MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913." |
47 | "Signal strength calculation is slow.(default:on)."); | 47 | "Signal strength calculation is slow.(default:on)."); |
48 | 48 | ||
49 | static const u8 lgs8g75_initdat[] = { | ||
50 | 0x01, 0x30, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
51 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
52 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
53 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
54 | 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
55 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
56 | 0xE4, 0xF5, 0xA8, 0xF5, 0xB8, 0xF5, 0x88, 0xF5, | ||
57 | 0x89, 0xF5, 0x87, 0x75, 0xD0, 0x00, 0x11, 0x50, | ||
58 | 0x11, 0x50, 0xF4, 0xF5, 0x80, 0xF5, 0x90, 0xF5, | ||
59 | 0xA0, 0xF5, 0xB0, 0x75, 0x81, 0x30, 0x80, 0x01, | ||
60 | 0x32, 0x90, 0x80, 0x12, 0x74, 0xFF, 0xF0, 0x90, | ||
61 | 0x80, 0x13, 0x74, 0x1F, 0xF0, 0x90, 0x80, 0x23, | ||
62 | 0x74, 0x01, 0xF0, 0x90, 0x80, 0x22, 0xF0, 0x90, | ||
63 | 0x00, 0x48, 0x74, 0x00, 0xF0, 0x90, 0x80, 0x4D, | ||
64 | 0x74, 0x05, 0xF0, 0x90, 0x80, 0x09, 0xE0, 0x60, | ||
65 | 0x21, 0x12, 0x00, 0xDD, 0x14, 0x60, 0x1B, 0x12, | ||
66 | 0x00, 0xDD, 0x14, 0x60, 0x15, 0x12, 0x00, 0xDD, | ||
67 | 0x14, 0x60, 0x0F, 0x12, 0x00, 0xDD, 0x14, 0x60, | ||
68 | 0x09, 0x12, 0x00, 0xDD, 0x14, 0x60, 0x03, 0x12, | ||
69 | 0x00, 0xDD, 0x90, 0x80, 0x42, 0xE0, 0x60, 0x0B, | ||
70 | 0x14, 0x60, 0x0C, 0x14, 0x60, 0x0D, 0x14, 0x60, | ||
71 | 0x0E, 0x01, 0xB3, 0x74, 0x04, 0x01, 0xB9, 0x74, | ||
72 | 0x05, 0x01, 0xB9, 0x74, 0x07, 0x01, 0xB9, 0x74, | ||
73 | 0x0A, 0xC0, 0xE0, 0x74, 0xC8, 0x12, 0x00, 0xE2, | ||
74 | 0xD0, 0xE0, 0x14, 0x70, 0xF4, 0x90, 0x80, 0x09, | ||
75 | 0xE0, 0x70, 0xAE, 0x12, 0x00, 0xF6, 0x12, 0x00, | ||
76 | 0xFE, 0x90, 0x00, 0x48, 0xE0, 0x04, 0xF0, 0x90, | ||
77 | 0x80, 0x4E, 0xF0, 0x01, 0x73, 0x90, 0x80, 0x08, | ||
78 | 0xF0, 0x22, 0xF8, 0x7A, 0x0C, 0x79, 0xFD, 0x00, | ||
79 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD9, | ||
80 | 0xF6, 0xDA, 0xF2, 0xD8, 0xEE, 0x22, 0x90, 0x80, | ||
81 | 0x65, 0xE0, 0x54, 0xFD, 0xF0, 0x22, 0x90, 0x80, | ||
82 | 0x65, 0xE0, 0x44, 0xC2, 0xF0, 0x22 | ||
83 | }; | ||
84 | |||
49 | /* LGS8GXX internal helper functions */ | 85 | /* LGS8GXX internal helper functions */ |
50 | 86 | ||
51 | static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data) | 87 | static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data) |
@@ -55,7 +91,7 @@ static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data) | |||
55 | struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 }; | 91 | struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 }; |
56 | 92 | ||
57 | msg.addr = priv->config->demod_address; | 93 | msg.addr = priv->config->demod_address; |
58 | if (reg >= 0xC0) | 94 | if (priv->config->prod != LGS8GXX_PROD_LGS8G75 && reg >= 0xC0) |
59 | msg.addr += 0x02; | 95 | msg.addr += 0x02; |
60 | 96 | ||
61 | if (debug >= 2) | 97 | if (debug >= 2) |
@@ -84,7 +120,7 @@ static int lgs8gxx_read_reg(struct lgs8gxx_state *priv, u8 reg, u8 *p_data) | |||
84 | }; | 120 | }; |
85 | 121 | ||
86 | dev_addr = priv->config->demod_address; | 122 | dev_addr = priv->config->demod_address; |
87 | if (reg >= 0xC0) | 123 | if (priv->config->prod != LGS8GXX_PROD_LGS8G75 && reg >= 0xC0) |
88 | dev_addr += 0x02; | 124 | dev_addr += 0x02; |
89 | msg[1].addr = msg[0].addr = dev_addr; | 125 | msg[1].addr = msg[0].addr = dev_addr; |
90 | 126 | ||
@@ -112,19 +148,36 @@ static int lgs8gxx_soft_reset(struct lgs8gxx_state *priv) | |||
112 | return 0; | 148 | return 0; |
113 | } | 149 | } |
114 | 150 | ||
151 | static int wait_reg_mask(struct lgs8gxx_state *priv, u8 reg, u8 mask, | ||
152 | u8 val, u8 delay, u8 tries) | ||
153 | { | ||
154 | u8 t; | ||
155 | int i; | ||
156 | |||
157 | for (i = 0; i < tries; i++) { | ||
158 | lgs8gxx_read_reg(priv, reg, &t); | ||
159 | |||
160 | if ((t & mask) == val) | ||
161 | return 0; | ||
162 | msleep(delay); | ||
163 | } | ||
164 | |||
165 | return 1; | ||
166 | } | ||
167 | |||
115 | static int lgs8gxx_set_ad_mode(struct lgs8gxx_state *priv) | 168 | static int lgs8gxx_set_ad_mode(struct lgs8gxx_state *priv) |
116 | { | 169 | { |
117 | const struct lgs8gxx_config *config = priv->config; | 170 | const struct lgs8gxx_config *config = priv->config; |
118 | u8 if_conf; | 171 | u8 if_conf; |
119 | 172 | ||
120 | if_conf = 0x10; /* AGC output on; */ | 173 | if_conf = 0x10; /* AGC output on, RF_AGC output off; */ |
121 | 174 | ||
122 | if_conf |= | 175 | if_conf |= |
123 | ((config->ext_adc) ? 0x80 : 0x00) | | 176 | ((config->ext_adc) ? 0x80 : 0x00) | |
124 | ((config->if_neg_center) ? 0x04 : 0x00) | | 177 | ((config->if_neg_center) ? 0x04 : 0x00) | |
125 | ((config->if_freq == 0) ? 0x08 : 0x00) | /* Baseband */ | 178 | ((config->if_freq == 0) ? 0x08 : 0x00) | /* Baseband */ |
126 | ((config->ext_adc && config->adc_signed) ? 0x02 : 0x00) | | 179 | ((config->adc_signed) ? 0x02 : 0x00) | |
127 | ((config->ext_adc && config->if_neg_edge) ? 0x01 : 0x00); | 180 | ((config->if_neg_edge) ? 0x01 : 0x00); |
128 | 181 | ||
129 | if (config->ext_adc && | 182 | if (config->ext_adc && |
130 | (config->prod == LGS8GXX_PROD_LGS8G52)) { | 183 | (config->prod == LGS8GXX_PROD_LGS8G52)) { |
@@ -157,39 +210,82 @@ static int lgs8gxx_set_if_freq(struct lgs8gxx_state *priv, u32 freq /*in kHz*/) | |||
157 | } | 210 | } |
158 | dprintk("AFC_INIT_FREQ = 0x%08X\n", v32); | 211 | dprintk("AFC_INIT_FREQ = 0x%08X\n", v32); |
159 | 212 | ||
160 | lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32)); | 213 | if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { |
161 | lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 8)); | 214 | lgs8gxx_write_reg(priv, 0x08, 0xFF & (v32)); |
162 | lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 16)); | 215 | lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32 >> 8)); |
163 | lgs8gxx_write_reg(priv, 0x0C, 0xFF & (v32 >> 24)); | 216 | lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 16)); |
217 | lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 24)); | ||
218 | } else { | ||
219 | lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32)); | ||
220 | lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 8)); | ||
221 | lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 16)); | ||
222 | lgs8gxx_write_reg(priv, 0x0C, 0xFF & (v32 >> 24)); | ||
223 | } | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static int lgs8gxx_get_afc_phase(struct lgs8gxx_state *priv) | ||
229 | { | ||
230 | u64 val; | ||
231 | u32 v32 = 0; | ||
232 | u8 reg_addr, t; | ||
233 | int i; | ||
234 | |||
235 | if (priv->config->prod == LGS8GXX_PROD_LGS8G75) | ||
236 | reg_addr = 0x23; | ||
237 | else | ||
238 | reg_addr = 0x48; | ||
239 | |||
240 | for (i = 0; i < 4; i++) { | ||
241 | lgs8gxx_read_reg(priv, reg_addr, &t); | ||
242 | v32 <<= 8; | ||
243 | v32 |= t; | ||
244 | reg_addr--; | ||
245 | } | ||
164 | 246 | ||
247 | val = v32; | ||
248 | val *= priv->config->if_clk_freq; | ||
249 | val /= (u64)1 << 32; | ||
250 | dprintk("AFC = %u kHz\n", (u32)val); | ||
165 | return 0; | 251 | return 0; |
166 | } | 252 | } |
167 | 253 | ||
168 | static int lgs8gxx_set_mode_auto(struct lgs8gxx_state *priv) | 254 | static int lgs8gxx_set_mode_auto(struct lgs8gxx_state *priv) |
169 | { | 255 | { |
170 | u8 t; | 256 | u8 t; |
257 | u8 prod = priv->config->prod; | ||
171 | 258 | ||
172 | if (priv->config->prod == LGS8GXX_PROD_LGS8913) | 259 | if (prod == LGS8GXX_PROD_LGS8913) |
173 | lgs8gxx_write_reg(priv, 0xC6, 0x01); | 260 | lgs8gxx_write_reg(priv, 0xC6, 0x01); |
174 | 261 | ||
175 | lgs8gxx_read_reg(priv, 0x7E, &t); | 262 | if (prod == LGS8GXX_PROD_LGS8G75) { |
176 | lgs8gxx_write_reg(priv, 0x7E, t | 0x01); | 263 | lgs8gxx_read_reg(priv, 0x0C, &t); |
177 | 264 | t &= (~0x04); | |
178 | /* clear FEC self reset */ | 265 | lgs8gxx_write_reg(priv, 0x0C, t | 0x80); |
179 | lgs8gxx_read_reg(priv, 0xC5, &t); | 266 | lgs8gxx_write_reg(priv, 0x39, 0x00); |
180 | lgs8gxx_write_reg(priv, 0xC5, t & 0xE0); | 267 | lgs8gxx_write_reg(priv, 0x3D, 0x04); |
268 | } else if (prod == LGS8GXX_PROD_LGS8913 || | ||
269 | prod == LGS8GXX_PROD_LGS8GL5 || | ||
270 | prod == LGS8GXX_PROD_LGS8G42 || | ||
271 | prod == LGS8GXX_PROD_LGS8G52 || | ||
272 | prod == LGS8GXX_PROD_LGS8G54) { | ||
273 | lgs8gxx_read_reg(priv, 0x7E, &t); | ||
274 | lgs8gxx_write_reg(priv, 0x7E, t | 0x01); | ||
275 | |||
276 | /* clear FEC self reset */ | ||
277 | lgs8gxx_read_reg(priv, 0xC5, &t); | ||
278 | lgs8gxx_write_reg(priv, 0xC5, t & 0xE0); | ||
279 | } | ||
181 | 280 | ||
182 | if (priv->config->prod == LGS8GXX_PROD_LGS8913) { | 281 | if (prod == LGS8GXX_PROD_LGS8913) { |
183 | /* FEC auto detect */ | 282 | /* FEC auto detect */ |
184 | lgs8gxx_write_reg(priv, 0xC1, 0x03); | 283 | lgs8gxx_write_reg(priv, 0xC1, 0x03); |
185 | 284 | ||
186 | lgs8gxx_read_reg(priv, 0x7C, &t); | 285 | lgs8gxx_read_reg(priv, 0x7C, &t); |
187 | t = (t & 0x8C) | 0x03; | 286 | t = (t & 0x8C) | 0x03; |
188 | lgs8gxx_write_reg(priv, 0x7C, t); | 287 | lgs8gxx_write_reg(priv, 0x7C, t); |
189 | } | ||
190 | |||
191 | 288 | ||
192 | if (priv->config->prod == LGS8GXX_PROD_LGS8913) { | ||
193 | /* BER test mode */ | 289 | /* BER test mode */ |
194 | lgs8gxx_read_reg(priv, 0xC3, &t); | 290 | lgs8gxx_read_reg(priv, 0xC3, &t); |
195 | t = (t & 0xEF) | 0x10; | 291 | t = (t & 0xEF) | 0x10; |
@@ -207,6 +303,32 @@ static int lgs8gxx_set_mode_manual(struct lgs8gxx_state *priv) | |||
207 | int ret = 0; | 303 | int ret = 0; |
208 | u8 t; | 304 | u8 t; |
209 | 305 | ||
306 | if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { | ||
307 | u8 t2; | ||
308 | lgs8gxx_read_reg(priv, 0x0C, &t); | ||
309 | t &= (~0x80); | ||
310 | lgs8gxx_write_reg(priv, 0x0C, t); | ||
311 | |||
312 | lgs8gxx_read_reg(priv, 0x0C, &t); | ||
313 | lgs8gxx_read_reg(priv, 0x19, &t2); | ||
314 | |||
315 | if (((t&0x03) == 0x01) && (t2&0x01)) { | ||
316 | lgs8gxx_write_reg(priv, 0x6E, 0x05); | ||
317 | lgs8gxx_write_reg(priv, 0x39, 0x02); | ||
318 | lgs8gxx_write_reg(priv, 0x39, 0x03); | ||
319 | lgs8gxx_write_reg(priv, 0x3D, 0x05); | ||
320 | lgs8gxx_write_reg(priv, 0x3E, 0x28); | ||
321 | lgs8gxx_write_reg(priv, 0x53, 0x80); | ||
322 | } else { | ||
323 | lgs8gxx_write_reg(priv, 0x6E, 0x3F); | ||
324 | lgs8gxx_write_reg(priv, 0x39, 0x00); | ||
325 | lgs8gxx_write_reg(priv, 0x3D, 0x04); | ||
326 | } | ||
327 | |||
328 | lgs8gxx_soft_reset(priv); | ||
329 | return 0; | ||
330 | } | ||
331 | |||
210 | /* turn off auto-detect; manual settings */ | 332 | /* turn off auto-detect; manual settings */ |
211 | lgs8gxx_write_reg(priv, 0x7E, 0); | 333 | lgs8gxx_write_reg(priv, 0x7E, 0); |
212 | if (priv->config->prod == LGS8GXX_PROD_LGS8913) | 334 | if (priv->config->prod == LGS8GXX_PROD_LGS8913) |
@@ -226,11 +348,39 @@ static int lgs8gxx_is_locked(struct lgs8gxx_state *priv, u8 *locked) | |||
226 | int ret = 0; | 348 | int ret = 0; |
227 | u8 t; | 349 | u8 t; |
228 | 350 | ||
229 | ret = lgs8gxx_read_reg(priv, 0x4B, &t); | 351 | if (priv->config->prod == LGS8GXX_PROD_LGS8G75) |
352 | ret = lgs8gxx_read_reg(priv, 0x13, &t); | ||
353 | else | ||
354 | ret = lgs8gxx_read_reg(priv, 0x4B, &t); | ||
230 | if (ret != 0) | 355 | if (ret != 0) |
231 | return ret; | 356 | return ret; |
232 | 357 | ||
233 | *locked = ((t & 0xC0) == 0xC0) ? 1 : 0; | 358 | if (priv->config->prod == LGS8GXX_PROD_LGS8G75) |
359 | *locked = ((t & 0x80) == 0x80) ? 1 : 0; | ||
360 | else | ||
361 | *locked = ((t & 0xC0) == 0xC0) ? 1 : 0; | ||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | /* Wait for Code Acquisition Lock */ | ||
366 | static int lgs8gxx_wait_ca_lock(struct lgs8gxx_state *priv, u8 *locked) | ||
367 | { | ||
368 | int ret = 0; | ||
369 | u8 reg, mask, val; | ||
370 | |||
371 | if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { | ||
372 | reg = 0x13; | ||
373 | mask = 0x80; | ||
374 | val = 0x80; | ||
375 | } else { | ||
376 | reg = 0x4B; | ||
377 | mask = 0xC0; | ||
378 | val = 0xC0; | ||
379 | } | ||
380 | |||
381 | ret = wait_reg_mask(priv, reg, mask, val, 50, 40); | ||
382 | *locked = (ret == 0) ? 1 : 0; | ||
383 | |||
234 | return 0; | 384 | return 0; |
235 | } | 385 | } |
236 | 386 | ||
@@ -238,21 +388,30 @@ static int lgs8gxx_is_autodetect_finished(struct lgs8gxx_state *priv, | |||
238 | u8 *finished) | 388 | u8 *finished) |
239 | { | 389 | { |
240 | int ret = 0; | 390 | int ret = 0; |
241 | u8 t; | 391 | u8 reg, mask, val; |
242 | 392 | ||
243 | ret = lgs8gxx_read_reg(priv, 0xA4, &t); | 393 | if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { |
244 | if (ret != 0) | 394 | reg = 0x1f; |
245 | return ret; | 395 | mask = 0xC0; |
396 | val = 0x80; | ||
397 | } else { | ||
398 | reg = 0xA4; | ||
399 | mask = 0x03; | ||
400 | val = 0x01; | ||
401 | } | ||
246 | 402 | ||
247 | *finished = ((t & 0x3) == 0x1) ? 1 : 0; | 403 | ret = wait_reg_mask(priv, reg, mask, val, 10, 20); |
404 | *finished = (ret == 0) ? 1 : 0; | ||
248 | 405 | ||
249 | return 0; | 406 | return 0; |
250 | } | 407 | } |
251 | 408 | ||
252 | static int lgs8gxx_autolock_gi(struct lgs8gxx_state *priv, u8 gi, u8 *locked) | 409 | static int lgs8gxx_autolock_gi(struct lgs8gxx_state *priv, u8 gi, u8 cpn, |
410 | u8 *locked) | ||
253 | { | 411 | { |
254 | int err; | 412 | int err = 0; |
255 | u8 ad_fini = 0; | 413 | u8 ad_fini = 0; |
414 | u8 t1, t2; | ||
256 | 415 | ||
257 | if (gi == GI_945) | 416 | if (gi == GI_945) |
258 | dprintk("try GI 945\n"); | 417 | dprintk("try GI 945\n"); |
@@ -260,17 +419,29 @@ static int lgs8gxx_autolock_gi(struct lgs8gxx_state *priv, u8 gi, u8 *locked) | |||
260 | dprintk("try GI 595\n"); | 419 | dprintk("try GI 595\n"); |
261 | else if (gi == GI_420) | 420 | else if (gi == GI_420) |
262 | dprintk("try GI 420\n"); | 421 | dprintk("try GI 420\n"); |
263 | lgs8gxx_write_reg(priv, 0x04, gi); | 422 | if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { |
423 | lgs8gxx_read_reg(priv, 0x0C, &t1); | ||
424 | lgs8gxx_read_reg(priv, 0x18, &t2); | ||
425 | t1 &= ~(GI_MASK); | ||
426 | t1 |= gi; | ||
427 | t2 &= 0xFE; | ||
428 | t2 |= cpn ? 0x01 : 0x00; | ||
429 | lgs8gxx_write_reg(priv, 0x0C, t1); | ||
430 | lgs8gxx_write_reg(priv, 0x18, t2); | ||
431 | } else { | ||
432 | lgs8gxx_write_reg(priv, 0x04, gi); | ||
433 | } | ||
264 | lgs8gxx_soft_reset(priv); | 434 | lgs8gxx_soft_reset(priv); |
265 | msleep(50); | 435 | err = lgs8gxx_wait_ca_lock(priv, locked); |
436 | if (err || !(*locked)) | ||
437 | return err; | ||
266 | err = lgs8gxx_is_autodetect_finished(priv, &ad_fini); | 438 | err = lgs8gxx_is_autodetect_finished(priv, &ad_fini); |
267 | if (err != 0) | 439 | if (err != 0) |
268 | return err; | 440 | return err; |
269 | if (ad_fini) { | 441 | if (ad_fini) { |
270 | err = lgs8gxx_is_locked(priv, locked); | 442 | dprintk("auto detect finished\n"); |
271 | if (err != 0) | 443 | } else |
272 | return err; | 444 | *locked = 0; |
273 | } | ||
274 | 445 | ||
275 | return 0; | 446 | return 0; |
276 | } | 447 | } |
@@ -285,13 +456,18 @@ static int lgs8gxx_auto_detect(struct lgs8gxx_state *priv, | |||
285 | dprintk("%s\n", __func__); | 456 | dprintk("%s\n", __func__); |
286 | 457 | ||
287 | lgs8gxx_set_mode_auto(priv); | 458 | lgs8gxx_set_mode_auto(priv); |
288 | /* Guard Interval */ | 459 | if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { |
289 | lgs8gxx_write_reg(priv, 0x03, 00); | 460 | lgs8gxx_write_reg(priv, 0x67, 0xAA); |
461 | lgs8gxx_write_reg(priv, 0x6E, 0x3F); | ||
462 | } else { | ||
463 | /* Guard Interval */ | ||
464 | lgs8gxx_write_reg(priv, 0x03, 00); | ||
465 | } | ||
290 | 466 | ||
291 | for (i = 0; i < 2; i++) { | 467 | for (i = 0; i < 2; i++) { |
292 | for (j = 0; j < 2; j++) { | 468 | for (j = 0; j < 2; j++) { |
293 | tmp_gi = GI_945; | 469 | tmp_gi = GI_945; |
294 | err = lgs8gxx_autolock_gi(priv, GI_945, &locked); | 470 | err = lgs8gxx_autolock_gi(priv, GI_945, j, &locked); |
295 | if (err) | 471 | if (err) |
296 | goto out; | 472 | goto out; |
297 | if (locked) | 473 | if (locked) |
@@ -299,14 +475,14 @@ static int lgs8gxx_auto_detect(struct lgs8gxx_state *priv, | |||
299 | } | 475 | } |
300 | for (j = 0; j < 2; j++) { | 476 | for (j = 0; j < 2; j++) { |
301 | tmp_gi = GI_420; | 477 | tmp_gi = GI_420; |
302 | err = lgs8gxx_autolock_gi(priv, GI_420, &locked); | 478 | err = lgs8gxx_autolock_gi(priv, GI_420, j, &locked); |
303 | if (err) | 479 | if (err) |
304 | goto out; | 480 | goto out; |
305 | if (locked) | 481 | if (locked) |
306 | goto locked; | 482 | goto locked; |
307 | } | 483 | } |
308 | tmp_gi = GI_595; | 484 | tmp_gi = GI_595; |
309 | err = lgs8gxx_autolock_gi(priv, GI_595, &locked); | 485 | err = lgs8gxx_autolock_gi(priv, GI_595, 1, &locked); |
310 | if (err) | 486 | if (err) |
311 | goto out; | 487 | goto out; |
312 | if (locked) | 488 | if (locked) |
@@ -317,8 +493,13 @@ locked: | |||
317 | if ((err == 0) && (locked == 1)) { | 493 | if ((err == 0) && (locked == 1)) { |
318 | u8 t; | 494 | u8 t; |
319 | 495 | ||
320 | lgs8gxx_read_reg(priv, 0xA2, &t); | 496 | if (priv->config->prod != LGS8GXX_PROD_LGS8G75) { |
321 | *detected_param = t; | 497 | lgs8gxx_read_reg(priv, 0xA2, &t); |
498 | *detected_param = t; | ||
499 | } else { | ||
500 | lgs8gxx_read_reg(priv, 0x1F, &t); | ||
501 | *detected_param = t & 0x3F; | ||
502 | } | ||
322 | 503 | ||
323 | if (tmp_gi == GI_945) | 504 | if (tmp_gi == GI_945) |
324 | dprintk("GI 945 locked\n"); | 505 | dprintk("GI 945 locked\n"); |
@@ -345,18 +526,28 @@ static void lgs8gxx_auto_lock(struct lgs8gxx_state *priv) | |||
345 | 526 | ||
346 | if (err != 0) { | 527 | if (err != 0) { |
347 | dprintk("lgs8gxx_auto_detect failed\n"); | 528 | dprintk("lgs8gxx_auto_detect failed\n"); |
348 | } | 529 | } else |
530 | dprintk("detected param = 0x%02X\n", detected_param); | ||
349 | 531 | ||
350 | /* Apply detected parameters */ | 532 | /* Apply detected parameters */ |
351 | if (priv->config->prod == LGS8GXX_PROD_LGS8913) { | 533 | if (priv->config->prod == LGS8GXX_PROD_LGS8913) { |
352 | u8 inter_leave_len = detected_param & TIM_MASK ; | 534 | u8 inter_leave_len = detected_param & TIM_MASK ; |
353 | inter_leave_len = (inter_leave_len == TIM_LONG) ? 0x60 : 0x40; | 535 | /* Fix 8913 time interleaver detection bug */ |
536 | inter_leave_len = (inter_leave_len == TIM_MIDDLE) ? 0x60 : 0x40; | ||
354 | detected_param &= CF_MASK | SC_MASK | LGS_FEC_MASK; | 537 | detected_param &= CF_MASK | SC_MASK | LGS_FEC_MASK; |
355 | detected_param |= inter_leave_len; | 538 | detected_param |= inter_leave_len; |
356 | } | 539 | } |
357 | lgs8gxx_write_reg(priv, 0x7D, detected_param); | 540 | if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { |
358 | if (priv->config->prod == LGS8GXX_PROD_LGS8913) | 541 | u8 t; |
359 | lgs8gxx_write_reg(priv, 0xC0, detected_param); | 542 | lgs8gxx_read_reg(priv, 0x19, &t); |
543 | t &= 0x81; | ||
544 | t |= detected_param << 1; | ||
545 | lgs8gxx_write_reg(priv, 0x19, t); | ||
546 | } else { | ||
547 | lgs8gxx_write_reg(priv, 0x7D, detected_param); | ||
548 | if (priv->config->prod == LGS8GXX_PROD_LGS8913) | ||
549 | lgs8gxx_write_reg(priv, 0xC0, detected_param); | ||
550 | } | ||
360 | /* lgs8gxx_soft_reset(priv); */ | 551 | /* lgs8gxx_soft_reset(priv); */ |
361 | 552 | ||
362 | /* Enter manual mode */ | 553 | /* Enter manual mode */ |
@@ -378,9 +569,10 @@ static int lgs8gxx_set_mpeg_mode(struct lgs8gxx_state *priv, | |||
378 | u8 serial, u8 clk_pol, u8 clk_gated) | 569 | u8 serial, u8 clk_pol, u8 clk_gated) |
379 | { | 570 | { |
380 | int ret = 0; | 571 | int ret = 0; |
381 | u8 t; | 572 | u8 t, reg_addr; |
382 | 573 | ||
383 | ret = lgs8gxx_read_reg(priv, 0xC2, &t); | 574 | reg_addr = (priv->config->prod == LGS8GXX_PROD_LGS8G75) ? 0x30 : 0xC2; |
575 | ret = lgs8gxx_read_reg(priv, reg_addr, &t); | ||
384 | if (ret != 0) | 576 | if (ret != 0) |
385 | return ret; | 577 | return ret; |
386 | 578 | ||
@@ -389,13 +581,29 @@ static int lgs8gxx_set_mpeg_mode(struct lgs8gxx_state *priv, | |||
389 | t |= clk_pol ? TS_CLK_INVERTED : TS_CLK_NORMAL; | 581 | t |= clk_pol ? TS_CLK_INVERTED : TS_CLK_NORMAL; |
390 | t |= clk_gated ? TS_CLK_GATED : TS_CLK_FREERUN; | 582 | t |= clk_gated ? TS_CLK_GATED : TS_CLK_FREERUN; |
391 | 583 | ||
392 | ret = lgs8gxx_write_reg(priv, 0xC2, t); | 584 | ret = lgs8gxx_write_reg(priv, reg_addr, t); |
393 | if (ret != 0) | 585 | if (ret != 0) |
394 | return ret; | 586 | return ret; |
395 | 587 | ||
396 | return 0; | 588 | return 0; |
397 | } | 589 | } |
398 | 590 | ||
591 | /* A/D input peak-to-peak voltage range */ | ||
592 | static int lgs8g75_set_adc_vpp(struct lgs8gxx_state *priv, | ||
593 | u8 sel) | ||
594 | { | ||
595 | u8 r26 = 0x73, r27 = 0x90; | ||
596 | |||
597 | if (priv->config->prod != LGS8GXX_PROD_LGS8G75) | ||
598 | return 0; | ||
599 | |||
600 | r26 |= (sel & 0x01) << 7; | ||
601 | r27 |= (sel & 0x02) >> 1; | ||
602 | lgs8gxx_write_reg(priv, 0x26, r26); | ||
603 | lgs8gxx_write_reg(priv, 0x27, r27); | ||
604 | |||
605 | return 0; | ||
606 | } | ||
399 | 607 | ||
400 | /* LGS8913 demod frontend functions */ | 608 | /* LGS8913 demod frontend functions */ |
401 | 609 | ||
@@ -417,6 +625,34 @@ static int lgs8913_init(struct lgs8gxx_state *priv) | |||
417 | return 0; | 625 | return 0; |
418 | } | 626 | } |
419 | 627 | ||
628 | static int lgs8g75_init_data(struct lgs8gxx_state *priv) | ||
629 | { | ||
630 | const u8 *p = lgs8g75_initdat; | ||
631 | int i; | ||
632 | |||
633 | lgs8gxx_write_reg(priv, 0xC6, 0x40); | ||
634 | |||
635 | lgs8gxx_write_reg(priv, 0x3D, 0x04); | ||
636 | lgs8gxx_write_reg(priv, 0x39, 0x00); | ||
637 | |||
638 | lgs8gxx_write_reg(priv, 0x3A, 0x00); | ||
639 | lgs8gxx_write_reg(priv, 0x38, 0x00); | ||
640 | lgs8gxx_write_reg(priv, 0x3B, 0x00); | ||
641 | lgs8gxx_write_reg(priv, 0x38, 0x00); | ||
642 | |||
643 | for (i = 0; i < sizeof(lgs8g75_initdat); i++) { | ||
644 | lgs8gxx_write_reg(priv, 0x38, 0x00); | ||
645 | lgs8gxx_write_reg(priv, 0x3A, (u8)(i&0xff)); | ||
646 | lgs8gxx_write_reg(priv, 0x3B, (u8)(i>>8)); | ||
647 | lgs8gxx_write_reg(priv, 0x3C, *p); | ||
648 | p++; | ||
649 | } | ||
650 | |||
651 | lgs8gxx_write_reg(priv, 0x38, 0x00); | ||
652 | |||
653 | return 0; | ||
654 | } | ||
655 | |||
420 | static int lgs8gxx_init(struct dvb_frontend *fe) | 656 | static int lgs8gxx_init(struct dvb_frontend *fe) |
421 | { | 657 | { |
422 | struct lgs8gxx_state *priv = | 658 | struct lgs8gxx_state *priv = |
@@ -429,6 +665,9 @@ static int lgs8gxx_init(struct dvb_frontend *fe) | |||
429 | lgs8gxx_read_reg(priv, 0, &data); | 665 | lgs8gxx_read_reg(priv, 0, &data); |
430 | dprintk("reg 0 = 0x%02X\n", data); | 666 | dprintk("reg 0 = 0x%02X\n", data); |
431 | 667 | ||
668 | if (config->prod == LGS8GXX_PROD_LGS8G75) | ||
669 | lgs8g75_set_adc_vpp(priv, config->adc_vpp); | ||
670 | |||
432 | /* Setup MPEG output format */ | 671 | /* Setup MPEG output format */ |
433 | err = lgs8gxx_set_mpeg_mode(priv, config->serial_ts, | 672 | err = lgs8gxx_set_mpeg_mode(priv, config->serial_ts, |
434 | config->ts_clk_pol, | 673 | config->ts_clk_pol, |
@@ -439,8 +678,7 @@ static int lgs8gxx_init(struct dvb_frontend *fe) | |||
439 | if (config->prod == LGS8GXX_PROD_LGS8913) | 678 | if (config->prod == LGS8GXX_PROD_LGS8913) |
440 | lgs8913_init(priv); | 679 | lgs8913_init(priv); |
441 | lgs8gxx_set_if_freq(priv, priv->config->if_freq); | 680 | lgs8gxx_set_if_freq(priv, priv->config->if_freq); |
442 | if (config->prod != LGS8GXX_PROD_LGS8913) | 681 | lgs8gxx_set_ad_mode(priv); |
443 | lgs8gxx_set_ad_mode(priv); | ||
444 | 682 | ||
445 | return 0; | 683 | return 0; |
446 | } | 684 | } |
@@ -489,9 +727,6 @@ static int lgs8gxx_set_fe(struct dvb_frontend *fe, | |||
489 | static int lgs8gxx_get_fe(struct dvb_frontend *fe, | 727 | static int lgs8gxx_get_fe(struct dvb_frontend *fe, |
490 | struct dvb_frontend_parameters *fe_params) | 728 | struct dvb_frontend_parameters *fe_params) |
491 | { | 729 | { |
492 | struct lgs8gxx_state *priv = fe->demodulator_priv; | ||
493 | u8 t; | ||
494 | |||
495 | dprintk("%s\n", __func__); | 730 | dprintk("%s\n", __func__); |
496 | 731 | ||
497 | /* TODO: get real readings from device */ | 732 | /* TODO: get real readings from device */ |
@@ -501,29 +736,10 @@ static int lgs8gxx_get_fe(struct dvb_frontend *fe, | |||
501 | /* bandwidth */ | 736 | /* bandwidth */ |
502 | fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; | 737 | fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; |
503 | 738 | ||
504 | |||
505 | lgs8gxx_read_reg(priv, 0x7D, &t); | ||
506 | fe_params->u.ofdm.code_rate_HP = FEC_AUTO; | 739 | fe_params->u.ofdm.code_rate_HP = FEC_AUTO; |
507 | fe_params->u.ofdm.code_rate_LP = FEC_AUTO; | 740 | fe_params->u.ofdm.code_rate_LP = FEC_AUTO; |
508 | 741 | ||
509 | /* constellation */ | 742 | fe_params->u.ofdm.constellation = QAM_AUTO; |
510 | switch (t & SC_MASK) { | ||
511 | case SC_QAM64: | ||
512 | fe_params->u.ofdm.constellation = QAM_64; | ||
513 | break; | ||
514 | case SC_QAM32: | ||
515 | fe_params->u.ofdm.constellation = QAM_32; | ||
516 | break; | ||
517 | case SC_QAM16: | ||
518 | fe_params->u.ofdm.constellation = QAM_16; | ||
519 | break; | ||
520 | case SC_QAM4: | ||
521 | case SC_QAM4NR: | ||
522 | fe_params->u.ofdm.constellation = QPSK; | ||
523 | break; | ||
524 | default: | ||
525 | fe_params->u.ofdm.constellation = QAM_64; | ||
526 | } | ||
527 | 743 | ||
528 | /* transmission mode */ | 744 | /* transmission mode */ |
529 | fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; | 745 | fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; |
@@ -552,9 +768,19 @@ static int lgs8gxx_read_status(struct dvb_frontend *fe, fe_status_t *fe_status) | |||
552 | { | 768 | { |
553 | struct lgs8gxx_state *priv = fe->demodulator_priv; | 769 | struct lgs8gxx_state *priv = fe->demodulator_priv; |
554 | s8 ret; | 770 | s8 ret; |
555 | u8 t; | 771 | u8 t, locked = 0; |
556 | 772 | ||
557 | dprintk("%s\n", __func__); | 773 | dprintk("%s\n", __func__); |
774 | *fe_status = 0; | ||
775 | |||
776 | lgs8gxx_get_afc_phase(priv); | ||
777 | lgs8gxx_is_locked(priv, &locked); | ||
778 | if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { | ||
779 | if (locked) | ||
780 | *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | | ||
781 | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; | ||
782 | return 0; | ||
783 | } | ||
558 | 784 | ||
559 | ret = lgs8gxx_read_reg(priv, 0x4B, &t); | 785 | ret = lgs8gxx_read_reg(priv, 0x4B, &t); |
560 | if (ret != 0) | 786 | if (ret != 0) |
@@ -658,12 +884,33 @@ static int lgs8913_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal) | |||
658 | return 0; | 884 | return 0; |
659 | } | 885 | } |
660 | 886 | ||
887 | static int lgs8g75_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal) | ||
888 | { | ||
889 | u8 t; | ||
890 | s16 v = 0; | ||
891 | |||
892 | dprintk("%s\n", __func__); | ||
893 | |||
894 | lgs8gxx_read_reg(priv, 0xB1, &t); | ||
895 | v |= t; | ||
896 | v <<= 8; | ||
897 | lgs8gxx_read_reg(priv, 0xB0, &t); | ||
898 | v |= t; | ||
899 | |||
900 | *signal = v; | ||
901 | dprintk("%s: signal=0x%02X\n", __func__, *signal); | ||
902 | |||
903 | return 0; | ||
904 | } | ||
905 | |||
661 | static int lgs8gxx_read_signal_strength(struct dvb_frontend *fe, u16 *signal) | 906 | static int lgs8gxx_read_signal_strength(struct dvb_frontend *fe, u16 *signal) |
662 | { | 907 | { |
663 | struct lgs8gxx_state *priv = fe->demodulator_priv; | 908 | struct lgs8gxx_state *priv = fe->demodulator_priv; |
664 | 909 | ||
665 | if (priv->config->prod == LGS8GXX_PROD_LGS8913) | 910 | if (priv->config->prod == LGS8GXX_PROD_LGS8913) |
666 | return lgs8913_read_signal_strength(priv, signal); | 911 | return lgs8913_read_signal_strength(priv, signal); |
912 | else if (priv->config->prod == LGS8GXX_PROD_LGS8G75) | ||
913 | return lgs8g75_read_signal_strength(priv, signal); | ||
667 | else | 914 | else |
668 | return lgs8gxx_read_signal_agc(priv, signal); | 915 | return lgs8gxx_read_signal_agc(priv, signal); |
669 | } | 916 | } |
@@ -674,7 +921,10 @@ static int lgs8gxx_read_snr(struct dvb_frontend *fe, u16 *snr) | |||
674 | u8 t; | 921 | u8 t; |
675 | *snr = 0; | 922 | *snr = 0; |
676 | 923 | ||
677 | lgs8gxx_read_reg(priv, 0x95, &t); | 924 | if (priv->config->prod == LGS8GXX_PROD_LGS8G75) |
925 | lgs8gxx_read_reg(priv, 0x34, &t); | ||
926 | else | ||
927 | lgs8gxx_read_reg(priv, 0x95, &t); | ||
678 | dprintk("AVG Noise=0x%02X\n", t); | 928 | dprintk("AVG Noise=0x%02X\n", t); |
679 | *snr = 256 - t; | 929 | *snr = 256 - t; |
680 | *snr <<= 8; | 930 | *snr <<= 8; |
@@ -690,31 +940,68 @@ static int lgs8gxx_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | |||
690 | return 0; | 940 | return 0; |
691 | } | 941 | } |
692 | 942 | ||
943 | static void packet_counter_start(struct lgs8gxx_state *priv) | ||
944 | { | ||
945 | u8 orig, t; | ||
946 | |||
947 | if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { | ||
948 | lgs8gxx_read_reg(priv, 0x30, &orig); | ||
949 | orig &= 0xE7; | ||
950 | t = orig | 0x10; | ||
951 | lgs8gxx_write_reg(priv, 0x30, t); | ||
952 | t = orig | 0x18; | ||
953 | lgs8gxx_write_reg(priv, 0x30, t); | ||
954 | t = orig | 0x10; | ||
955 | lgs8gxx_write_reg(priv, 0x30, t); | ||
956 | } else { | ||
957 | lgs8gxx_write_reg(priv, 0xC6, 0x01); | ||
958 | lgs8gxx_write_reg(priv, 0xC6, 0x41); | ||
959 | lgs8gxx_write_reg(priv, 0xC6, 0x01); | ||
960 | } | ||
961 | } | ||
962 | |||
963 | static void packet_counter_stop(struct lgs8gxx_state *priv) | ||
964 | { | ||
965 | u8 t; | ||
966 | |||
967 | if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { | ||
968 | lgs8gxx_read_reg(priv, 0x30, &t); | ||
969 | t &= 0xE7; | ||
970 | lgs8gxx_write_reg(priv, 0x30, t); | ||
971 | } else { | ||
972 | lgs8gxx_write_reg(priv, 0xC6, 0x81); | ||
973 | } | ||
974 | } | ||
975 | |||
693 | static int lgs8gxx_read_ber(struct dvb_frontend *fe, u32 *ber) | 976 | static int lgs8gxx_read_ber(struct dvb_frontend *fe, u32 *ber) |
694 | { | 977 | { |
695 | struct lgs8gxx_state *priv = fe->demodulator_priv; | 978 | struct lgs8gxx_state *priv = fe->demodulator_priv; |
696 | u8 r0, r1, r2, r3; | 979 | u8 reg_err, reg_total, t; |
697 | u32 total_cnt, err_cnt; | 980 | u32 total_cnt = 0, err_cnt = 0; |
981 | int i; | ||
698 | 982 | ||
699 | dprintk("%s\n", __func__); | 983 | dprintk("%s\n", __func__); |
700 | 984 | ||
701 | lgs8gxx_write_reg(priv, 0xc6, 0x01); | 985 | packet_counter_start(priv); |
702 | lgs8gxx_write_reg(priv, 0xc6, 0x41); | ||
703 | lgs8gxx_write_reg(priv, 0xc6, 0x01); | ||
704 | |||
705 | msleep(200); | 986 | msleep(200); |
987 | packet_counter_stop(priv); | ||
988 | |||
989 | if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { | ||
990 | reg_total = 0x28; reg_err = 0x2C; | ||
991 | } else { | ||
992 | reg_total = 0xD0; reg_err = 0xD4; | ||
993 | } | ||
706 | 994 | ||
707 | lgs8gxx_write_reg(priv, 0xc6, 0x81); | 995 | for (i = 0; i < 4; i++) { |
708 | lgs8gxx_read_reg(priv, 0xd0, &r0); | 996 | total_cnt <<= 8; |
709 | lgs8gxx_read_reg(priv, 0xd1, &r1); | 997 | lgs8gxx_read_reg(priv, reg_total+3-i, &t); |
710 | lgs8gxx_read_reg(priv, 0xd2, &r2); | 998 | total_cnt |= t; |
711 | lgs8gxx_read_reg(priv, 0xd3, &r3); | 999 | } |
712 | total_cnt = (r3 << 24) | (r2 << 16) | (r1 << 8) | (r0); | 1000 | for (i = 0; i < 4; i++) { |
713 | lgs8gxx_read_reg(priv, 0xd4, &r0); | 1001 | err_cnt <<= 8; |
714 | lgs8gxx_read_reg(priv, 0xd5, &r1); | 1002 | lgs8gxx_read_reg(priv, reg_err+3-i, &t); |
715 | lgs8gxx_read_reg(priv, 0xd6, &r2); | 1003 | err_cnt |= t; |
716 | lgs8gxx_read_reg(priv, 0xd7, &r3); | 1004 | } |
717 | err_cnt = (r3 << 24) | (r2 << 16) | (r1 << 8) | (r0); | ||
718 | dprintk("error=%d total=%d\n", err_cnt, total_cnt); | 1005 | dprintk("error=%d total=%d\n", err_cnt, total_cnt); |
719 | 1006 | ||
720 | if (total_cnt == 0) | 1007 | if (total_cnt == 0) |
@@ -801,6 +1088,9 @@ struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config, | |||
801 | sizeof(struct dvb_frontend_ops)); | 1088 | sizeof(struct dvb_frontend_ops)); |
802 | priv->frontend.demodulator_priv = priv; | 1089 | priv->frontend.demodulator_priv = priv; |
803 | 1090 | ||
1091 | if (config->prod == LGS8GXX_PROD_LGS8G75) | ||
1092 | lgs8g75_init_data(priv); | ||
1093 | |||
804 | return &priv->frontend; | 1094 | return &priv->frontend; |
805 | 1095 | ||
806 | error_out: | 1096 | error_out: |
diff --git a/drivers/media/dvb/frontends/lgs8gxx.h b/drivers/media/dvb/frontends/lgs8gxx.h index 321d366a8307..33c3c5e162fa 100644 --- a/drivers/media/dvb/frontends/lgs8gxx.h +++ b/drivers/media/dvb/frontends/lgs8gxx.h | |||
@@ -1,9 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * Support for Legend Silicon DMB-TH demodulator | 2 | * Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator |
3 | * LGS8913, LGS8GL5 | 3 | * LGS8913, LGS8GL5, LGS8G75 |
4 | * experimental support LGS8G42, LGS8G52 | 4 | * experimental support LGS8G42, LGS8G52 |
5 | * | 5 | * |
6 | * Copyright (C) 2007,2008 David T.L. Wong <davidtlwong@gmail.com> | 6 | * Copyright (C) 2007-2009 David T.L. Wong <davidtlwong@gmail.com> |
7 | * Copyright (C) 2008 Sirius International (Hong Kong) Limited | 7 | * Copyright (C) 2008 Sirius International (Hong Kong) Limited |
8 | * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5) | 8 | * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5) |
9 | * | 9 | * |
@@ -34,6 +34,7 @@ | |||
34 | #define LGS8GXX_PROD_LGS8G42 3 | 34 | #define LGS8GXX_PROD_LGS8G42 3 |
35 | #define LGS8GXX_PROD_LGS8G52 4 | 35 | #define LGS8GXX_PROD_LGS8G52 4 |
36 | #define LGS8GXX_PROD_LGS8G54 5 | 36 | #define LGS8GXX_PROD_LGS8G54 5 |
37 | #define LGS8GXX_PROD_LGS8G75 6 | ||
37 | 38 | ||
38 | struct lgs8gxx_config { | 39 | struct lgs8gxx_config { |
39 | 40 | ||
@@ -70,6 +71,10 @@ struct lgs8gxx_config { | |||
70 | /*IF use Negative center frequency*/ | 71 | /*IF use Negative center frequency*/ |
71 | u8 if_neg_center; | 72 | u8 if_neg_center; |
72 | 73 | ||
74 | /*8G75 internal ADC input range selection*/ | ||
75 | /*0: 0.8Vpp, 1: 1.0Vpp, 2: 1.6Vpp, 3: 2.0Vpp*/ | ||
76 | u8 adc_vpp; | ||
77 | |||
73 | /* slave address and configuration of the tuner */ | 78 | /* slave address and configuration of the tuner */ |
74 | u8 tuner_address; | 79 | u8 tuner_address; |
75 | }; | 80 | }; |
diff --git a/drivers/media/dvb/frontends/lgs8gxx_priv.h b/drivers/media/dvb/frontends/lgs8gxx_priv.h index 9776d30686dc..8ef376f1414d 100644 --- a/drivers/media/dvb/frontends/lgs8gxx_priv.h +++ b/drivers/media/dvb/frontends/lgs8gxx_priv.h | |||
@@ -1,9 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * Support for Legend Silicon DMB-TH demodulator | 2 | * Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator |
3 | * LGS8913, LGS8GL5 | 3 | * LGS8913, LGS8GL5, LGS8G75 |
4 | * experimental support LGS8G42, LGS8G52 | 4 | * experimental support LGS8G42, LGS8G52 |
5 | * | 5 | * |
6 | * Copyright (C) 2007,2008 David T.L. Wong <davidtlwong@gmail.com> | 6 | * Copyright (C) 2007-2009 David T.L. Wong <davidtlwong@gmail.com> |
7 | * Copyright (C) 2008 Sirius International (Hong Kong) Limited | 7 | * Copyright (C) 2008 Sirius International (Hong Kong) Limited |
8 | * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5) | 8 | * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5) |
9 | * | 9 | * |
@@ -38,7 +38,7 @@ struct lgs8gxx_state { | |||
38 | #define SC_QAM64 0x10 /* 64QAM modulation */ | 38 | #define SC_QAM64 0x10 /* 64QAM modulation */ |
39 | #define SC_QAM32 0x0C /* 32QAM modulation */ | 39 | #define SC_QAM32 0x0C /* 32QAM modulation */ |
40 | #define SC_QAM16 0x08 /* 16QAM modulation */ | 40 | #define SC_QAM16 0x08 /* 16QAM modulation */ |
41 | #define SC_QAM4NR 0x04 /* 4QAM modulation */ | 41 | #define SC_QAM4NR 0x04 /* 4QAM-NR modulation */ |
42 | #define SC_QAM4 0x00 /* 4QAM modulation */ | 42 | #define SC_QAM4 0x00 /* 4QAM modulation */ |
43 | 43 | ||
44 | #define LGS_FEC_MASK 0x03 /* FEC Rate Mask */ | 44 | #define LGS_FEC_MASK 0x03 /* FEC Rate Mask */ |
@@ -47,8 +47,8 @@ struct lgs8gxx_state { | |||
47 | #define LGS_FEC_0_8 0x02 /* FEC Rate 0.8 */ | 47 | #define LGS_FEC_0_8 0x02 /* FEC Rate 0.8 */ |
48 | 48 | ||
49 | #define TIM_MASK 0x20 /* Time Interleave Length Mask */ | 49 | #define TIM_MASK 0x20 /* Time Interleave Length Mask */ |
50 | #define TIM_LONG 0x00 /* Time Interleave Length = 720 */ | 50 | #define TIM_LONG 0x20 /* Time Interleave Length = 720 */ |
51 | #define TIM_MIDDLE 0x20 /* Time Interleave Length = 240 */ | 51 | #define TIM_MIDDLE 0x00 /* Time Interleave Length = 240 */ |
52 | 52 | ||
53 | #define CF_MASK 0x80 /* Control Frame Mask */ | 53 | #define CF_MASK 0x80 /* Control Frame Mask */ |
54 | #define CF_EN 0x80 /* Control Frame On */ | 54 | #define CF_EN 0x80 /* Control Frame On */ |