Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

David Wong and committed by
Mauro Carvalho Chehab
b80dc1c6 a0d64456

+400 -105
+386 -96
drivers/media/dvb/frontends/lgs8gxx.c
··· 1 1 /* 2 - * Support for Legend Silicon DMB-TH demodulator 3 - * LGS8913, LGS8GL5 2 + * Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator 3 + * LGS8913, LGS8GL5, LGS8G75 4 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 7 * Copyright (C) 2008 Sirius International (Hong Kong) Limited 8 8 * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5) 9 9 * ··· 46 46 MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913." 47 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 85 /* LGS8GXX internal helper functions */ 50 86 51 87 static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data) ··· 91 55 struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 }; 92 56 93 57 msg.addr = priv->config->demod_address; 94 - if (reg >= 0xC0) 58 + if (priv->config->prod != LGS8GXX_PROD_LGS8G75 && reg >= 0xC0) 95 59 msg.addr += 0x02; 96 60 97 61 if (debug >= 2) ··· 120 84 }; 121 85 122 86 dev_addr = priv->config->demod_address; 123 - if (reg >= 0xC0) 87 + if (priv->config->prod != LGS8GXX_PROD_LGS8G75 && reg >= 0xC0) 124 88 dev_addr += 0x02; 125 89 msg[1].addr = msg[0].addr = dev_addr; 126 90 ··· 148 112 return 0; 149 113 } 150 114 115 + static int wait_reg_mask(struct lgs8gxx_state *priv, u8 reg, u8 mask, 116 + u8 val, u8 delay, u8 tries) 117 + { 118 + u8 t; 119 + int i; 120 + 121 + for (i = 0; i < tries; i++) { 122 + lgs8gxx_read_reg(priv, reg, &t); 123 + 124 + if ((t & mask) == val) 125 + return 0; 126 + msleep(delay); 127 + } 128 + 129 + return 1; 130 + } 131 + 151 132 static int lgs8gxx_set_ad_mode(struct lgs8gxx_state *priv) 152 133 { 153 134 const struct lgs8gxx_config *config = priv->config; 154 135 u8 if_conf; 155 136 156 - if_conf = 0x10; /* AGC output on; */ 137 + if_conf = 0x10; /* AGC output on, RF_AGC output off; */ 157 138 158 139 if_conf |= 159 140 ((config->ext_adc) ? 0x80 : 0x00) | 160 141 ((config->if_neg_center) ? 0x04 : 0x00) | 161 142 ((config->if_freq == 0) ? 0x08 : 0x00) | /* Baseband */ 162 - ((config->ext_adc && config->adc_signed) ? 0x02 : 0x00) | 163 - ((config->ext_adc && config->if_neg_edge) ? 0x01 : 0x00); 143 + ((config->adc_signed) ? 0x02 : 0x00) | 144 + ((config->if_neg_edge) ? 0x01 : 0x00); 164 145 165 146 if (config->ext_adc && 166 147 (config->prod == LGS8GXX_PROD_LGS8G52)) { ··· 210 157 } 211 158 dprintk("AFC_INIT_FREQ = 0x%08X\n", v32); 212 159 213 - lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32)); 214 - lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 8)); 215 - lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 16)); 216 - lgs8gxx_write_reg(priv, 0x0C, 0xFF & (v32 >> 24)); 160 + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 161 + lgs8gxx_write_reg(priv, 0x08, 0xFF & (v32)); 162 + lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32 >> 8)); 163 + lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 16)); 164 + lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 24)); 165 + } else { 166 + lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32)); 167 + lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 8)); 168 + lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 16)); 169 + lgs8gxx_write_reg(priv, 0x0C, 0xFF & (v32 >> 24)); 170 + } 217 171 172 + return 0; 173 + } 174 + 175 + static int lgs8gxx_get_afc_phase(struct lgs8gxx_state *priv) 176 + { 177 + u64 val; 178 + u32 v32 = 0; 179 + u8 reg_addr, t; 180 + int i; 181 + 182 + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) 183 + reg_addr = 0x23; 184 + else 185 + reg_addr = 0x48; 186 + 187 + for (i = 0; i < 4; i++) { 188 + lgs8gxx_read_reg(priv, reg_addr, &t); 189 + v32 <<= 8; 190 + v32 |= t; 191 + reg_addr--; 192 + } 193 + 194 + val = v32; 195 + val *= priv->config->if_clk_freq; 196 + val /= (u64)1 << 32; 197 + dprintk("AFC = %u kHz\n", (u32)val); 218 198 return 0; 219 199 } 220 200 221 201 static int lgs8gxx_set_mode_auto(struct lgs8gxx_state *priv) 222 202 { 223 203 u8 t; 204 + u8 prod = priv->config->prod; 224 205 225 - if (priv->config->prod == LGS8GXX_PROD_LGS8913) 206 + if (prod == LGS8GXX_PROD_LGS8913) 226 207 lgs8gxx_write_reg(priv, 0xC6, 0x01); 227 208 228 - lgs8gxx_read_reg(priv, 0x7E, &t); 229 - lgs8gxx_write_reg(priv, 0x7E, t | 0x01); 209 + if (prod == LGS8GXX_PROD_LGS8G75) { 210 + lgs8gxx_read_reg(priv, 0x0C, &t); 211 + t &= (~0x04); 212 + lgs8gxx_write_reg(priv, 0x0C, t | 0x80); 213 + lgs8gxx_write_reg(priv, 0x39, 0x00); 214 + lgs8gxx_write_reg(priv, 0x3D, 0x04); 215 + } else if (prod == LGS8GXX_PROD_LGS8913 || 216 + prod == LGS8GXX_PROD_LGS8GL5 || 217 + prod == LGS8GXX_PROD_LGS8G42 || 218 + prod == LGS8GXX_PROD_LGS8G52 || 219 + prod == LGS8GXX_PROD_LGS8G54) { 220 + lgs8gxx_read_reg(priv, 0x7E, &t); 221 + lgs8gxx_write_reg(priv, 0x7E, t | 0x01); 230 222 231 - /* clear FEC self reset */ 232 - lgs8gxx_read_reg(priv, 0xC5, &t); 233 - lgs8gxx_write_reg(priv, 0xC5, t & 0xE0); 223 + /* clear FEC self reset */ 224 + lgs8gxx_read_reg(priv, 0xC5, &t); 225 + lgs8gxx_write_reg(priv, 0xC5, t & 0xE0); 226 + } 234 227 235 - if (priv->config->prod == LGS8GXX_PROD_LGS8913) { 228 + if (prod == LGS8GXX_PROD_LGS8913) { 236 229 /* FEC auto detect */ 237 230 lgs8gxx_write_reg(priv, 0xC1, 0x03); 238 231 239 232 lgs8gxx_read_reg(priv, 0x7C, &t); 240 233 t = (t & 0x8C) | 0x03; 241 234 lgs8gxx_write_reg(priv, 0x7C, t); 242 - } 243 235 244 - 245 - if (priv->config->prod == LGS8GXX_PROD_LGS8913) { 246 236 /* BER test mode */ 247 237 lgs8gxx_read_reg(priv, 0xC3, &t); 248 238 t = (t & 0xEF) | 0x10; ··· 302 206 { 303 207 int ret = 0; 304 208 u8 t; 209 + 210 + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 211 + u8 t2; 212 + lgs8gxx_read_reg(priv, 0x0C, &t); 213 + t &= (~0x80); 214 + lgs8gxx_write_reg(priv, 0x0C, t); 215 + 216 + lgs8gxx_read_reg(priv, 0x0C, &t); 217 + lgs8gxx_read_reg(priv, 0x19, &t2); 218 + 219 + if (((t&0x03) == 0x01) && (t2&0x01)) { 220 + lgs8gxx_write_reg(priv, 0x6E, 0x05); 221 + lgs8gxx_write_reg(priv, 0x39, 0x02); 222 + lgs8gxx_write_reg(priv, 0x39, 0x03); 223 + lgs8gxx_write_reg(priv, 0x3D, 0x05); 224 + lgs8gxx_write_reg(priv, 0x3E, 0x28); 225 + lgs8gxx_write_reg(priv, 0x53, 0x80); 226 + } else { 227 + lgs8gxx_write_reg(priv, 0x6E, 0x3F); 228 + lgs8gxx_write_reg(priv, 0x39, 0x00); 229 + lgs8gxx_write_reg(priv, 0x3D, 0x04); 230 + } 231 + 232 + lgs8gxx_soft_reset(priv); 233 + return 0; 234 + } 305 235 306 236 /* turn off auto-detect; manual settings */ 307 237 lgs8gxx_write_reg(priv, 0x7E, 0); ··· 348 226 int ret = 0; 349 227 u8 t; 350 228 351 - ret = lgs8gxx_read_reg(priv, 0x4B, &t); 229 + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) 230 + ret = lgs8gxx_read_reg(priv, 0x13, &t); 231 + else 232 + ret = lgs8gxx_read_reg(priv, 0x4B, &t); 352 233 if (ret != 0) 353 234 return ret; 354 235 355 - *locked = ((t & 0xC0) == 0xC0) ? 1 : 0; 236 + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) 237 + *locked = ((t & 0x80) == 0x80) ? 1 : 0; 238 + else 239 + *locked = ((t & 0xC0) == 0xC0) ? 1 : 0; 240 + return 0; 241 + } 242 + 243 + /* Wait for Code Acquisition Lock */ 244 + static int lgs8gxx_wait_ca_lock(struct lgs8gxx_state *priv, u8 *locked) 245 + { 246 + int ret = 0; 247 + u8 reg, mask, val; 248 + 249 + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 250 + reg = 0x13; 251 + mask = 0x80; 252 + val = 0x80; 253 + } else { 254 + reg = 0x4B; 255 + mask = 0xC0; 256 + val = 0xC0; 257 + } 258 + 259 + ret = wait_reg_mask(priv, reg, mask, val, 50, 40); 260 + *locked = (ret == 0) ? 1 : 0; 261 + 356 262 return 0; 357 263 } 358 264 ··· 388 238 u8 *finished) 389 239 { 390 240 int ret = 0; 391 - u8 t; 241 + u8 reg, mask, val; 392 242 393 - ret = lgs8gxx_read_reg(priv, 0xA4, &t); 394 - if (ret != 0) 395 - return ret; 243 + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 244 + reg = 0x1f; 245 + mask = 0xC0; 246 + val = 0x80; 247 + } else { 248 + reg = 0xA4; 249 + mask = 0x03; 250 + val = 0x01; 251 + } 396 252 397 - *finished = ((t & 0x3) == 0x1) ? 1 : 0; 253 + ret = wait_reg_mask(priv, reg, mask, val, 10, 20); 254 + *finished = (ret == 0) ? 1 : 0; 398 255 399 256 return 0; 400 257 } 401 258 402 - static int lgs8gxx_autolock_gi(struct lgs8gxx_state *priv, u8 gi, u8 *locked) 259 + static int lgs8gxx_autolock_gi(struct lgs8gxx_state *priv, u8 gi, u8 cpn, 260 + u8 *locked) 403 261 { 404 - int err; 262 + int err = 0; 405 263 u8 ad_fini = 0; 264 + u8 t1, t2; 406 265 407 266 if (gi == GI_945) 408 267 dprintk("try GI 945\n"); ··· 419 260 dprintk("try GI 595\n"); 420 261 else if (gi == GI_420) 421 262 dprintk("try GI 420\n"); 422 - lgs8gxx_write_reg(priv, 0x04, gi); 263 + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 264 + lgs8gxx_read_reg(priv, 0x0C, &t1); 265 + lgs8gxx_read_reg(priv, 0x18, &t2); 266 + t1 &= ~(GI_MASK); 267 + t1 |= gi; 268 + t2 &= 0xFE; 269 + t2 |= cpn ? 0x01 : 0x00; 270 + lgs8gxx_write_reg(priv, 0x0C, t1); 271 + lgs8gxx_write_reg(priv, 0x18, t2); 272 + } else { 273 + lgs8gxx_write_reg(priv, 0x04, gi); 274 + } 423 275 lgs8gxx_soft_reset(priv); 424 - msleep(50); 276 + err = lgs8gxx_wait_ca_lock(priv, locked); 277 + if (err || !(*locked)) 278 + return err; 425 279 err = lgs8gxx_is_autodetect_finished(priv, &ad_fini); 426 280 if (err != 0) 427 281 return err; 428 282 if (ad_fini) { 429 - err = lgs8gxx_is_locked(priv, locked); 430 - if (err != 0) 431 - return err; 432 - } 283 + dprintk("auto detect finished\n"); 284 + } else 285 + *locked = 0; 433 286 434 287 return 0; 435 288 } ··· 456 285 dprintk("%s\n", __func__); 457 286 458 287 lgs8gxx_set_mode_auto(priv); 459 - /* Guard Interval */ 460 - lgs8gxx_write_reg(priv, 0x03, 00); 288 + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 289 + lgs8gxx_write_reg(priv, 0x67, 0xAA); 290 + lgs8gxx_write_reg(priv, 0x6E, 0x3F); 291 + } else { 292 + /* Guard Interval */ 293 + lgs8gxx_write_reg(priv, 0x03, 00); 294 + } 461 295 462 296 for (i = 0; i < 2; i++) { 463 297 for (j = 0; j < 2; j++) { 464 298 tmp_gi = GI_945; 465 - err = lgs8gxx_autolock_gi(priv, GI_945, &locked); 299 + err = lgs8gxx_autolock_gi(priv, GI_945, j, &locked); 466 300 if (err) 467 301 goto out; 468 302 if (locked) ··· 475 299 } 476 300 for (j = 0; j < 2; j++) { 477 301 tmp_gi = GI_420; 478 - err = lgs8gxx_autolock_gi(priv, GI_420, &locked); 302 + err = lgs8gxx_autolock_gi(priv, GI_420, j, &locked); 479 303 if (err) 480 304 goto out; 481 305 if (locked) 482 306 goto locked; 483 307 } 484 308 tmp_gi = GI_595; 485 - err = lgs8gxx_autolock_gi(priv, GI_595, &locked); 309 + err = lgs8gxx_autolock_gi(priv, GI_595, 1, &locked); 486 310 if (err) 487 311 goto out; 488 312 if (locked) ··· 493 317 if ((err == 0) && (locked == 1)) { 494 318 u8 t; 495 319 496 - lgs8gxx_read_reg(priv, 0xA2, &t); 497 - *detected_param = t; 320 + if (priv->config->prod != LGS8GXX_PROD_LGS8G75) { 321 + lgs8gxx_read_reg(priv, 0xA2, &t); 322 + *detected_param = t; 323 + } else { 324 + lgs8gxx_read_reg(priv, 0x1F, &t); 325 + *detected_param = t & 0x3F; 326 + } 498 327 499 328 if (tmp_gi == GI_945) 500 329 dprintk("GI 945 locked\n"); ··· 526 345 527 346 if (err != 0) { 528 347 dprintk("lgs8gxx_auto_detect failed\n"); 529 - } 348 + } else 349 + dprintk("detected param = 0x%02X\n", detected_param); 530 350 531 351 /* Apply detected parameters */ 532 352 if (priv->config->prod == LGS8GXX_PROD_LGS8913) { 533 353 u8 inter_leave_len = detected_param & TIM_MASK ; 534 - inter_leave_len = (inter_leave_len == TIM_LONG) ? 0x60 : 0x40; 354 + /* Fix 8913 time interleaver detection bug */ 355 + inter_leave_len = (inter_leave_len == TIM_MIDDLE) ? 0x60 : 0x40; 535 356 detected_param &= CF_MASK | SC_MASK | LGS_FEC_MASK; 536 357 detected_param |= inter_leave_len; 537 358 } 538 - lgs8gxx_write_reg(priv, 0x7D, detected_param); 539 - if (priv->config->prod == LGS8GXX_PROD_LGS8913) 540 - lgs8gxx_write_reg(priv, 0xC0, detected_param); 359 + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 360 + u8 t; 361 + lgs8gxx_read_reg(priv, 0x19, &t); 362 + t &= 0x81; 363 + t |= detected_param << 1; 364 + lgs8gxx_write_reg(priv, 0x19, t); 365 + } else { 366 + lgs8gxx_write_reg(priv, 0x7D, detected_param); 367 + if (priv->config->prod == LGS8GXX_PROD_LGS8913) 368 + lgs8gxx_write_reg(priv, 0xC0, detected_param); 369 + } 541 370 /* lgs8gxx_soft_reset(priv); */ 542 371 543 372 /* Enter manual mode */ ··· 569 378 u8 serial, u8 clk_pol, u8 clk_gated) 570 379 { 571 380 int ret = 0; 572 - u8 t; 381 + u8 t, reg_addr; 573 382 574 - ret = lgs8gxx_read_reg(priv, 0xC2, &t); 383 + reg_addr = (priv->config->prod == LGS8GXX_PROD_LGS8G75) ? 0x30 : 0xC2; 384 + ret = lgs8gxx_read_reg(priv, reg_addr, &t); 575 385 if (ret != 0) 576 386 return ret; 577 387 ··· 581 389 t |= clk_pol ? TS_CLK_INVERTED : TS_CLK_NORMAL; 582 390 t |= clk_gated ? TS_CLK_GATED : TS_CLK_FREERUN; 583 391 584 - ret = lgs8gxx_write_reg(priv, 0xC2, t); 392 + ret = lgs8gxx_write_reg(priv, reg_addr, t); 585 393 if (ret != 0) 586 394 return ret; 587 395 588 396 return 0; 589 397 } 590 398 399 + /* A/D input peak-to-peak voltage range */ 400 + static int lgs8g75_set_adc_vpp(struct lgs8gxx_state *priv, 401 + u8 sel) 402 + { 403 + u8 r26 = 0x73, r27 = 0x90; 404 + 405 + if (priv->config->prod != LGS8GXX_PROD_LGS8G75) 406 + return 0; 407 + 408 + r26 |= (sel & 0x01) << 7; 409 + r27 |= (sel & 0x02) >> 1; 410 + lgs8gxx_write_reg(priv, 0x26, r26); 411 + lgs8gxx_write_reg(priv, 0x27, r27); 412 + 413 + return 0; 414 + } 591 415 592 416 /* LGS8913 demod frontend functions */ 593 417 ··· 625 417 return 0; 626 418 } 627 419 420 + static int lgs8g75_init_data(struct lgs8gxx_state *priv) 421 + { 422 + const u8 *p = lgs8g75_initdat; 423 + int i; 424 + 425 + lgs8gxx_write_reg(priv, 0xC6, 0x40); 426 + 427 + lgs8gxx_write_reg(priv, 0x3D, 0x04); 428 + lgs8gxx_write_reg(priv, 0x39, 0x00); 429 + 430 + lgs8gxx_write_reg(priv, 0x3A, 0x00); 431 + lgs8gxx_write_reg(priv, 0x38, 0x00); 432 + lgs8gxx_write_reg(priv, 0x3B, 0x00); 433 + lgs8gxx_write_reg(priv, 0x38, 0x00); 434 + 435 + for (i = 0; i < sizeof(lgs8g75_initdat); i++) { 436 + lgs8gxx_write_reg(priv, 0x38, 0x00); 437 + lgs8gxx_write_reg(priv, 0x3A, (u8)(i&0xff)); 438 + lgs8gxx_write_reg(priv, 0x3B, (u8)(i>>8)); 439 + lgs8gxx_write_reg(priv, 0x3C, *p); 440 + p++; 441 + } 442 + 443 + lgs8gxx_write_reg(priv, 0x38, 0x00); 444 + 445 + return 0; 446 + } 447 + 628 448 static int lgs8gxx_init(struct dvb_frontend *fe) 629 449 { 630 450 struct lgs8gxx_state *priv = ··· 665 429 lgs8gxx_read_reg(priv, 0, &data); 666 430 dprintk("reg 0 = 0x%02X\n", data); 667 431 432 + if (config->prod == LGS8GXX_PROD_LGS8G75) 433 + lgs8g75_set_adc_vpp(priv, config->adc_vpp); 434 + 668 435 /* Setup MPEG output format */ 669 436 err = lgs8gxx_set_mpeg_mode(priv, config->serial_ts, 670 437 config->ts_clk_pol, ··· 678 439 if (config->prod == LGS8GXX_PROD_LGS8913) 679 440 lgs8913_init(priv); 680 441 lgs8gxx_set_if_freq(priv, priv->config->if_freq); 681 - if (config->prod != LGS8GXX_PROD_LGS8913) 682 - lgs8gxx_set_ad_mode(priv); 442 + lgs8gxx_set_ad_mode(priv); 683 443 684 444 return 0; 685 445 } ··· 727 489 static int lgs8gxx_get_fe(struct dvb_frontend *fe, 728 490 struct dvb_frontend_parameters *fe_params) 729 491 { 730 - struct lgs8gxx_state *priv = fe->demodulator_priv; 731 - u8 t; 732 - 733 492 dprintk("%s\n", __func__); 734 493 735 494 /* TODO: get real readings from device */ ··· 736 501 /* bandwidth */ 737 502 fe_params->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; 738 503 739 - 740 - lgs8gxx_read_reg(priv, 0x7D, &t); 741 504 fe_params->u.ofdm.code_rate_HP = FEC_AUTO; 742 505 fe_params->u.ofdm.code_rate_LP = FEC_AUTO; 743 506 744 - /* constellation */ 745 - switch (t & SC_MASK) { 746 - case SC_QAM64: 747 - fe_params->u.ofdm.constellation = QAM_64; 748 - break; 749 - case SC_QAM32: 750 - fe_params->u.ofdm.constellation = QAM_32; 751 - break; 752 - case SC_QAM16: 753 - fe_params->u.ofdm.constellation = QAM_16; 754 - break; 755 - case SC_QAM4: 756 - case SC_QAM4NR: 757 - fe_params->u.ofdm.constellation = QPSK; 758 - break; 759 - default: 760 - fe_params->u.ofdm.constellation = QAM_64; 761 - } 507 + fe_params->u.ofdm.constellation = QAM_AUTO; 762 508 763 509 /* transmission mode */ 764 510 fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO; ··· 768 552 { 769 553 struct lgs8gxx_state *priv = fe->demodulator_priv; 770 554 s8 ret; 771 - u8 t; 555 + u8 t, locked = 0; 772 556 773 557 dprintk("%s\n", __func__); 558 + *fe_status = 0; 559 + 560 + lgs8gxx_get_afc_phase(priv); 561 + lgs8gxx_is_locked(priv, &locked); 562 + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 563 + if (locked) 564 + *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | 565 + FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; 566 + return 0; 567 + } 774 568 775 569 ret = lgs8gxx_read_reg(priv, 0x4B, &t); 776 570 if (ret != 0) ··· 884 658 return 0; 885 659 } 886 660 661 + static int lgs8g75_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal) 662 + { 663 + u8 t; 664 + s16 v = 0; 665 + 666 + dprintk("%s\n", __func__); 667 + 668 + lgs8gxx_read_reg(priv, 0xB1, &t); 669 + v |= t; 670 + v <<= 8; 671 + lgs8gxx_read_reg(priv, 0xB0, &t); 672 + v |= t; 673 + 674 + *signal = v; 675 + dprintk("%s: signal=0x%02X\n", __func__, *signal); 676 + 677 + return 0; 678 + } 679 + 887 680 static int lgs8gxx_read_signal_strength(struct dvb_frontend *fe, u16 *signal) 888 681 { 889 682 struct lgs8gxx_state *priv = fe->demodulator_priv; 890 683 891 684 if (priv->config->prod == LGS8GXX_PROD_LGS8913) 892 685 return lgs8913_read_signal_strength(priv, signal); 686 + else if (priv->config->prod == LGS8GXX_PROD_LGS8G75) 687 + return lgs8g75_read_signal_strength(priv, signal); 893 688 else 894 689 return lgs8gxx_read_signal_agc(priv, signal); 895 690 } ··· 921 674 u8 t; 922 675 *snr = 0; 923 676 924 - lgs8gxx_read_reg(priv, 0x95, &t); 677 + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) 678 + lgs8gxx_read_reg(priv, 0x34, &t); 679 + else 680 + lgs8gxx_read_reg(priv, 0x95, &t); 925 681 dprintk("AVG Noise=0x%02X\n", t); 926 682 *snr = 256 - t; 927 683 *snr <<= 8; ··· 940 690 return 0; 941 691 } 942 692 693 + static void packet_counter_start(struct lgs8gxx_state *priv) 694 + { 695 + u8 orig, t; 696 + 697 + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 698 + lgs8gxx_read_reg(priv, 0x30, &orig); 699 + orig &= 0xE7; 700 + t = orig | 0x10; 701 + lgs8gxx_write_reg(priv, 0x30, t); 702 + t = orig | 0x18; 703 + lgs8gxx_write_reg(priv, 0x30, t); 704 + t = orig | 0x10; 705 + lgs8gxx_write_reg(priv, 0x30, t); 706 + } else { 707 + lgs8gxx_write_reg(priv, 0xC6, 0x01); 708 + lgs8gxx_write_reg(priv, 0xC6, 0x41); 709 + lgs8gxx_write_reg(priv, 0xC6, 0x01); 710 + } 711 + } 712 + 713 + static void packet_counter_stop(struct lgs8gxx_state *priv) 714 + { 715 + u8 t; 716 + 717 + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 718 + lgs8gxx_read_reg(priv, 0x30, &t); 719 + t &= 0xE7; 720 + lgs8gxx_write_reg(priv, 0x30, t); 721 + } else { 722 + lgs8gxx_write_reg(priv, 0xC6, 0x81); 723 + } 724 + } 725 + 943 726 static int lgs8gxx_read_ber(struct dvb_frontend *fe, u32 *ber) 944 727 { 945 728 struct lgs8gxx_state *priv = fe->demodulator_priv; 946 - u8 r0, r1, r2, r3; 947 - u32 total_cnt, err_cnt; 729 + u8 reg_err, reg_total, t; 730 + u32 total_cnt = 0, err_cnt = 0; 731 + int i; 948 732 949 733 dprintk("%s\n", __func__); 950 734 951 - lgs8gxx_write_reg(priv, 0xc6, 0x01); 952 - lgs8gxx_write_reg(priv, 0xc6, 0x41); 953 - lgs8gxx_write_reg(priv, 0xc6, 0x01); 954 - 735 + packet_counter_start(priv); 955 736 msleep(200); 737 + packet_counter_stop(priv); 956 738 957 - lgs8gxx_write_reg(priv, 0xc6, 0x81); 958 - lgs8gxx_read_reg(priv, 0xd0, &r0); 959 - lgs8gxx_read_reg(priv, 0xd1, &r1); 960 - lgs8gxx_read_reg(priv, 0xd2, &r2); 961 - lgs8gxx_read_reg(priv, 0xd3, &r3); 962 - total_cnt = (r3 << 24) | (r2 << 16) | (r1 << 8) | (r0); 963 - lgs8gxx_read_reg(priv, 0xd4, &r0); 964 - lgs8gxx_read_reg(priv, 0xd5, &r1); 965 - lgs8gxx_read_reg(priv, 0xd6, &r2); 966 - lgs8gxx_read_reg(priv, 0xd7, &r3); 967 - err_cnt = (r3 << 24) | (r2 << 16) | (r1 << 8) | (r0); 739 + if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 740 + reg_total = 0x28; reg_err = 0x2C; 741 + } else { 742 + reg_total = 0xD0; reg_err = 0xD4; 743 + } 744 + 745 + for (i = 0; i < 4; i++) { 746 + total_cnt <<= 8; 747 + lgs8gxx_read_reg(priv, reg_total+3-i, &t); 748 + total_cnt |= t; 749 + } 750 + for (i = 0; i < 4; i++) { 751 + err_cnt <<= 8; 752 + lgs8gxx_read_reg(priv, reg_err+3-i, &t); 753 + err_cnt |= t; 754 + } 968 755 dprintk("error=%d total=%d\n", err_cnt, total_cnt); 969 756 970 757 if (total_cnt == 0) ··· 1087 800 memcpy(&priv->frontend.ops, &lgs8gxx_ops, 1088 801 sizeof(struct dvb_frontend_ops)); 1089 802 priv->frontend.demodulator_priv = priv; 803 + 804 + if (config->prod == LGS8GXX_PROD_LGS8G75) 805 + lgs8g75_init_data(priv); 1090 806 1091 807 return &priv->frontend; 1092 808
+8 -3
drivers/media/dvb/frontends/lgs8gxx.h
··· 1 1 /* 2 - * Support for Legend Silicon DMB-TH demodulator 3 - * LGS8913, LGS8GL5 2 + * Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator 3 + * LGS8913, LGS8GL5, LGS8G75 4 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 7 * Copyright (C) 2008 Sirius International (Hong Kong) Limited 8 8 * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5) 9 9 * ··· 34 34 #define LGS8GXX_PROD_LGS8G42 3 35 35 #define LGS8GXX_PROD_LGS8G52 4 36 36 #define LGS8GXX_PROD_LGS8G54 5 37 + #define LGS8GXX_PROD_LGS8G75 6 37 38 38 39 struct lgs8gxx_config { 39 40 ··· 70 69 71 70 /*IF use Negative center frequency*/ 72 71 u8 if_neg_center; 72 + 73 + /*8G75 internal ADC input range selection*/ 74 + /*0: 0.8Vpp, 1: 1.0Vpp, 2: 1.6Vpp, 3: 2.0Vpp*/ 75 + u8 adc_vpp; 73 76 74 77 /* slave address and configuration of the tuner */ 75 78 u8 tuner_address;
+6 -6
drivers/media/dvb/frontends/lgs8gxx_priv.h
··· 1 1 /* 2 - * Support for Legend Silicon DMB-TH demodulator 3 - * LGS8913, LGS8GL5 2 + * Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator 3 + * LGS8913, LGS8GL5, LGS8G75 4 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 7 * Copyright (C) 2008 Sirius International (Hong Kong) Limited 8 8 * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5) 9 9 * ··· 38 38 #define SC_QAM64 0x10 /* 64QAM modulation */ 39 39 #define SC_QAM32 0x0C /* 32QAM modulation */ 40 40 #define SC_QAM16 0x08 /* 16QAM modulation */ 41 - #define SC_QAM4NR 0x04 /* 4QAM modulation */ 41 + #define SC_QAM4NR 0x04 /* 4QAM-NR modulation */ 42 42 #define SC_QAM4 0x00 /* 4QAM modulation */ 43 43 44 44 #define LGS_FEC_MASK 0x03 /* FEC Rate Mask */ ··· 47 47 #define LGS_FEC_0_8 0x02 /* FEC Rate 0.8 */ 48 48 49 49 #define TIM_MASK 0x20 /* Time Interleave Length Mask */ 50 - #define TIM_LONG 0x00 /* Time Interleave Length = 720 */ 51 - #define TIM_MIDDLE 0x20 /* Time Interleave Length = 240 */ 50 + #define TIM_LONG 0x20 /* Time Interleave Length = 720 */ 51 + #define TIM_MIDDLE 0x00 /* Time Interleave Length = 240 */ 52 52 53 53 #define CF_MASK 0x80 /* Control Frame Mask */ 54 54 #define CF_EN 0x80 /* Control Frame On */