diff options
-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 | } |