diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/media/tuners/tda18271-common.c | 104 |
1 files changed, 71 insertions, 33 deletions
diff --git a/drivers/media/tuners/tda18271-common.c b/drivers/media/tuners/tda18271-common.c index 221171eeb0c3..18c77afe2e4f 100644 --- a/drivers/media/tuners/tda18271-common.c +++ b/drivers/media/tuners/tda18271-common.c | |||
| @@ -187,7 +187,8 @@ int tda18271_read_extended(struct dvb_frontend *fe) | |||
| 187 | return (ret == 2 ? 0 : ret); | 187 | return (ret == 2 ? 0 : ret); |
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) | 190 | static int __tda18271_write_regs(struct dvb_frontend *fe, int idx, int len, |
| 191 | bool lock_i2c) | ||
| 191 | { | 192 | { |
| 192 | struct tda18271_priv *priv = fe->tuner_priv; | 193 | struct tda18271_priv *priv = fe->tuner_priv; |
| 193 | unsigned char *regs = priv->tda18271_regs; | 194 | unsigned char *regs = priv->tda18271_regs; |
| @@ -198,7 +199,6 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) | |||
| 198 | 199 | ||
| 199 | BUG_ON((len == 0) || (idx + len > sizeof(buf))); | 200 | BUG_ON((len == 0) || (idx + len > sizeof(buf))); |
| 200 | 201 | ||
| 201 | |||
| 202 | switch (priv->small_i2c) { | 202 | switch (priv->small_i2c) { |
| 203 | case TDA18271_03_BYTE_CHUNK_INIT: | 203 | case TDA18271_03_BYTE_CHUNK_INIT: |
| 204 | max = 3; | 204 | max = 3; |
| @@ -214,7 +214,19 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) | |||
| 214 | max = 39; | 214 | max = 39; |
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | tda18271_i2c_gate_ctrl(fe, 1); | 217 | |
| 218 | /* | ||
| 219 | * If lock_i2c is true, it will take the I2C bus for tda18271 private | ||
| 220 | * usage during the entire write ops, as otherwise, bad things could | ||
| 221 | * happen. | ||
| 222 | * During device init, several write operations will happen. So, | ||
| 223 | * tda18271_init_regs controls the I2C lock directly, | ||
| 224 | * disabling lock_i2c here. | ||
| 225 | */ | ||
| 226 | if (lock_i2c) { | ||
| 227 | tda18271_i2c_gate_ctrl(fe, 1); | ||
| 228 | i2c_lock_adapter(priv->i2c_props.adap); | ||
| 229 | } | ||
| 218 | while (len) { | 230 | while (len) { |
| 219 | if (max > len) | 231 | if (max > len) |
| 220 | max = len; | 232 | max = len; |
| @@ -226,14 +238,17 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) | |||
| 226 | msg.len = max + 1; | 238 | msg.len = max + 1; |
| 227 | 239 | ||
| 228 | /* write registers */ | 240 | /* write registers */ |
| 229 | ret = i2c_transfer(priv->i2c_props.adap, &msg, 1); | 241 | ret = __i2c_transfer(priv->i2c_props.adap, &msg, 1); |
| 230 | if (ret != 1) | 242 | if (ret != 1) |
| 231 | break; | 243 | break; |
| 232 | 244 | ||
| 233 | idx += max; | 245 | idx += max; |
| 234 | len -= max; | 246 | len -= max; |
| 235 | } | 247 | } |
| 236 | tda18271_i2c_gate_ctrl(fe, 0); | 248 | if (lock_i2c) { |
| 249 | i2c_unlock_adapter(priv->i2c_props.adap); | ||
| 250 | tda18271_i2c_gate_ctrl(fe, 0); | ||
| 251 | } | ||
| 237 | 252 | ||
| 238 | if (ret != 1) | 253 | if (ret != 1) |
| 239 | tda_err("ERROR: idx = 0x%x, len = %d, " | 254 | tda_err("ERROR: idx = 0x%x, len = %d, " |
| @@ -242,10 +257,16 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) | |||
| 242 | return (ret == 1 ? 0 : ret); | 257 | return (ret == 1 ? 0 : ret); |
| 243 | } | 258 | } |
| 244 | 259 | ||
| 260 | int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len) | ||
| 261 | { | ||
| 262 | return __tda18271_write_regs(fe, idx, len, true); | ||
| 263 | } | ||
| 264 | |||
| 245 | /*---------------------------------------------------------------------*/ | 265 | /*---------------------------------------------------------------------*/ |
| 246 | 266 | ||
| 247 | int tda18271_charge_pump_source(struct dvb_frontend *fe, | 267 | static int __tda18271_charge_pump_source(struct dvb_frontend *fe, |
| 248 | enum tda18271_pll pll, int force) | 268 | enum tda18271_pll pll, int force, |
| 269 | bool lock_i2c) | ||
| 249 | { | 270 | { |
| 250 | struct tda18271_priv *priv = fe->tuner_priv; | 271 | struct tda18271_priv *priv = fe->tuner_priv; |
| 251 | unsigned char *regs = priv->tda18271_regs; | 272 | unsigned char *regs = priv->tda18271_regs; |
| @@ -255,9 +276,16 @@ int tda18271_charge_pump_source(struct dvb_frontend *fe, | |||
| 255 | regs[r_cp] &= ~0x20; | 276 | regs[r_cp] &= ~0x20; |
| 256 | regs[r_cp] |= ((force & 1) << 5); | 277 | regs[r_cp] |= ((force & 1) << 5); |
| 257 | 278 | ||
| 258 | return tda18271_write_regs(fe, r_cp, 1); | 279 | return __tda18271_write_regs(fe, r_cp, 1, lock_i2c); |
| 280 | } | ||
| 281 | |||
| 282 | int tda18271_charge_pump_source(struct dvb_frontend *fe, | ||
| 283 | enum tda18271_pll pll, int force) | ||
| 284 | { | ||
| 285 | return __tda18271_charge_pump_source(fe, pll, force, true); | ||
| 259 | } | 286 | } |
| 260 | 287 | ||
| 288 | |||
| 261 | int tda18271_init_regs(struct dvb_frontend *fe) | 289 | int tda18271_init_regs(struct dvb_frontend *fe) |
| 262 | { | 290 | { |
| 263 | struct tda18271_priv *priv = fe->tuner_priv; | 291 | struct tda18271_priv *priv = fe->tuner_priv; |
| @@ -267,6 +295,13 @@ int tda18271_init_regs(struct dvb_frontend *fe) | |||
| 267 | i2c_adapter_id(priv->i2c_props.adap), | 295 | i2c_adapter_id(priv->i2c_props.adap), |
| 268 | priv->i2c_props.addr); | 296 | priv->i2c_props.addr); |
| 269 | 297 | ||
| 298 | /* | ||
| 299 | * Don't let any other I2C transfer to happen at adapter during init, | ||
| 300 | * as those could cause bad things | ||
| 301 | */ | ||
| 302 | tda18271_i2c_gate_ctrl(fe, 1); | ||
| 303 | i2c_lock_adapter(priv->i2c_props.adap); | ||
| 304 | |||
| 270 | /* initialize registers */ | 305 | /* initialize registers */ |
| 271 | switch (priv->id) { | 306 | switch (priv->id) { |
| 272 | case TDA18271HDC1: | 307 | case TDA18271HDC1: |
| @@ -352,28 +387,28 @@ int tda18271_init_regs(struct dvb_frontend *fe) | |||
| 352 | regs[R_EB22] = 0x48; | 387 | regs[R_EB22] = 0x48; |
| 353 | regs[R_EB23] = 0xb0; | 388 | regs[R_EB23] = 0xb0; |
| 354 | 389 | ||
| 355 | tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS); | 390 | __tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS, false); |
| 356 | 391 | ||
| 357 | /* setup agc1 gain */ | 392 | /* setup agc1 gain */ |
| 358 | regs[R_EB17] = 0x00; | 393 | regs[R_EB17] = 0x00; |
| 359 | tda18271_write_regs(fe, R_EB17, 1); | 394 | __tda18271_write_regs(fe, R_EB17, 1, false); |
| 360 | regs[R_EB17] = 0x03; | 395 | regs[R_EB17] = 0x03; |
| 361 | tda18271_write_regs(fe, R_EB17, 1); | 396 | __tda18271_write_regs(fe, R_EB17, 1, false); |
| 362 | regs[R_EB17] = 0x43; | 397 | regs[R_EB17] = 0x43; |
| 363 | tda18271_write_regs(fe, R_EB17, 1); | 398 | __tda18271_write_regs(fe, R_EB17, 1, false); |
| 364 | regs[R_EB17] = 0x4c; | 399 | regs[R_EB17] = 0x4c; |
| 365 | tda18271_write_regs(fe, R_EB17, 1); | 400 | __tda18271_write_regs(fe, R_EB17, 1, false); |
| 366 | 401 | ||
| 367 | /* setup agc2 gain */ | 402 | /* setup agc2 gain */ |
| 368 | if ((priv->id) == TDA18271HDC1) { | 403 | if ((priv->id) == TDA18271HDC1) { |
| 369 | regs[R_EB20] = 0xa0; | 404 | regs[R_EB20] = 0xa0; |
| 370 | tda18271_write_regs(fe, R_EB20, 1); | 405 | __tda18271_write_regs(fe, R_EB20, 1, false); |
| 371 | regs[R_EB20] = 0xa7; | 406 | regs[R_EB20] = 0xa7; |
| 372 | tda18271_write_regs(fe, R_EB20, 1); | 407 | __tda18271_write_regs(fe, R_EB20, 1, false); |
| 373 | regs[R_EB20] = 0xe7; | 408 | regs[R_EB20] = 0xe7; |
| 374 | tda18271_write_regs(fe, R_EB20, 1); | 409 | __tda18271_write_regs(fe, R_EB20, 1, false); |
| 375 | regs[R_EB20] = 0xec; | 410 | regs[R_EB20] = 0xec; |
| 376 | tda18271_write_regs(fe, R_EB20, 1); | 411 | __tda18271_write_regs(fe, R_EB20, 1, false); |
| 377 | } | 412 | } |
| 378 | 413 | ||
| 379 | /* image rejection calibration */ | 414 | /* image rejection calibration */ |
| @@ -391,21 +426,21 @@ int tda18271_init_regs(struct dvb_frontend *fe) | |||
| 391 | regs[R_MD2] = 0x08; | 426 | regs[R_MD2] = 0x08; |
| 392 | regs[R_MD3] = 0x00; | 427 | regs[R_MD3] = 0x00; |
| 393 | 428 | ||
| 394 | tda18271_write_regs(fe, R_EP3, 11); | 429 | __tda18271_write_regs(fe, R_EP3, 11, false); |
| 395 | 430 | ||
| 396 | if ((priv->id) == TDA18271HDC2) { | 431 | if ((priv->id) == TDA18271HDC2) { |
| 397 | /* main pll cp source on */ | 432 | /* main pll cp source on */ |
| 398 | tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1); | 433 | __tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 1, false); |
| 399 | msleep(1); | 434 | msleep(1); |
| 400 | 435 | ||
| 401 | /* main pll cp source off */ | 436 | /* main pll cp source off */ |
| 402 | tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0); | 437 | __tda18271_charge_pump_source(fe, TDA18271_MAIN_PLL, 0, false); |
| 403 | } | 438 | } |
| 404 | 439 | ||
| 405 | msleep(5); /* pll locking */ | 440 | msleep(5); /* pll locking */ |
| 406 | 441 | ||
| 407 | /* launch detector */ | 442 | /* launch detector */ |
| 408 | tda18271_write_regs(fe, R_EP1, 1); | 443 | __tda18271_write_regs(fe, R_EP1, 1, false); |
| 409 | msleep(5); /* wanted low measurement */ | 444 | msleep(5); /* wanted low measurement */ |
| 410 | 445 | ||
| 411 | regs[R_EP5] = 0x85; | 446 | regs[R_EP5] = 0x85; |
| @@ -413,11 +448,11 @@ int tda18271_init_regs(struct dvb_frontend *fe) | |||
| 413 | regs[R_CD1] = 0x66; | 448 | regs[R_CD1] = 0x66; |
| 414 | regs[R_CD2] = 0x70; | 449 | regs[R_CD2] = 0x70; |
| 415 | 450 | ||
| 416 | tda18271_write_regs(fe, R_EP3, 7); | 451 | __tda18271_write_regs(fe, R_EP3, 7, false); |
| 417 | msleep(5); /* pll locking */ | 452 | msleep(5); /* pll locking */ |
| 418 | 453 | ||
| 419 | /* launch optimization algorithm */ | 454 | /* launch optimization algorithm */ |
| 420 | tda18271_write_regs(fe, R_EP2, 1); | 455 | __tda18271_write_regs(fe, R_EP2, 1, false); |
| 421 | msleep(30); /* image low optimization completion */ | 456 | msleep(30); /* image low optimization completion */ |
| 422 | 457 | ||
| 423 | /* mid-band */ | 458 | /* mid-band */ |
| @@ -428,11 +463,11 @@ int tda18271_init_regs(struct dvb_frontend *fe) | |||
| 428 | regs[R_MD1] = 0x73; | 463 | regs[R_MD1] = 0x73; |
| 429 | regs[R_MD2] = 0x1a; | 464 | regs[R_MD2] = 0x1a; |
| 430 | 465 | ||
| 431 | tda18271_write_regs(fe, R_EP3, 11); | 466 | __tda18271_write_regs(fe, R_EP3, 11, false); |
| 432 | msleep(5); /* pll locking */ | 467 | msleep(5); /* pll locking */ |
| 433 | 468 | ||
| 434 | /* launch detector */ | 469 | /* launch detector */ |
| 435 | tda18271_write_regs(fe, R_EP1, 1); | 470 | __tda18271_write_regs(fe, R_EP1, 1, false); |
| 436 | msleep(5); /* wanted mid measurement */ | 471 | msleep(5); /* wanted mid measurement */ |
| 437 | 472 | ||
| 438 | regs[R_EP5] = 0x86; | 473 | regs[R_EP5] = 0x86; |
| @@ -440,11 +475,11 @@ int tda18271_init_regs(struct dvb_frontend *fe) | |||
| 440 | regs[R_CD1] = 0x66; | 475 | regs[R_CD1] = 0x66; |
| 441 | regs[R_CD2] = 0xa0; | 476 | regs[R_CD2] = 0xa0; |
| 442 | 477 | ||
| 443 | tda18271_write_regs(fe, R_EP3, 7); | 478 | __tda18271_write_regs(fe, R_EP3, 7, false); |
| 444 | msleep(5); /* pll locking */ | 479 | msleep(5); /* pll locking */ |
| 445 | 480 | ||
| 446 | /* launch optimization algorithm */ | 481 | /* launch optimization algorithm */ |
| 447 | tda18271_write_regs(fe, R_EP2, 1); | 482 | __tda18271_write_regs(fe, R_EP2, 1, false); |
| 448 | msleep(30); /* image mid optimization completion */ | 483 | msleep(30); /* image mid optimization completion */ |
| 449 | 484 | ||
| 450 | /* high-band */ | 485 | /* high-band */ |
| @@ -456,30 +491,33 @@ int tda18271_init_regs(struct dvb_frontend *fe) | |||
| 456 | regs[R_MD1] = 0x71; | 491 | regs[R_MD1] = 0x71; |
| 457 | regs[R_MD2] = 0xcd; | 492 | regs[R_MD2] = 0xcd; |
| 458 | 493 | ||
| 459 | tda18271_write_regs(fe, R_EP3, 11); | 494 | __tda18271_write_regs(fe, R_EP3, 11, false); |
| 460 | msleep(5); /* pll locking */ | 495 | msleep(5); /* pll locking */ |
| 461 | 496 | ||
| 462 | /* launch detector */ | 497 | /* launch detector */ |
| 463 | tda18271_write_regs(fe, R_EP1, 1); | 498 | __tda18271_write_regs(fe, R_EP1, 1, false); |
| 464 | msleep(5); /* wanted high measurement */ | 499 | msleep(5); /* wanted high measurement */ |
| 465 | 500 | ||
| 466 | regs[R_EP5] = 0x87; | 501 | regs[R_EP5] = 0x87; |
| 467 | regs[R_CD1] = 0x65; | 502 | regs[R_CD1] = 0x65; |
| 468 | regs[R_CD2] = 0x50; | 503 | regs[R_CD2] = 0x50; |
| 469 | 504 | ||
| 470 | tda18271_write_regs(fe, R_EP3, 7); | 505 | __tda18271_write_regs(fe, R_EP3, 7, false); |
| 471 | msleep(5); /* pll locking */ | 506 | msleep(5); /* pll locking */ |
| 472 | 507 | ||
| 473 | /* launch optimization algorithm */ | 508 | /* launch optimization algorithm */ |
| 474 | tda18271_write_regs(fe, R_EP2, 1); | 509 | __tda18271_write_regs(fe, R_EP2, 1, false); |
| 475 | msleep(30); /* image high optimization completion */ | 510 | msleep(30); /* image high optimization completion */ |
| 476 | 511 | ||
| 477 | /* return to normal mode */ | 512 | /* return to normal mode */ |
| 478 | regs[R_EP4] = 0x64; | 513 | regs[R_EP4] = 0x64; |
| 479 | tda18271_write_regs(fe, R_EP4, 1); | 514 | __tda18271_write_regs(fe, R_EP4, 1, false); |
| 480 | 515 | ||
| 481 | /* synchronize */ | 516 | /* synchronize */ |
| 482 | tda18271_write_regs(fe, R_EP1, 1); | 517 | __tda18271_write_regs(fe, R_EP1, 1, false); |
| 518 | |||
| 519 | i2c_unlock_adapter(priv->i2c_props.adap); | ||
| 520 | tda18271_i2c_gate_ctrl(fe, 0); | ||
| 483 | 521 | ||
| 484 | return 0; | 522 | return 0; |
| 485 | } | 523 | } |
