diff options
-rw-r--r-- | drivers/media/video/tuner-simple.c | 331 |
1 files changed, 184 insertions, 147 deletions
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index de0b291459f7..10addf2ba5ce 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c | |||
@@ -251,59 +251,13 @@ static int simple_config_lookup(struct dvb_frontend *fe, | |||
251 | 251 | ||
252 | /* ---------------------------------------------------------------------- */ | 252 | /* ---------------------------------------------------------------------- */ |
253 | 253 | ||
254 | static int simple_set_tv_freq(struct dvb_frontend *fe, | 254 | static int simple_std_setup(struct dvb_frontend *fe, |
255 | struct analog_parameters *params) | 255 | struct analog_parameters *params, |
256 | u8 *buffer, u8 *config, u8 *cb) | ||
256 | { | 257 | { |
257 | struct tuner_simple_priv *priv = fe->tuner_priv; | 258 | struct tuner_simple_priv *priv = fe->tuner_priv; |
258 | u8 config, cb, tuneraddr; | 259 | u8 tuneraddr; |
259 | u16 div; | 260 | int rc; |
260 | struct tunertype *tun; | ||
261 | u8 buffer[4]; | ||
262 | int rc, IFPCoff, i; | ||
263 | enum param_type desired_type; | ||
264 | struct tuner_params *t_params; | ||
265 | |||
266 | tun = priv->tun; | ||
267 | |||
268 | /* IFPCoff = Video Intermediate Frequency - Vif: | ||
269 | 940 =16*58.75 NTSC/J (Japan) | ||
270 | 732 =16*45.75 M/N STD | ||
271 | 704 =16*44 ATSC (at DVB code) | ||
272 | 632 =16*39.50 I U.K. | ||
273 | 622.4=16*38.90 B/G D/K I, L STD | ||
274 | 592 =16*37.00 D China | ||
275 | 590 =16.36.875 B Australia | ||
276 | 543.2=16*33.95 L' STD | ||
277 | 171.2=16*10.70 FM Radio (at set_radio_freq) | ||
278 | */ | ||
279 | |||
280 | if (params->std == V4L2_STD_NTSC_M_JP) { | ||
281 | IFPCoff = 940; | ||
282 | desired_type = TUNER_PARAM_TYPE_NTSC; | ||
283 | } else if ((params->std & V4L2_STD_MN) && | ||
284 | !(params->std & ~V4L2_STD_MN)) { | ||
285 | IFPCoff = 732; | ||
286 | desired_type = TUNER_PARAM_TYPE_NTSC; | ||
287 | } else if (params->std == V4L2_STD_SECAM_LC) { | ||
288 | IFPCoff = 543; | ||
289 | desired_type = TUNER_PARAM_TYPE_SECAM; | ||
290 | } else { | ||
291 | IFPCoff = 623; | ||
292 | desired_type = TUNER_PARAM_TYPE_PAL; | ||
293 | } | ||
294 | |||
295 | t_params = simple_tuner_params(fe, desired_type); | ||
296 | |||
297 | i = simple_config_lookup(fe, t_params, ¶ms->frequency, | ||
298 | &config, &cb); | ||
299 | |||
300 | div = params->frequency + IFPCoff + offset; | ||
301 | |||
302 | tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, " | ||
303 | "Offset=%d.%02d MHz, div=%0d\n", | ||
304 | params->frequency / 16, params->frequency % 16 * 100 / 16, | ||
305 | IFPCoff / 16, IFPCoff % 16 * 100 / 16, | ||
306 | offset / 16, offset % 16 * 100 / 16, div); | ||
307 | 261 | ||
308 | /* tv norm specific stuff for multi-norm tuners */ | 262 | /* tv norm specific stuff for multi-norm tuners */ |
309 | switch (priv->type) { | 263 | switch (priv->type) { |
@@ -311,45 +265,45 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, | |||
311 | /* 0x01 -> ??? no change ??? */ | 265 | /* 0x01 -> ??? no change ??? */ |
312 | /* 0x02 -> PAL BDGHI / SECAM L */ | 266 | /* 0x02 -> PAL BDGHI / SECAM L */ |
313 | /* 0x04 -> ??? PAL others / SECAM others ??? */ | 267 | /* 0x04 -> ??? PAL others / SECAM others ??? */ |
314 | cb &= ~0x03; | 268 | *cb &= ~0x03; |
315 | if (params->std & V4L2_STD_SECAM_L) | 269 | if (params->std & V4L2_STD_SECAM_L) |
316 | /* also valid for V4L2_STD_SECAM */ | 270 | /* also valid for V4L2_STD_SECAM */ |
317 | cb |= PHILIPS_MF_SET_STD_L; | 271 | *cb |= PHILIPS_MF_SET_STD_L; |
318 | else if (params->std & V4L2_STD_SECAM_LC) | 272 | else if (params->std & V4L2_STD_SECAM_LC) |
319 | cb |= PHILIPS_MF_SET_STD_LC; | 273 | *cb |= PHILIPS_MF_SET_STD_LC; |
320 | else /* V4L2_STD_B|V4L2_STD_GH */ | 274 | else /* V4L2_STD_B|V4L2_STD_GH */ |
321 | cb |= PHILIPS_MF_SET_STD_BG; | 275 | *cb |= PHILIPS_MF_SET_STD_BG; |
322 | break; | 276 | break; |
323 | 277 | ||
324 | case TUNER_TEMIC_4046FM5: | 278 | case TUNER_TEMIC_4046FM5: |
325 | cb &= ~0x0f; | 279 | *cb &= ~0x0f; |
326 | 280 | ||
327 | if (params->std & V4L2_STD_PAL_BG) { | 281 | if (params->std & V4L2_STD_PAL_BG) { |
328 | cb |= TEMIC_SET_PAL_BG; | 282 | *cb |= TEMIC_SET_PAL_BG; |
329 | 283 | ||
330 | } else if (params->std & V4L2_STD_PAL_I) { | 284 | } else if (params->std & V4L2_STD_PAL_I) { |
331 | cb |= TEMIC_SET_PAL_I; | 285 | *cb |= TEMIC_SET_PAL_I; |
332 | 286 | ||
333 | } else if (params->std & V4L2_STD_PAL_DK) { | 287 | } else if (params->std & V4L2_STD_PAL_DK) { |
334 | cb |= TEMIC_SET_PAL_DK; | 288 | *cb |= TEMIC_SET_PAL_DK; |
335 | 289 | ||
336 | } else if (params->std & V4L2_STD_SECAM_L) { | 290 | } else if (params->std & V4L2_STD_SECAM_L) { |
337 | cb |= TEMIC_SET_PAL_L; | 291 | *cb |= TEMIC_SET_PAL_L; |
338 | 292 | ||
339 | } | 293 | } |
340 | break; | 294 | break; |
341 | 295 | ||
342 | case TUNER_PHILIPS_FQ1216ME: | 296 | case TUNER_PHILIPS_FQ1216ME: |
343 | cb &= ~0x0f; | 297 | *cb &= ~0x0f; |
344 | 298 | ||
345 | if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) { | 299 | if (params->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) { |
346 | cb |= PHILIPS_SET_PAL_BGDK; | 300 | *cb |= PHILIPS_SET_PAL_BGDK; |
347 | 301 | ||
348 | } else if (params->std & V4L2_STD_PAL_I) { | 302 | } else if (params->std & V4L2_STD_PAL_I) { |
349 | cb |= PHILIPS_SET_PAL_I; | 303 | *cb |= PHILIPS_SET_PAL_I; |
350 | 304 | ||
351 | } else if (params->std & V4L2_STD_SECAM_L) { | 305 | } else if (params->std & V4L2_STD_SECAM_L) { |
352 | cb |= PHILIPS_SET_PAL_L; | 306 | *cb |= PHILIPS_SET_PAL_L; |
353 | 307 | ||
354 | } | 308 | } |
355 | break; | 309 | break; |
@@ -359,15 +313,15 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, | |||
359 | /* 0x01 -> ATSC antenna input 2 */ | 313 | /* 0x01 -> ATSC antenna input 2 */ |
360 | /* 0x02 -> NTSC antenna input 1 */ | 314 | /* 0x02 -> NTSC antenna input 1 */ |
361 | /* 0x03 -> NTSC antenna input 2 */ | 315 | /* 0x03 -> NTSC antenna input 2 */ |
362 | cb &= ~0x03; | 316 | *cb &= ~0x03; |
363 | if (!(params->std & V4L2_STD_ATSC)) | 317 | if (!(params->std & V4L2_STD_ATSC)) |
364 | cb |= 2; | 318 | *cb |= 2; |
365 | /* FIXME: input */ | 319 | /* FIXME: input */ |
366 | break; | 320 | break; |
367 | 321 | ||
368 | case TUNER_MICROTUNE_4042FI5: | 322 | case TUNER_MICROTUNE_4042FI5: |
369 | /* Set the charge pump for fast tuning */ | 323 | /* Set the charge pump for fast tuning */ |
370 | config |= TUNER_CHARGE_PUMP; | 324 | *config |= TUNER_CHARGE_PUMP; |
371 | break; | 325 | break; |
372 | 326 | ||
373 | case TUNER_PHILIPS_TUV1236D: | 327 | case TUNER_PHILIPS_TUV1236D: |
@@ -379,9 +333,9 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, | |||
379 | buffer[1] = 0x00; | 333 | buffer[1] = 0x00; |
380 | buffer[2] = 0x17; | 334 | buffer[2] = 0x17; |
381 | buffer[3] = 0x00; | 335 | buffer[3] = 0x00; |
382 | cb &= ~0x40; | 336 | *cb &= ~0x40; |
383 | if (params->std & V4L2_STD_ATSC) { | 337 | if (params->std & V4L2_STD_ATSC) { |
384 | cb |= 0x40; | 338 | *cb |= 0x40; |
385 | buffer[1] = 0x04; | 339 | buffer[1] = 0x04; |
386 | } | 340 | } |
387 | /* set to the correct mode (analog or digital) */ | 341 | /* set to the correct mode (analog or digital) */ |
@@ -400,6 +354,165 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, | |||
400 | break; | 354 | break; |
401 | } | 355 | } |
402 | 356 | ||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | static int simple_post_tune(struct dvb_frontend *fe, u8 *buffer, | ||
361 | u16 div, u8 config, u8 cb) | ||
362 | { | ||
363 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
364 | int rc; | ||
365 | |||
366 | switch (priv->type) { | ||
367 | case TUNER_LG_TDVS_H06XF: | ||
368 | /* Set the Auxiliary Byte. */ | ||
369 | buffer[0] = buffer[2]; | ||
370 | buffer[0] &= ~0x20; | ||
371 | buffer[0] |= 0x18; | ||
372 | buffer[1] = 0x20; | ||
373 | tuner_dbg("tv 0x%02x 0x%02x\n", buffer[0], buffer[1]); | ||
374 | |||
375 | rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2); | ||
376 | if (2 != rc) | ||
377 | tuner_warn("i2c i/o error: rc == %d " | ||
378 | "(should be 2)\n", rc); | ||
379 | break; | ||
380 | case TUNER_MICROTUNE_4042FI5: | ||
381 | { | ||
382 | /* FIXME - this may also work for other tuners */ | ||
383 | unsigned long timeout = jiffies + msecs_to_jiffies(1); | ||
384 | u8 status_byte = 0; | ||
385 | |||
386 | /* Wait until the PLL locks */ | ||
387 | for (;;) { | ||
388 | if (time_after(jiffies, timeout)) | ||
389 | return 0; | ||
390 | rc = tuner_i2c_xfer_recv(&priv->i2c_props, | ||
391 | &status_byte, 1); | ||
392 | if (1 != rc) { | ||
393 | tuner_warn("i2c i/o read error: rc == %d " | ||
394 | "(should be 1)\n", rc); | ||
395 | break; | ||
396 | } | ||
397 | if (status_byte & TUNER_PLL_LOCKED) | ||
398 | break; | ||
399 | udelay(10); | ||
400 | } | ||
401 | |||
402 | /* Set the charge pump for optimized phase noise figure */ | ||
403 | config &= ~TUNER_CHARGE_PUMP; | ||
404 | buffer[0] = (div>>8) & 0x7f; | ||
405 | buffer[1] = div & 0xff; | ||
406 | buffer[2] = config; | ||
407 | buffer[3] = cb; | ||
408 | tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
409 | buffer[0], buffer[1], buffer[2], buffer[3]); | ||
410 | |||
411 | rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4); | ||
412 | if (4 != rc) | ||
413 | tuner_warn("i2c i/o error: rc == %d " | ||
414 | "(should be 4)\n", rc); | ||
415 | break; | ||
416 | } | ||
417 | } | ||
418 | |||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | static int simple_radio_bandswitch(struct dvb_frontend *fe, u8 *buffer) | ||
423 | { | ||
424 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
425 | |||
426 | switch (priv->type) { | ||
427 | case TUNER_TENA_9533_DI: | ||
428 | case TUNER_YMEC_TVF_5533MF: | ||
429 | tuner_dbg("This tuner doesn't have FM. " | ||
430 | "Most cards have a TEA5767 for FM\n"); | ||
431 | return 0; | ||
432 | case TUNER_PHILIPS_FM1216ME_MK3: | ||
433 | case TUNER_PHILIPS_FM1236_MK3: | ||
434 | case TUNER_PHILIPS_FMD1216ME_MK3: | ||
435 | case TUNER_LG_NTSC_TAPE: | ||
436 | case TUNER_PHILIPS_FM1256_IH3: | ||
437 | buffer[3] = 0x19; | ||
438 | break; | ||
439 | case TUNER_TNF_5335MF: | ||
440 | buffer[3] = 0x11; | ||
441 | break; | ||
442 | case TUNER_LG_PAL_FM: | ||
443 | buffer[3] = 0xa5; | ||
444 | break; | ||
445 | case TUNER_THOMSON_DTT761X: | ||
446 | buffer[3] = 0x39; | ||
447 | break; | ||
448 | case TUNER_MICROTUNE_4049FM5: | ||
449 | default: | ||
450 | buffer[3] = 0xa4; | ||
451 | break; | ||
452 | } | ||
453 | |||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | /* ---------------------------------------------------------------------- */ | ||
458 | |||
459 | static int simple_set_tv_freq(struct dvb_frontend *fe, | ||
460 | struct analog_parameters *params) | ||
461 | { | ||
462 | struct tuner_simple_priv *priv = fe->tuner_priv; | ||
463 | u8 config, cb; | ||
464 | u16 div; | ||
465 | struct tunertype *tun; | ||
466 | u8 buffer[4]; | ||
467 | int rc, IFPCoff, i; | ||
468 | enum param_type desired_type; | ||
469 | struct tuner_params *t_params; | ||
470 | |||
471 | tun = priv->tun; | ||
472 | |||
473 | /* IFPCoff = Video Intermediate Frequency - Vif: | ||
474 | 940 =16*58.75 NTSC/J (Japan) | ||
475 | 732 =16*45.75 M/N STD | ||
476 | 704 =16*44 ATSC (at DVB code) | ||
477 | 632 =16*39.50 I U.K. | ||
478 | 622.4=16*38.90 B/G D/K I, L STD | ||
479 | 592 =16*37.00 D China | ||
480 | 590 =16.36.875 B Australia | ||
481 | 543.2=16*33.95 L' STD | ||
482 | 171.2=16*10.70 FM Radio (at set_radio_freq) | ||
483 | */ | ||
484 | |||
485 | if (params->std == V4L2_STD_NTSC_M_JP) { | ||
486 | IFPCoff = 940; | ||
487 | desired_type = TUNER_PARAM_TYPE_NTSC; | ||
488 | } else if ((params->std & V4L2_STD_MN) && | ||
489 | !(params->std & ~V4L2_STD_MN)) { | ||
490 | IFPCoff = 732; | ||
491 | desired_type = TUNER_PARAM_TYPE_NTSC; | ||
492 | } else if (params->std == V4L2_STD_SECAM_LC) { | ||
493 | IFPCoff = 543; | ||
494 | desired_type = TUNER_PARAM_TYPE_SECAM; | ||
495 | } else { | ||
496 | IFPCoff = 623; | ||
497 | desired_type = TUNER_PARAM_TYPE_PAL; | ||
498 | } | ||
499 | |||
500 | t_params = simple_tuner_params(fe, desired_type); | ||
501 | |||
502 | i = simple_config_lookup(fe, t_params, ¶ms->frequency, | ||
503 | &config, &cb); | ||
504 | |||
505 | div = params->frequency + IFPCoff + offset; | ||
506 | |||
507 | tuner_dbg("Freq= %d.%02d MHz, V_IF=%d.%02d MHz, " | ||
508 | "Offset=%d.%02d MHz, div=%0d\n", | ||
509 | params->frequency / 16, params->frequency % 16 * 100 / 16, | ||
510 | IFPCoff / 16, IFPCoff % 16 * 100 / 16, | ||
511 | offset / 16, offset % 16 * 100 / 16, div); | ||
512 | |||
513 | /* tv norm specific stuff for multi-norm tuners */ | ||
514 | simple_std_setup(fe, params, &buffer[1], &config, &cb); | ||
515 | |||
403 | if (t_params->cb_first_if_lower_freq && div < priv->last_div) { | 516 | if (t_params->cb_first_if_lower_freq && div < priv->last_div) { |
404 | buffer[0] = config; | 517 | buffer[0] = config; |
405 | buffer[1] = cb; | 518 | buffer[1] = cb; |
@@ -463,58 +576,8 @@ static int simple_set_tv_freq(struct dvb_frontend *fe, | |||
463 | if (4 != rc) | 576 | if (4 != rc) |
464 | tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc); | 577 | tuner_warn("i2c i/o error: rc == %d (should be 4)\n", rc); |
465 | 578 | ||
466 | switch (priv->type) { | 579 | simple_post_tune(fe, &buffer[0], div, config, cb); |
467 | case TUNER_LG_TDVS_H06XF: | ||
468 | /* Set the Auxiliary Byte. */ | ||
469 | buffer[0] = buffer[2]; | ||
470 | buffer[0] &= ~0x20; | ||
471 | buffer[0] |= 0x18; | ||
472 | buffer[1] = 0x20; | ||
473 | tuner_dbg("tv 0x%02x 0x%02x\n", buffer[0], buffer[1]); | ||
474 | |||
475 | rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 2); | ||
476 | if (2 != rc) | ||
477 | tuner_warn("i2c i/o error: rc == %d " | ||
478 | "(should be 2)\n", rc); | ||
479 | break; | ||
480 | case TUNER_MICROTUNE_4042FI5: | ||
481 | { | ||
482 | /* FIXME - this may also work for other tuners */ | ||
483 | unsigned long timeout = jiffies + msecs_to_jiffies(1); | ||
484 | u8 status_byte = 0; | ||
485 | |||
486 | /* Wait until the PLL locks */ | ||
487 | for (;;) { | ||
488 | if (time_after(jiffies, timeout)) | ||
489 | return 0; | ||
490 | rc = tuner_i2c_xfer_recv(&priv->i2c_props, | ||
491 | &status_byte, 1); | ||
492 | if (1 != rc) { | ||
493 | tuner_warn("i2c i/o read error: rc == %d " | ||
494 | "(should be 1)\n", rc); | ||
495 | break; | ||
496 | } | ||
497 | if (status_byte & TUNER_PLL_LOCKED) | ||
498 | break; | ||
499 | udelay(10); | ||
500 | } | ||
501 | |||
502 | /* Set the charge pump for optimized phase noise figure */ | ||
503 | config &= ~TUNER_CHARGE_PUMP; | ||
504 | buffer[0] = (div>>8) & 0x7f; | ||
505 | buffer[1] = div & 0xff; | ||
506 | buffer[2] = config; | ||
507 | buffer[3] = cb; | ||
508 | tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", | ||
509 | buffer[0], buffer[1], buffer[2], buffer[3]); | ||
510 | 580 | ||
511 | rc = tuner_i2c_xfer_send(&priv->i2c_props, buffer, 4); | ||
512 | if (4 != rc) | ||
513 | tuner_warn("i2c i/o error: rc == %d " | ||
514 | "(should be 4)\n", rc); | ||
515 | break; | ||
516 | } | ||
517 | } | ||
518 | return 0; | 581 | return 0; |
519 | } | 582 | } |
520 | 583 | ||
@@ -555,33 +618,7 @@ static int simple_set_radio_freq(struct dvb_frontend *fe, | |||
555 | } | 618 | } |
556 | 619 | ||
557 | /* Bandswitch byte */ | 620 | /* Bandswitch byte */ |
558 | switch (priv->type) { | 621 | simple_radio_bandswitch(fe, &buffer[0]); |
559 | case TUNER_TENA_9533_DI: | ||
560 | case TUNER_YMEC_TVF_5533MF: | ||
561 | tuner_dbg("This tuner doesn't have FM. " | ||
562 | "Most cards have a TEA5767 for FM\n"); | ||
563 | return 0; | ||
564 | case TUNER_PHILIPS_FM1216ME_MK3: | ||
565 | case TUNER_PHILIPS_FM1236_MK3: | ||
566 | case TUNER_PHILIPS_FMD1216ME_MK3: | ||
567 | case TUNER_LG_NTSC_TAPE: | ||
568 | case TUNER_PHILIPS_FM1256_IH3: | ||
569 | buffer[3] = 0x19; | ||
570 | break; | ||
571 | case TUNER_TNF_5335MF: | ||
572 | buffer[3] = 0x11; | ||
573 | break; | ||
574 | case TUNER_LG_PAL_FM: | ||
575 | buffer[3] = 0xa5; | ||
576 | break; | ||
577 | case TUNER_THOMSON_DTT761X: | ||
578 | buffer[3] = 0x39; | ||
579 | break; | ||
580 | case TUNER_MICROTUNE_4049FM5: | ||
581 | default: | ||
582 | buffer[3] = 0xa4; | ||
583 | break; | ||
584 | } | ||
585 | 622 | ||
586 | buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) | | 623 | buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) | |
587 | TUNER_RATIO_SELECT_50; /* 50 kHz step */ | 624 | TUNER_RATIO_SELECT_50; /* 50 kHz step */ |