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

Configure Feed

Select the types of activity you want to include in your feed.

at v3.4-rc3 1073 lines 24 kB view raw
1/* 2 * Support for Legend Silicon GB20600 (a.k.a DMB-TH) demodulator 3 * LGS8913, LGS8GL5, LGS8G75 4 * experimental support LGS8G42, LGS8G52 5 * 6 * Copyright (C) 2007-2009 David T.L. Wong <davidtlwong@gmail.com> 7 * Copyright (C) 2008 Sirius International (Hong Kong) Limited 8 * Timothy Lee <timothy.lee@siriushk.com> (for initial work on LGS8GL5) 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 23 * 24 */ 25 26#include <asm/div64.h> 27#include <linux/firmware.h> 28 29#include "dvb_frontend.h" 30 31#include "lgs8gxx.h" 32#include "lgs8gxx_priv.h" 33 34#define dprintk(args...) \ 35 do { \ 36 if (debug) \ 37 printk(KERN_DEBUG "lgs8gxx: " args); \ 38 } while (0) 39 40static int debug; 41static int fake_signal_str = 1; 42 43module_param(debug, int, 0644); 44MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); 45 46module_param(fake_signal_str, int, 0644); 47MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913." 48"Signal strength calculation is slow.(default:on)."); 49 50/* LGS8GXX internal helper functions */ 51 52static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data) 53{ 54 int ret; 55 u8 buf[] = { reg, data }; 56 struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 }; 57 58 msg.addr = priv->config->demod_address; 59 if (priv->config->prod != LGS8GXX_PROD_LGS8G75 && reg >= 0xC0) 60 msg.addr += 0x02; 61 62 if (debug >= 2) 63 dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, data); 64 65 ret = i2c_transfer(priv->i2c, &msg, 1); 66 67 if (ret != 1) 68 dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n", 69 __func__, reg, data, ret); 70 71 return (ret != 1) ? -1 : 0; 72} 73 74static int lgs8gxx_read_reg(struct lgs8gxx_state *priv, u8 reg, u8 *p_data) 75{ 76 int ret; 77 u8 dev_addr; 78 79 u8 b0[] = { reg }; 80 u8 b1[] = { 0 }; 81 struct i2c_msg msg[] = { 82 { .flags = 0, .buf = b0, .len = 1 }, 83 { .flags = I2C_M_RD, .buf = b1, .len = 1 }, 84 }; 85 86 dev_addr = priv->config->demod_address; 87 if (priv->config->prod != LGS8GXX_PROD_LGS8G75 && reg >= 0xC0) 88 dev_addr += 0x02; 89 msg[1].addr = msg[0].addr = dev_addr; 90 91 ret = i2c_transfer(priv->i2c, msg, 2); 92 if (ret != 2) { 93 dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg, ret); 94 return -1; 95 } 96 97 *p_data = b1[0]; 98 if (debug >= 2) 99 dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, b1[0]); 100 return 0; 101} 102 103static int lgs8gxx_soft_reset(struct lgs8gxx_state *priv) 104{ 105 lgs8gxx_write_reg(priv, 0x02, 0x00); 106 msleep(1); 107 lgs8gxx_write_reg(priv, 0x02, 0x01); 108 msleep(100); 109 110 return 0; 111} 112 113static int wait_reg_mask(struct lgs8gxx_state *priv, u8 reg, u8 mask, 114 u8 val, u8 delay, u8 tries) 115{ 116 u8 t; 117 int i; 118 119 for (i = 0; i < tries; i++) { 120 lgs8gxx_read_reg(priv, reg, &t); 121 122 if ((t & mask) == val) 123 return 0; 124 msleep(delay); 125 } 126 127 return 1; 128} 129 130static int lgs8gxx_set_ad_mode(struct lgs8gxx_state *priv) 131{ 132 const struct lgs8gxx_config *config = priv->config; 133 u8 if_conf; 134 135 if_conf = 0x10; /* AGC output on, RF_AGC output off; */ 136 137 if_conf |= 138 ((config->ext_adc) ? 0x80 : 0x00) | 139 ((config->if_neg_center) ? 0x04 : 0x00) | 140 ((config->if_freq == 0) ? 0x08 : 0x00) | /* Baseband */ 141 ((config->adc_signed) ? 0x02 : 0x00) | 142 ((config->if_neg_edge) ? 0x01 : 0x00); 143 144 if (config->ext_adc && 145 (config->prod == LGS8GXX_PROD_LGS8G52)) { 146 lgs8gxx_write_reg(priv, 0xBA, 0x40); 147 } 148 149 lgs8gxx_write_reg(priv, 0x07, if_conf); 150 151 return 0; 152} 153 154static int lgs8gxx_set_if_freq(struct lgs8gxx_state *priv, u32 freq /*in kHz*/) 155{ 156 u64 val; 157 u32 v32; 158 u32 if_clk; 159 160 if_clk = priv->config->if_clk_freq; 161 162 val = freq; 163 if (freq != 0) { 164 val <<= 32; 165 if (if_clk != 0) 166 do_div(val, if_clk); 167 v32 = val & 0xFFFFFFFF; 168 dprintk("Set IF Freq to %dkHz\n", freq); 169 } else { 170 v32 = 0; 171 dprintk("Set IF Freq to baseband\n"); 172 } 173 dprintk("AFC_INIT_FREQ = 0x%08X\n", v32); 174 175 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 176 lgs8gxx_write_reg(priv, 0x08, 0xFF & (v32)); 177 lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32 >> 8)); 178 lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 16)); 179 lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 24)); 180 } else { 181 lgs8gxx_write_reg(priv, 0x09, 0xFF & (v32)); 182 lgs8gxx_write_reg(priv, 0x0A, 0xFF & (v32 >> 8)); 183 lgs8gxx_write_reg(priv, 0x0B, 0xFF & (v32 >> 16)); 184 lgs8gxx_write_reg(priv, 0x0C, 0xFF & (v32 >> 24)); 185 } 186 187 return 0; 188} 189 190static int lgs8gxx_get_afc_phase(struct lgs8gxx_state *priv) 191{ 192 u64 val; 193 u32 v32 = 0; 194 u8 reg_addr, t; 195 int i; 196 197 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) 198 reg_addr = 0x23; 199 else 200 reg_addr = 0x48; 201 202 for (i = 0; i < 4; i++) { 203 lgs8gxx_read_reg(priv, reg_addr, &t); 204 v32 <<= 8; 205 v32 |= t; 206 reg_addr--; 207 } 208 209 val = v32; 210 val *= priv->config->if_clk_freq; 211 val >>= 32; 212 dprintk("AFC = %u kHz\n", (u32)val); 213 return 0; 214} 215 216static int lgs8gxx_set_mode_auto(struct lgs8gxx_state *priv) 217{ 218 u8 t; 219 u8 prod = priv->config->prod; 220 221 if (prod == LGS8GXX_PROD_LGS8913) 222 lgs8gxx_write_reg(priv, 0xC6, 0x01); 223 224 if (prod == LGS8GXX_PROD_LGS8G75) { 225 lgs8gxx_read_reg(priv, 0x0C, &t); 226 t &= (~0x04); 227 lgs8gxx_write_reg(priv, 0x0C, t | 0x80); 228 lgs8gxx_write_reg(priv, 0x39, 0x00); 229 lgs8gxx_write_reg(priv, 0x3D, 0x04); 230 } else if (prod == LGS8GXX_PROD_LGS8913 || 231 prod == LGS8GXX_PROD_LGS8GL5 || 232 prod == LGS8GXX_PROD_LGS8G42 || 233 prod == LGS8GXX_PROD_LGS8G52 || 234 prod == LGS8GXX_PROD_LGS8G54) { 235 lgs8gxx_read_reg(priv, 0x7E, &t); 236 lgs8gxx_write_reg(priv, 0x7E, t | 0x01); 237 238 /* clear FEC self reset */ 239 lgs8gxx_read_reg(priv, 0xC5, &t); 240 lgs8gxx_write_reg(priv, 0xC5, t & 0xE0); 241 } 242 243 if (prod == LGS8GXX_PROD_LGS8913) { 244 /* FEC auto detect */ 245 lgs8gxx_write_reg(priv, 0xC1, 0x03); 246 247 lgs8gxx_read_reg(priv, 0x7C, &t); 248 t = (t & 0x8C) | 0x03; 249 lgs8gxx_write_reg(priv, 0x7C, t); 250 251 /* BER test mode */ 252 lgs8gxx_read_reg(priv, 0xC3, &t); 253 t = (t & 0xEF) | 0x10; 254 lgs8gxx_write_reg(priv, 0xC3, t); 255 } 256 257 if (priv->config->prod == LGS8GXX_PROD_LGS8G52) 258 lgs8gxx_write_reg(priv, 0xD9, 0x40); 259 260 return 0; 261} 262 263static int lgs8gxx_set_mode_manual(struct lgs8gxx_state *priv) 264{ 265 int ret = 0; 266 u8 t; 267 268 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 269 u8 t2; 270 lgs8gxx_read_reg(priv, 0x0C, &t); 271 t &= (~0x80); 272 lgs8gxx_write_reg(priv, 0x0C, t); 273 274 lgs8gxx_read_reg(priv, 0x0C, &t); 275 lgs8gxx_read_reg(priv, 0x19, &t2); 276 277 if (((t&0x03) == 0x01) && (t2&0x01)) { 278 lgs8gxx_write_reg(priv, 0x6E, 0x05); 279 lgs8gxx_write_reg(priv, 0x39, 0x02); 280 lgs8gxx_write_reg(priv, 0x39, 0x03); 281 lgs8gxx_write_reg(priv, 0x3D, 0x05); 282 lgs8gxx_write_reg(priv, 0x3E, 0x28); 283 lgs8gxx_write_reg(priv, 0x53, 0x80); 284 } else { 285 lgs8gxx_write_reg(priv, 0x6E, 0x3F); 286 lgs8gxx_write_reg(priv, 0x39, 0x00); 287 lgs8gxx_write_reg(priv, 0x3D, 0x04); 288 } 289 290 lgs8gxx_soft_reset(priv); 291 return 0; 292 } 293 294 /* turn off auto-detect; manual settings */ 295 lgs8gxx_write_reg(priv, 0x7E, 0); 296 if (priv->config->prod == LGS8GXX_PROD_LGS8913) 297 lgs8gxx_write_reg(priv, 0xC1, 0); 298 299 ret = lgs8gxx_read_reg(priv, 0xC5, &t); 300 t = (t & 0xE0) | 0x06; 301 lgs8gxx_write_reg(priv, 0xC5, t); 302 303 lgs8gxx_soft_reset(priv); 304 305 return 0; 306} 307 308static int lgs8gxx_is_locked(struct lgs8gxx_state *priv, u8 *locked) 309{ 310 int ret = 0; 311 u8 t; 312 313 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) 314 ret = lgs8gxx_read_reg(priv, 0x13, &t); 315 else 316 ret = lgs8gxx_read_reg(priv, 0x4B, &t); 317 if (ret != 0) 318 return ret; 319 320 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) 321 *locked = ((t & 0x80) == 0x80) ? 1 : 0; 322 else 323 *locked = ((t & 0xC0) == 0xC0) ? 1 : 0; 324 return 0; 325} 326 327/* Wait for Code Acquisition Lock */ 328static int lgs8gxx_wait_ca_lock(struct lgs8gxx_state *priv, u8 *locked) 329{ 330 int ret = 0; 331 u8 reg, mask, val; 332 333 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 334 reg = 0x13; 335 mask = 0x80; 336 val = 0x80; 337 } else { 338 reg = 0x4B; 339 mask = 0xC0; 340 val = 0xC0; 341 } 342 343 ret = wait_reg_mask(priv, reg, mask, val, 50, 40); 344 *locked = (ret == 0) ? 1 : 0; 345 346 return 0; 347} 348 349static int lgs8gxx_is_autodetect_finished(struct lgs8gxx_state *priv, 350 u8 *finished) 351{ 352 int ret = 0; 353 u8 reg, mask, val; 354 355 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 356 reg = 0x1f; 357 mask = 0xC0; 358 val = 0x80; 359 } else { 360 reg = 0xA4; 361 mask = 0x03; 362 val = 0x01; 363 } 364 365 ret = wait_reg_mask(priv, reg, mask, val, 10, 20); 366 *finished = (ret == 0) ? 1 : 0; 367 368 return 0; 369} 370 371static int lgs8gxx_autolock_gi(struct lgs8gxx_state *priv, u8 gi, u8 cpn, 372 u8 *locked) 373{ 374 int err = 0; 375 u8 ad_fini = 0; 376 u8 t1, t2; 377 378 if (gi == GI_945) 379 dprintk("try GI 945\n"); 380 else if (gi == GI_595) 381 dprintk("try GI 595\n"); 382 else if (gi == GI_420) 383 dprintk("try GI 420\n"); 384 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 385 lgs8gxx_read_reg(priv, 0x0C, &t1); 386 lgs8gxx_read_reg(priv, 0x18, &t2); 387 t1 &= ~(GI_MASK); 388 t1 |= gi; 389 t2 &= 0xFE; 390 t2 |= cpn ? 0x01 : 0x00; 391 lgs8gxx_write_reg(priv, 0x0C, t1); 392 lgs8gxx_write_reg(priv, 0x18, t2); 393 } else { 394 lgs8gxx_write_reg(priv, 0x04, gi); 395 } 396 lgs8gxx_soft_reset(priv); 397 err = lgs8gxx_wait_ca_lock(priv, locked); 398 if (err || !(*locked)) 399 return err; 400 err = lgs8gxx_is_autodetect_finished(priv, &ad_fini); 401 if (err != 0) 402 return err; 403 if (ad_fini) { 404 dprintk("auto detect finished\n"); 405 } else 406 *locked = 0; 407 408 return 0; 409} 410 411static int lgs8gxx_auto_detect(struct lgs8gxx_state *priv, 412 u8 *detected_param, u8 *gi) 413{ 414 int i, j; 415 int err = 0; 416 u8 locked = 0, tmp_gi; 417 418 dprintk("%s\n", __func__); 419 420 lgs8gxx_set_mode_auto(priv); 421 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 422 lgs8gxx_write_reg(priv, 0x67, 0xAA); 423 lgs8gxx_write_reg(priv, 0x6E, 0x3F); 424 } else { 425 /* Guard Interval */ 426 lgs8gxx_write_reg(priv, 0x03, 00); 427 } 428 429 for (i = 0; i < 2; i++) { 430 for (j = 0; j < 2; j++) { 431 tmp_gi = GI_945; 432 err = lgs8gxx_autolock_gi(priv, GI_945, j, &locked); 433 if (err) 434 goto out; 435 if (locked) 436 goto locked; 437 } 438 for (j = 0; j < 2; j++) { 439 tmp_gi = GI_420; 440 err = lgs8gxx_autolock_gi(priv, GI_420, j, &locked); 441 if (err) 442 goto out; 443 if (locked) 444 goto locked; 445 } 446 tmp_gi = GI_595; 447 err = lgs8gxx_autolock_gi(priv, GI_595, 1, &locked); 448 if (err) 449 goto out; 450 if (locked) 451 goto locked; 452 } 453 454locked: 455 if ((err == 0) && (locked == 1)) { 456 u8 t; 457 458 if (priv->config->prod != LGS8GXX_PROD_LGS8G75) { 459 lgs8gxx_read_reg(priv, 0xA2, &t); 460 *detected_param = t; 461 } else { 462 lgs8gxx_read_reg(priv, 0x1F, &t); 463 *detected_param = t & 0x3F; 464 } 465 466 if (tmp_gi == GI_945) 467 dprintk("GI 945 locked\n"); 468 else if (tmp_gi == GI_595) 469 dprintk("GI 595 locked\n"); 470 else if (tmp_gi == GI_420) 471 dprintk("GI 420 locked\n"); 472 *gi = tmp_gi; 473 } 474 if (!locked) 475 err = -1; 476 477out: 478 return err; 479} 480 481static void lgs8gxx_auto_lock(struct lgs8gxx_state *priv) 482{ 483 s8 err; 484 u8 gi = 0x2; 485 u8 detected_param = 0; 486 487 err = lgs8gxx_auto_detect(priv, &detected_param, &gi); 488 489 if (err != 0) { 490 dprintk("lgs8gxx_auto_detect failed\n"); 491 } else 492 dprintk("detected param = 0x%02X\n", detected_param); 493 494 /* Apply detected parameters */ 495 if (priv->config->prod == LGS8GXX_PROD_LGS8913) { 496 u8 inter_leave_len = detected_param & TIM_MASK ; 497 /* Fix 8913 time interleaver detection bug */ 498 inter_leave_len = (inter_leave_len == TIM_MIDDLE) ? 0x60 : 0x40; 499 detected_param &= CF_MASK | SC_MASK | LGS_FEC_MASK; 500 detected_param |= inter_leave_len; 501 } 502 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 503 u8 t; 504 lgs8gxx_read_reg(priv, 0x19, &t); 505 t &= 0x81; 506 t |= detected_param << 1; 507 lgs8gxx_write_reg(priv, 0x19, t); 508 } else { 509 lgs8gxx_write_reg(priv, 0x7D, detected_param); 510 if (priv->config->prod == LGS8GXX_PROD_LGS8913) 511 lgs8gxx_write_reg(priv, 0xC0, detected_param); 512 } 513 /* lgs8gxx_soft_reset(priv); */ 514 515 /* Enter manual mode */ 516 lgs8gxx_set_mode_manual(priv); 517 518 switch (gi) { 519 case GI_945: 520 priv->curr_gi = 945; break; 521 case GI_595: 522 priv->curr_gi = 595; break; 523 case GI_420: 524 priv->curr_gi = 420; break; 525 default: 526 priv->curr_gi = 945; break; 527 } 528} 529 530static int lgs8gxx_set_mpeg_mode(struct lgs8gxx_state *priv, 531 u8 serial, u8 clk_pol, u8 clk_gated) 532{ 533 int ret = 0; 534 u8 t, reg_addr; 535 536 reg_addr = (priv->config->prod == LGS8GXX_PROD_LGS8G75) ? 0x30 : 0xC2; 537 ret = lgs8gxx_read_reg(priv, reg_addr, &t); 538 if (ret != 0) 539 return ret; 540 541 t &= 0xF8; 542 t |= serial ? TS_SERIAL : TS_PARALLEL; 543 t |= clk_pol ? TS_CLK_INVERTED : TS_CLK_NORMAL; 544 t |= clk_gated ? TS_CLK_GATED : TS_CLK_FREERUN; 545 546 ret = lgs8gxx_write_reg(priv, reg_addr, t); 547 if (ret != 0) 548 return ret; 549 550 return 0; 551} 552 553/* A/D input peak-to-peak voltage range */ 554static int lgs8g75_set_adc_vpp(struct lgs8gxx_state *priv, 555 u8 sel) 556{ 557 u8 r26 = 0x73, r27 = 0x90; 558 559 if (priv->config->prod != LGS8GXX_PROD_LGS8G75) 560 return 0; 561 562 r26 |= (sel & 0x01) << 7; 563 r27 |= (sel & 0x02) >> 1; 564 lgs8gxx_write_reg(priv, 0x26, r26); 565 lgs8gxx_write_reg(priv, 0x27, r27); 566 567 return 0; 568} 569 570/* LGS8913 demod frontend functions */ 571 572static int lgs8913_init(struct lgs8gxx_state *priv) 573{ 574 u8 t; 575 576 /* LGS8913 specific */ 577 lgs8gxx_write_reg(priv, 0xc1, 0x3); 578 579 lgs8gxx_read_reg(priv, 0x7c, &t); 580 lgs8gxx_write_reg(priv, 0x7c, (t&0x8c) | 0x3); 581 582 /* LGS8913 specific */ 583 lgs8gxx_read_reg(priv, 0xc3, &t); 584 lgs8gxx_write_reg(priv, 0xc3, t&0x10); 585 586 587 return 0; 588} 589 590static int lgs8g75_init_data(struct lgs8gxx_state *priv) 591{ 592 const struct firmware *fw; 593 int rc; 594 int i; 595 596 rc = request_firmware(&fw, "lgs8g75.fw", &priv->i2c->dev); 597 if (rc) 598 return rc; 599 600 lgs8gxx_write_reg(priv, 0xC6, 0x40); 601 602 lgs8gxx_write_reg(priv, 0x3D, 0x04); 603 lgs8gxx_write_reg(priv, 0x39, 0x00); 604 605 lgs8gxx_write_reg(priv, 0x3A, 0x00); 606 lgs8gxx_write_reg(priv, 0x38, 0x00); 607 lgs8gxx_write_reg(priv, 0x3B, 0x00); 608 lgs8gxx_write_reg(priv, 0x38, 0x00); 609 610 for (i = 0; i < fw->size; i++) { 611 lgs8gxx_write_reg(priv, 0x38, 0x00); 612 lgs8gxx_write_reg(priv, 0x3A, (u8)(i&0xff)); 613 lgs8gxx_write_reg(priv, 0x3B, (u8)(i>>8)); 614 lgs8gxx_write_reg(priv, 0x3C, fw->data[i]); 615 } 616 617 lgs8gxx_write_reg(priv, 0x38, 0x00); 618 619 release_firmware(fw); 620 return 0; 621} 622 623static int lgs8gxx_init(struct dvb_frontend *fe) 624{ 625 struct lgs8gxx_state *priv = 626 (struct lgs8gxx_state *)fe->demodulator_priv; 627 const struct lgs8gxx_config *config = priv->config; 628 u8 data = 0; 629 s8 err; 630 dprintk("%s\n", __func__); 631 632 lgs8gxx_read_reg(priv, 0, &data); 633 dprintk("reg 0 = 0x%02X\n", data); 634 635 if (config->prod == LGS8GXX_PROD_LGS8G75) 636 lgs8g75_set_adc_vpp(priv, config->adc_vpp); 637 638 /* Setup MPEG output format */ 639 err = lgs8gxx_set_mpeg_mode(priv, config->serial_ts, 640 config->ts_clk_pol, 641 config->ts_clk_gated); 642 if (err != 0) 643 return -EIO; 644 645 if (config->prod == LGS8GXX_PROD_LGS8913) 646 lgs8913_init(priv); 647 lgs8gxx_set_if_freq(priv, priv->config->if_freq); 648 lgs8gxx_set_ad_mode(priv); 649 650 return 0; 651} 652 653static void lgs8gxx_release(struct dvb_frontend *fe) 654{ 655 struct lgs8gxx_state *state = fe->demodulator_priv; 656 dprintk("%s\n", __func__); 657 658 kfree(state); 659} 660 661 662static int lgs8gxx_write(struct dvb_frontend *fe, const u8 buf[], int len) 663{ 664 struct lgs8gxx_state *priv = fe->demodulator_priv; 665 666 if (len != 2) 667 return -EINVAL; 668 669 return lgs8gxx_write_reg(priv, buf[0], buf[1]); 670} 671 672static int lgs8gxx_set_fe(struct dvb_frontend *fe) 673{ 674 675 struct lgs8gxx_state *priv = fe->demodulator_priv; 676 677 dprintk("%s\n", __func__); 678 679 /* set frequency */ 680 if (fe->ops.tuner_ops.set_params) { 681 fe->ops.tuner_ops.set_params(fe); 682 if (fe->ops.i2c_gate_ctrl) 683 fe->ops.i2c_gate_ctrl(fe, 0); 684 } 685 686 /* start auto lock */ 687 lgs8gxx_auto_lock(priv); 688 689 msleep(10); 690 691 return 0; 692} 693 694static int lgs8gxx_get_fe(struct dvb_frontend *fe) 695{ 696 struct dtv_frontend_properties *fe_params = &fe->dtv_property_cache; 697 dprintk("%s\n", __func__); 698 699 /* TODO: get real readings from device */ 700 /* inversion status */ 701 fe_params->inversion = INVERSION_OFF; 702 703 /* bandwidth */ 704 fe_params->bandwidth_hz = 8000000; 705 706 fe_params->code_rate_HP = FEC_AUTO; 707 fe_params->code_rate_LP = FEC_AUTO; 708 709 fe_params->modulation = QAM_AUTO; 710 711 /* transmission mode */ 712 fe_params->transmission_mode = TRANSMISSION_MODE_AUTO; 713 714 /* guard interval */ 715 fe_params->guard_interval = GUARD_INTERVAL_AUTO; 716 717 /* hierarchy */ 718 fe_params->hierarchy = HIERARCHY_NONE; 719 720 return 0; 721} 722 723static 724int lgs8gxx_get_tune_settings(struct dvb_frontend *fe, 725 struct dvb_frontend_tune_settings *fesettings) 726{ 727 /* FIXME: copy from tda1004x.c */ 728 fesettings->min_delay_ms = 800; 729 fesettings->step_size = 0; 730 fesettings->max_drift = 0; 731 return 0; 732} 733 734static int lgs8gxx_read_status(struct dvb_frontend *fe, fe_status_t *fe_status) 735{ 736 struct lgs8gxx_state *priv = fe->demodulator_priv; 737 s8 ret; 738 u8 t, locked = 0; 739 740 dprintk("%s\n", __func__); 741 *fe_status = 0; 742 743 lgs8gxx_get_afc_phase(priv); 744 lgs8gxx_is_locked(priv, &locked); 745 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 746 if (locked) 747 *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | 748 FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; 749 return 0; 750 } 751 752 ret = lgs8gxx_read_reg(priv, 0x4B, &t); 753 if (ret != 0) 754 return -EIO; 755 756 dprintk("Reg 0x4B: 0x%02X\n", t); 757 758 *fe_status = 0; 759 if (priv->config->prod == LGS8GXX_PROD_LGS8913) { 760 if ((t & 0x40) == 0x40) 761 *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER; 762 if ((t & 0x80) == 0x80) 763 *fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC | 764 FE_HAS_LOCK; 765 } else { 766 if ((t & 0x80) == 0x80) 767 *fe_status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | 768 FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; 769 } 770 771 /* success */ 772 dprintk("%s: fe_status=0x%x\n", __func__, *fe_status); 773 return 0; 774} 775 776static int lgs8gxx_read_signal_agc(struct lgs8gxx_state *priv, u16 *signal) 777{ 778 u16 v; 779 u8 agc_lvl[2], cat; 780 781 dprintk("%s()\n", __func__); 782 lgs8gxx_read_reg(priv, 0x3F, &agc_lvl[0]); 783 lgs8gxx_read_reg(priv, 0x3E, &agc_lvl[1]); 784 785 v = agc_lvl[0]; 786 v <<= 8; 787 v |= agc_lvl[1]; 788 789 dprintk("agc_lvl: 0x%04X\n", v); 790 791 if (v < 0x100) 792 cat = 0; 793 else if (v < 0x190) 794 cat = 5; 795 else if (v < 0x2A8) 796 cat = 4; 797 else if (v < 0x381) 798 cat = 3; 799 else if (v < 0x400) 800 cat = 2; 801 else if (v == 0x400) 802 cat = 1; 803 else 804 cat = 0; 805 806 *signal = cat * 65535 / 5; 807 808 return 0; 809} 810 811static int lgs8913_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal) 812{ 813 u8 t; s8 ret; 814 s16 max_strength = 0; 815 u8 str; 816 u16 i, gi = priv->curr_gi; 817 818 dprintk("%s\n", __func__); 819 820 ret = lgs8gxx_read_reg(priv, 0x4B, &t); 821 if (ret != 0) 822 return -EIO; 823 824 if (fake_signal_str) { 825 if ((t & 0xC0) == 0xC0) { 826 dprintk("Fake signal strength\n"); 827 *signal = 0x7FFF; 828 } else 829 *signal = 0; 830 return 0; 831 } 832 833 dprintk("gi = %d\n", gi); 834 for (i = 0; i < gi; i++) { 835 836 if ((i & 0xFF) == 0) 837 lgs8gxx_write_reg(priv, 0x84, 0x03 & (i >> 8)); 838 lgs8gxx_write_reg(priv, 0x83, i & 0xFF); 839 840 lgs8gxx_read_reg(priv, 0x94, &str); 841 if (max_strength < str) 842 max_strength = str; 843 } 844 845 *signal = max_strength; 846 dprintk("%s: signal=0x%02X\n", __func__, *signal); 847 848 lgs8gxx_read_reg(priv, 0x95, &t); 849 dprintk("%s: AVG Noise=0x%02X\n", __func__, t); 850 851 return 0; 852} 853 854static int lgs8g75_read_signal_strength(struct lgs8gxx_state *priv, u16 *signal) 855{ 856 u8 t; 857 s16 v = 0; 858 859 dprintk("%s\n", __func__); 860 861 lgs8gxx_read_reg(priv, 0xB1, &t); 862 v |= t; 863 v <<= 8; 864 lgs8gxx_read_reg(priv, 0xB0, &t); 865 v |= t; 866 867 *signal = v; 868 dprintk("%s: signal=0x%02X\n", __func__, *signal); 869 870 return 0; 871} 872 873static int lgs8gxx_read_signal_strength(struct dvb_frontend *fe, u16 *signal) 874{ 875 struct lgs8gxx_state *priv = fe->demodulator_priv; 876 877 if (priv->config->prod == LGS8GXX_PROD_LGS8913) 878 return lgs8913_read_signal_strength(priv, signal); 879 else if (priv->config->prod == LGS8GXX_PROD_LGS8G75) 880 return lgs8g75_read_signal_strength(priv, signal); 881 else 882 return lgs8gxx_read_signal_agc(priv, signal); 883} 884 885static int lgs8gxx_read_snr(struct dvb_frontend *fe, u16 *snr) 886{ 887 struct lgs8gxx_state *priv = fe->demodulator_priv; 888 u8 t; 889 *snr = 0; 890 891 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) 892 lgs8gxx_read_reg(priv, 0x34, &t); 893 else 894 lgs8gxx_read_reg(priv, 0x95, &t); 895 dprintk("AVG Noise=0x%02X\n", t); 896 *snr = 256 - t; 897 *snr <<= 8; 898 dprintk("snr=0x%x\n", *snr); 899 900 return 0; 901} 902 903static int lgs8gxx_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 904{ 905 *ucblocks = 0; 906 dprintk("%s: ucblocks=0x%x\n", __func__, *ucblocks); 907 return 0; 908} 909 910static void packet_counter_start(struct lgs8gxx_state *priv) 911{ 912 u8 orig, t; 913 914 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 915 lgs8gxx_read_reg(priv, 0x30, &orig); 916 orig &= 0xE7; 917 t = orig | 0x10; 918 lgs8gxx_write_reg(priv, 0x30, t); 919 t = orig | 0x18; 920 lgs8gxx_write_reg(priv, 0x30, t); 921 t = orig | 0x10; 922 lgs8gxx_write_reg(priv, 0x30, t); 923 } else { 924 lgs8gxx_write_reg(priv, 0xC6, 0x01); 925 lgs8gxx_write_reg(priv, 0xC6, 0x41); 926 lgs8gxx_write_reg(priv, 0xC6, 0x01); 927 } 928} 929 930static void packet_counter_stop(struct lgs8gxx_state *priv) 931{ 932 u8 t; 933 934 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 935 lgs8gxx_read_reg(priv, 0x30, &t); 936 t &= 0xE7; 937 lgs8gxx_write_reg(priv, 0x30, t); 938 } else { 939 lgs8gxx_write_reg(priv, 0xC6, 0x81); 940 } 941} 942 943static int lgs8gxx_read_ber(struct dvb_frontend *fe, u32 *ber) 944{ 945 struct lgs8gxx_state *priv = fe->demodulator_priv; 946 u8 reg_err, reg_total, t; 947 u32 total_cnt = 0, err_cnt = 0; 948 int i; 949 950 dprintk("%s\n", __func__); 951 952 packet_counter_start(priv); 953 msleep(200); 954 packet_counter_stop(priv); 955 956 if (priv->config->prod == LGS8GXX_PROD_LGS8G75) { 957 reg_total = 0x28; reg_err = 0x2C; 958 } else { 959 reg_total = 0xD0; reg_err = 0xD4; 960 } 961 962 for (i = 0; i < 4; i++) { 963 total_cnt <<= 8; 964 lgs8gxx_read_reg(priv, reg_total+3-i, &t); 965 total_cnt |= t; 966 } 967 for (i = 0; i < 4; i++) { 968 err_cnt <<= 8; 969 lgs8gxx_read_reg(priv, reg_err+3-i, &t); 970 err_cnt |= t; 971 } 972 dprintk("error=%d total=%d\n", err_cnt, total_cnt); 973 974 if (total_cnt == 0) 975 *ber = 0; 976 else 977 *ber = err_cnt * 100 / total_cnt; 978 979 dprintk("%s: ber=0x%x\n", __func__, *ber); 980 return 0; 981} 982 983static int lgs8gxx_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) 984{ 985 struct lgs8gxx_state *priv = fe->demodulator_priv; 986 987 if (priv->config->tuner_address == 0) 988 return 0; 989 if (enable) { 990 u8 v = 0x80 | priv->config->tuner_address; 991 return lgs8gxx_write_reg(priv, 0x01, v); 992 } 993 return lgs8gxx_write_reg(priv, 0x01, 0); 994} 995 996static struct dvb_frontend_ops lgs8gxx_ops = { 997 .delsys = { SYS_DMBTH }, 998 .info = { 999 .name = "Legend Silicon LGS8913/LGS8GXX DMB-TH", 1000 .frequency_min = 474000000, 1001 .frequency_max = 858000000, 1002 .frequency_stepsize = 10000, 1003 .caps = 1004 FE_CAN_FEC_AUTO | 1005 FE_CAN_QAM_AUTO | 1006 FE_CAN_TRANSMISSION_MODE_AUTO | 1007 FE_CAN_GUARD_INTERVAL_AUTO 1008 }, 1009 1010 .release = lgs8gxx_release, 1011 1012 .init = lgs8gxx_init, 1013 .write = lgs8gxx_write, 1014 .i2c_gate_ctrl = lgs8gxx_i2c_gate_ctrl, 1015 1016 .set_frontend = lgs8gxx_set_fe, 1017 .get_frontend = lgs8gxx_get_fe, 1018 .get_tune_settings = lgs8gxx_get_tune_settings, 1019 1020 .read_status = lgs8gxx_read_status, 1021 .read_ber = lgs8gxx_read_ber, 1022 .read_signal_strength = lgs8gxx_read_signal_strength, 1023 .read_snr = lgs8gxx_read_snr, 1024 .read_ucblocks = lgs8gxx_read_ucblocks, 1025}; 1026 1027struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config, 1028 struct i2c_adapter *i2c) 1029{ 1030 struct lgs8gxx_state *priv = NULL; 1031 u8 data = 0; 1032 1033 dprintk("%s()\n", __func__); 1034 1035 if (config == NULL || i2c == NULL) 1036 return NULL; 1037 1038 priv = kzalloc(sizeof(struct lgs8gxx_state), GFP_KERNEL); 1039 if (priv == NULL) 1040 goto error_out; 1041 1042 priv->config = config; 1043 priv->i2c = i2c; 1044 1045 /* check if the demod is there */ 1046 if (lgs8gxx_read_reg(priv, 0, &data) != 0) { 1047 dprintk("%s lgs8gxx not found at i2c addr 0x%02X\n", 1048 __func__, priv->config->demod_address); 1049 goto error_out; 1050 } 1051 1052 lgs8gxx_read_reg(priv, 1, &data); 1053 1054 memcpy(&priv->frontend.ops, &lgs8gxx_ops, 1055 sizeof(struct dvb_frontend_ops)); 1056 priv->frontend.demodulator_priv = priv; 1057 1058 if (config->prod == LGS8GXX_PROD_LGS8G75) 1059 lgs8g75_init_data(priv); 1060 1061 return &priv->frontend; 1062 1063error_out: 1064 dprintk("%s() error_out\n", __func__); 1065 kfree(priv); 1066 return NULL; 1067 1068} 1069EXPORT_SYMBOL(lgs8gxx_attach); 1070 1071MODULE_DESCRIPTION("Legend Silicon LGS8913/LGS8GXX DMB-TH demodulator driver"); 1072MODULE_AUTHOR("David T. L. Wong <davidtlwong@gmail.com>"); 1073MODULE_LICENSE("GPL");