aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/frontends/rtl2830.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/frontends/rtl2830.c')
-rw-r--r--drivers/media/dvb/frontends/rtl2830.c201
1 files changed, 198 insertions, 3 deletions
diff --git a/drivers/media/dvb/frontends/rtl2830.c b/drivers/media/dvb/frontends/rtl2830.c
index 45196c5b0736..93612ebac519 100644
--- a/drivers/media/dvb/frontends/rtl2830.c
+++ b/drivers/media/dvb/frontends/rtl2830.c
@@ -374,6 +374,118 @@ err:
374 return ret; 374 return ret;
375} 375}
376 376
377static int rtl2830_get_frontend(struct dvb_frontend *fe)
378{
379 struct rtl2830_priv *priv = fe->demodulator_priv;
380 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
381 int ret;
382 u8 buf[3];
383
384 if (priv->sleeping)
385 return 0;
386
387 ret = rtl2830_rd_regs(priv, 0x33c, buf, 2);
388 if (ret)
389 goto err;
390
391 ret = rtl2830_rd_reg(priv, 0x351, &buf[2]);
392 if (ret)
393 goto err;
394
395 dbg("%s: TPS=%02x %02x %02x", __func__, buf[0], buf[1], buf[2]);
396
397 switch ((buf[0] >> 2) & 3) {
398 case 0:
399 c->modulation = QPSK;
400 break;
401 case 1:
402 c->modulation = QAM_16;
403 break;
404 case 2:
405 c->modulation = QAM_64;
406 break;
407 }
408
409 switch ((buf[2] >> 2) & 1) {
410 case 0:
411 c->transmission_mode = TRANSMISSION_MODE_2K;
412 break;
413 case 1:
414 c->transmission_mode = TRANSMISSION_MODE_8K;
415 }
416
417 switch ((buf[2] >> 0) & 3) {
418 case 0:
419 c->guard_interval = GUARD_INTERVAL_1_32;
420 break;
421 case 1:
422 c->guard_interval = GUARD_INTERVAL_1_16;
423 break;
424 case 2:
425 c->guard_interval = GUARD_INTERVAL_1_8;
426 break;
427 case 3:
428 c->guard_interval = GUARD_INTERVAL_1_4;
429 break;
430 }
431
432 switch ((buf[0] >> 4) & 7) {
433 case 0:
434 c->hierarchy = HIERARCHY_NONE;
435 break;
436 case 1:
437 c->hierarchy = HIERARCHY_1;
438 break;
439 case 2:
440 c->hierarchy = HIERARCHY_2;
441 break;
442 case 3:
443 c->hierarchy = HIERARCHY_4;
444 break;
445 }
446
447 switch ((buf[1] >> 3) & 7) {
448 case 0:
449 c->code_rate_HP = FEC_1_2;
450 break;
451 case 1:
452 c->code_rate_HP = FEC_2_3;
453 break;
454 case 2:
455 c->code_rate_HP = FEC_3_4;
456 break;
457 case 3:
458 c->code_rate_HP = FEC_5_6;
459 break;
460 case 4:
461 c->code_rate_HP = FEC_7_8;
462 break;
463 }
464
465 switch ((buf[1] >> 0) & 7) {
466 case 0:
467 c->code_rate_LP = FEC_1_2;
468 break;
469 case 1:
470 c->code_rate_LP = FEC_2_3;
471 break;
472 case 2:
473 c->code_rate_LP = FEC_3_4;
474 break;
475 case 3:
476 c->code_rate_LP = FEC_5_6;
477 break;
478 case 4:
479 c->code_rate_LP = FEC_7_8;
480 break;
481 }
482
483 return 0;
484err:
485 dbg("%s: failed=%d", __func__, ret);
486 return ret;
487}
488
377static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status) 489static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status)
378{ 490{
379 struct rtl2830_priv *priv = fe->demodulator_priv; 491 struct rtl2830_priv *priv = fe->demodulator_priv;
@@ -404,14 +516,72 @@ err:
404 516
405static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr) 517static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr)
406{ 518{
407 *snr = 0; 519 struct rtl2830_priv *priv = fe->demodulator_priv;
520 int ret, hierarchy, constellation;
521 u8 buf[2], tmp;
522 u16 tmp16;
523#define CONSTELLATION_NUM 3
524#define HIERARCHY_NUM 4
525 static const u32 snr_constant[CONSTELLATION_NUM][HIERARCHY_NUM] = {
526 { 70705899, 70705899, 70705899, 70705899 },
527 { 82433173, 82433173, 87483115, 94445660 },
528 { 92888734, 92888734, 95487525, 99770748 },
529 };
530
531 if (priv->sleeping)
532 return 0;
533
534 /* reports SNR in resolution of 0.1 dB */
535
536 ret = rtl2830_rd_reg(priv, 0x33c, &tmp);
537 if (ret)
538 goto err;
539
540 constellation = (tmp >> 2) & 0x03; /* [3:2] */
541 if (constellation > CONSTELLATION_NUM - 1)
542 goto err;
543
544 hierarchy = (tmp >> 4) & 0x07; /* [6:4] */
545 if (hierarchy > HIERARCHY_NUM - 1)
546 goto err;
547
548 ret = rtl2830_rd_regs(priv, 0x40c, buf, 2);
549 if (ret)
550 goto err;
551
552 tmp16 = buf[0] << 8 | buf[1];
553
554 if (tmp16)
555 *snr = (snr_constant[constellation][hierarchy] -
556 intlog10(tmp16)) / ((1 << 24) / 100);
557 else
558 *snr = 0;
559
408 return 0; 560 return 0;
561err:
562 dbg("%s: failed=%d", __func__, ret);
563 return ret;
409} 564}
410 565
411static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber) 566static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber)
412{ 567{
413 *ber = 0; 568 struct rtl2830_priv *priv = fe->demodulator_priv;
569 int ret;
570 u8 buf[2];
571
572 if (priv->sleeping)
573 return 0;
574
575 ret = rtl2830_rd_regs(priv, 0x34e, buf, 2);
576 if (ret)
577 goto err;
578
579 *ber = buf[0] << 8 | buf[1];
580
414 return 0; 581 return 0;
582err:
583 dbg("%s: failed=%d", __func__, ret);
584 return ret;
415} 585}
416 586
417static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 587static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
@@ -422,8 +592,32 @@ static int rtl2830_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
422 592
423static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength) 593static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
424{ 594{
425 *strength = 0; 595 struct rtl2830_priv *priv = fe->demodulator_priv;
596 int ret;
597 u8 buf[2];
598 u16 if_agc_raw, if_agc;
599
600 if (priv->sleeping)
601 return 0;
602
603 ret = rtl2830_rd_regs(priv, 0x359, buf, 2);
604 if (ret)
605 goto err;
606
607 if_agc_raw = (buf[0] << 8 | buf[1]) & 0x3fff;
608
609 if (if_agc_raw & (1 << 9))
610 if_agc = -(~(if_agc_raw - 1) & 0x1ff);
611 else
612 if_agc = if_agc_raw;
613
614 *strength = (u8) (55 - if_agc / 182);
615 *strength |= *strength << 8;
616
426 return 0; 617 return 0;
618err:
619 dbg("%s: failed=%d", __func__, ret);
620 return ret;
427} 621}
428 622
429static struct dvb_frontend_ops rtl2830_ops; 623static struct dvb_frontend_ops rtl2830_ops;
@@ -549,6 +743,7 @@ static struct dvb_frontend_ops rtl2830_ops = {
549 .get_tune_settings = rtl2830_get_tune_settings, 743 .get_tune_settings = rtl2830_get_tune_settings,
550 744
551 .set_frontend = rtl2830_set_frontend, 745 .set_frontend = rtl2830_set_frontend,
746 .get_frontend = rtl2830_get_frontend,
552 747
553 .read_status = rtl2830_read_status, 748 .read_status = rtl2830_read_status,
554 .read_snr = rtl2830_read_snr, 749 .read_snr = rtl2830_read_snr,