aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/frontends/lgdt330x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/frontends/lgdt330x.c')
-rw-r--r--drivers/media/dvb/frontends/lgdt330x.c257
1 files changed, 126 insertions, 131 deletions
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
index 9a354708bd20..68aad0f6519f 100644
--- a/drivers/media/dvb/frontends/lgdt330x.c
+++ b/drivers/media/dvb/frontends/lgdt330x.c
@@ -31,9 +31,6 @@
31 * Air2PC/AirStar 2 ATSC 3rd generation (HD5000) 31 * Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
32 * pcHDTV HD5500 32 * pcHDTV HD5500
33 * 33 *
34 * TODO:
35 * signal strength always returns 0.
36 *
37 */ 34 */
38 35
39#include <linux/kernel.h> 36#include <linux/kernel.h>
@@ -46,9 +43,13 @@
46#include <asm/byteorder.h> 43#include <asm/byteorder.h>
47 44
48#include "dvb_frontend.h" 45#include "dvb_frontend.h"
46#include "dvb_math.h"
49#include "lgdt330x_priv.h" 47#include "lgdt330x_priv.h"
50#include "lgdt330x.h" 48#include "lgdt330x.h"
51 49
50/* Use Equalizer Mean Squared Error instead of Phaser Tracker MSE */
51/* #define USE_EQMSE */
52
52static int debug = 0; 53static int debug = 0;
53module_param(debug, int, 0644); 54module_param(debug, int, 0644);
54MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off)."); 55MODULE_PARM_DESC(debug,"Turn on/off lgdt330x frontend debugging (default:off).");
@@ -68,6 +69,7 @@ struct lgdt330x_state
68 69
69 /* Demodulator private data */ 70 /* Demodulator private data */
70 fe_modulation_t current_modulation; 71 fe_modulation_t current_modulation;
72 u32 snr; /* Result of last SNR calculation */
71 73
72 /* Tuner private data */ 74 /* Tuner private data */
73 u32 current_frequency; 75 u32 current_frequency;
@@ -302,10 +304,10 @@ static int lgdt330x_set_parameters(struct dvb_frontend* fe,
302 static u8 lgdt3303_8vsb_44_data[] = { 304 static u8 lgdt3303_8vsb_44_data[] = {
303 0x04, 0x00, 305 0x04, 0x00,
304 0x0d, 0x40, 306 0x0d, 0x40,
305 0x0e, 0x87, 307 0x0e, 0x87,
306 0x0f, 0x8e, 308 0x0f, 0x8e,
307 0x10, 0x01, 309 0x10, 0x01,
308 0x47, 0x8b }; 310 0x47, 0x8b };
309 311
310 /* 312 /*
311 * Array of byte pairs <address, value> 313 * Array of byte pairs <address, value>
@@ -435,9 +437,6 @@ static int lgdt3302_read_status(struct dvb_frontend* fe, fe_status_t* status)
435 /* Test signal does not exist flag */ 437 /* Test signal does not exist flag */
436 /* as well as the AGC lock flag. */ 438 /* as well as the AGC lock flag. */
437 *status |= FE_HAS_SIGNAL; 439 *status |= FE_HAS_SIGNAL;
438 } else {
439 /* Without a signal all other status bits are meaningless */
440 return 0;
441 } 440 }
442 441
443 /* 442 /*
@@ -500,9 +499,6 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
500 /* Test input signal does not exist flag */ 499 /* Test input signal does not exist flag */
501 /* as well as the AGC lock flag. */ 500 /* as well as the AGC lock flag. */
502 *status |= FE_HAS_SIGNAL; 501 *status |= FE_HAS_SIGNAL;
503 } else {
504 /* Without a signal all other status bits are meaningless */
505 return 0;
506 } 502 }
507 503
508 /* Carrier Recovery Lock Status Register */ 504 /* Carrier Recovery Lock Status Register */
@@ -543,151 +539,150 @@ static int lgdt3303_read_status(struct dvb_frontend* fe, fe_status_t* status)
543 return 0; 539 return 0;
544} 540}
545 541
546static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength) 542/* Calculate SNR estimation (scaled by 2^24)
543
544 8-VSB SNR equations from LGDT3302 and LGDT3303 datasheets, QAM
545 equations from LGDT3303 datasheet. VSB is the same between the '02
546 and '03, so maybe QAM is too? Perhaps someone with a newer datasheet
547 that has QAM information could verify?
548
549 For 8-VSB: (two ways, take your pick)
550 LGDT3302:
551 SNR_EQ = 10 * log10(25 * 24^2 / EQ_MSE)
552 LGDT3303:
553 SNR_EQ = 10 * log10(25 * 32^2 / EQ_MSE)
554 LGDT3302 & LGDT3303:
555 SNR_PT = 10 * log10(25 * 32^2 / PT_MSE) (we use this one)
556 For 64-QAM:
557 SNR = 10 * log10( 688128 / MSEQAM)
558 For 256-QAM:
559 SNR = 10 * log10( 696320 / MSEQAM)
560
561 We re-write the snr equation as:
562 SNR * 2^24 = 10*(c - intlog10(MSE))
563 Where for 256-QAM, c = log10(696320) * 2^24, and so on. */
564
565static u32 calculate_snr(u32 mse, u32 c)
547{ 566{
548 /* not directly available. */ 567 if (mse == 0) /* No signal */
549 *strength = 0; 568 return 0;
550 return 0; 569
570 mse = intlog10(mse);
571 if (mse > c) {
572 /* Negative SNR, which is possible, but realisticly the
573 demod will lose lock before the signal gets this bad. The
574 API only allows for unsigned values, so just return 0 */
575 return 0;
576 }
577 return 10*(c - mse);
551} 578}
552 579
553static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr) 580static int lgdt3302_read_snr(struct dvb_frontend* fe, u16* snr)
554{ 581{
555#ifdef SNR_IN_DB
556 /*
557 * Spec sheet shows formula for SNR_EQ = 10 log10(25 * 24**2 / noise)
558 * and SNR_PH = 10 log10(25 * 32**2 / noise) for equalizer and phase tracker
559 * respectively. The following tables are built on these formulas.
560 * The usual definition is SNR = 20 log10(signal/noise)
561 * If the specification is wrong the value retuned is 1/2 the actual SNR in db.
562 *
563 * This table is a an ordered list of noise values computed by the
564 * formula from the spec sheet such that the index into the table
565 * starting at 43 or 45 is the SNR value in db. There are duplicate noise
566 * value entries at the beginning because the SNR varies more than
567 * 1 db for a change of 1 digit in noise at very small values of noise.
568 *
569 * Examples from SNR_EQ table:
570 * noise SNR
571 * 0 43
572 * 1 42
573 * 2 39
574 * 3 37
575 * 4 36
576 * 5 35
577 * 6 34
578 * 7 33
579 * 8 33
580 * 9 32
581 * 10 32
582 * 11 31
583 * 12 31
584 * 13 30
585 */
586
587 static const u32 SNR_EQ[] =
588 { 1, 2, 2, 2, 3, 3, 4, 4, 5, 7,
589 9, 11, 13, 17, 21, 26, 33, 41, 52, 65,
590 81, 102, 129, 162, 204, 257, 323, 406, 511, 644,
591 810, 1020, 1284, 1616, 2035, 2561, 3224, 4059, 5110, 6433,
592 8098, 10195, 12835, 16158, 20341, 25608, 32238, 40585, 51094, 64323,
593 80978, 101945, 128341, 161571, 203406, 256073, 0x40000
594 };
595
596 static const u32 SNR_PH[] =
597 { 1, 2, 2, 2, 3, 3, 4, 5, 6, 8,
598 10, 12, 15, 19, 23, 29, 37, 46, 58, 73,
599 91, 115, 144, 182, 229, 288, 362, 456, 574, 722,
600 909, 1144, 1440, 1813, 2282, 2873, 3617, 4553, 5732, 7216,
601 9084, 11436, 14396, 18124, 22817, 28724, 36161, 45524, 57312, 72151,
602 90833, 114351, 143960, 181235, 228161, 0x080000
603 };
604
605 static u8 buf[5];/* read data buffer */
606 static u32 noise; /* noise value */
607 static u32 snr_db; /* index into SNR_EQ[] */
608 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; 582 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
583 u8 buf[5]; /* read data buffer */
584 u32 noise; /* noise value */
585 u32 c; /* per-modulation SNR calculation constant */
609 586
610 /* read both equalizer and phase tracker noise data */ 587 switch(state->current_modulation) {
611 i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf)); 588 case VSB_8:
612 589 i2c_read_demod_bytes(state, LGDT3302_EQPH_ERR0, buf, 5);
613 if (state->current_modulation == VSB_8) { 590#ifdef USE_EQMSE
614 /* Equalizer Mean-Square Error Register for VSB */ 591 /* Use Equalizer Mean-Square Error Register */
592 /* SNR for ranges from -15.61 to +41.58 */
615 noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2]; 593 noise = ((buf[0] & 7) << 16) | (buf[1] << 8) | buf[2];
616 594 c = 69765745; /* log10(25*24^2)*2^24 */
617 /*
618 * Look up noise value in table.
619 * A better search algorithm could be used...
620 * watch out there are duplicate entries.
621 */
622 for (snr_db = 0; snr_db < sizeof(SNR_EQ); snr_db++) {
623 if (noise < SNR_EQ[snr_db]) {
624 *snr = 43 - snr_db;
625 break;
626 }
627 }
628 } else {
629 /* Phase Tracker Mean-Square Error Register for QAM */
630 noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
631
632 /* Look up noise value in table. */
633 for (snr_db = 0; snr_db < sizeof(SNR_PH); snr_db++) {
634 if (noise < SNR_PH[snr_db]) {
635 *snr = 45 - snr_db;
636 break;
637 }
638 }
639 }
640#else 595#else
641 /* Return the raw noise value */ 596 /* Use Phase Tracker Mean-Square Error Register */
642 static u8 buf[5];/* read data buffer */ 597 /* SNR for ranges from -13.11 to +44.08 */
643 static u32 noise; /* noise value */
644 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
645
646 /* read both equalizer and pase tracker noise data */
647 i2c_read_demod_bytes(state, EQPH_ERR0, buf, sizeof(buf));
648
649 if (state->current_modulation == VSB_8) {
650 /* Phase Tracker Mean-Square Error Register for VSB */
651 noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4]; 598 noise = ((buf[0] & 7<<3) << 13) | (buf[3] << 8) | buf[4];
652 } else { 599 c = 73957994; /* log10(25*32^2)*2^24 */
653 600#endif
654 /* Carrier Recovery Mean-Square Error for QAM */ 601 break;
655 i2c_read_demod_bytes(state, 0x1a, buf, 2); 602 case QAM_64:
603 case QAM_256:
604 i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2);
656 noise = ((buf[0] & 3) << 8) | buf[1]; 605 noise = ((buf[0] & 3) << 8) | buf[1];
606 c = state->current_modulation == QAM_64 ? 97939837 : 98026066;
607 /* log10(688128)*2^24 and log10(696320)*2^24 */
608 break;
609 default:
610 printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
611 __FUNCTION__);
612 return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
657 } 613 }
658 614
659 /* Small values for noise mean signal is better so invert noise */ 615 state->snr = calculate_snr(noise, c);
660 *snr = ~noise; 616 *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
661#endif
662 617
663 dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr); 618 dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
619 state->snr >> 24, (((state->snr>>8) & 0xffff) * 100) >> 16);
664 620
665 return 0; 621 return 0;
666} 622}
667 623
668static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr) 624static int lgdt3303_read_snr(struct dvb_frontend* fe, u16* snr)
669{ 625{
670 /* Return the raw noise value */
671 static u8 buf[5];/* read data buffer */
672 static u32 noise; /* noise value */
673 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv; 626 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
627 u8 buf[5]; /* read data buffer */
628 u32 noise; /* noise value */
629 u32 c; /* per-modulation SNR calculation constant */
674 630
675 if (state->current_modulation == VSB_8) { 631 switch(state->current_modulation) {
676 632 case VSB_8:
677 i2c_read_demod_bytes(state, 0x6e, buf, 5); 633 i2c_read_demod_bytes(state, LGDT3303_EQPH_ERR0, buf, 5);
678 /* Phase Tracker Mean-Square Error Register for VSB */ 634#ifdef USE_EQMSE
635 /* Use Equalizer Mean-Square Error Register */
636 /* SNR for ranges from -16.12 to +44.08 */
637 noise = ((buf[0] & 0x78) << 13) | (buf[1] << 8) | buf[2];
638 c = 73957994; /* log10(25*32^2)*2^24 */
639#else
640 /* Use Phase Tracker Mean-Square Error Register */
641 /* SNR for ranges from -13.11 to +44.08 */
679 noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4]; 642 noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
680 } else { 643 c = 73957994; /* log10(25*32^2)*2^24 */
681 644#endif
682 /* Carrier Recovery Mean-Square Error for QAM */ 645 break;
683 i2c_read_demod_bytes(state, 0x1a, buf, 2); 646 case QAM_64:
647 case QAM_256:
648 i2c_read_demod_bytes(state, CARRIER_MSEQAM1, buf, 2);
684 noise = (buf[0] << 8) | buf[1]; 649 noise = (buf[0] << 8) | buf[1];
650 c = state->current_modulation == QAM_64 ? 97939837 : 98026066;
651 /* log10(688128)*2^24 and log10(696320)*2^24 */
652 break;
653 default:
654 printk(KERN_ERR "lgdt330x: %s: Modulation set to unsupported value\n",
655 __FUNCTION__);
656 return -EREMOTEIO; /* return -EDRIVER_IS_GIBBERED; */
685 } 657 }
686 658
687 /* Small values for noise mean signal is better so invert noise */ 659 state->snr = calculate_snr(noise, c);
688 *snr = ~noise; 660 *snr = (state->snr) >> 16; /* Convert from 8.24 fixed-point to 8.8 */
661
662 dprintk("%s: noise = 0x%08x, snr = %d.%02d dB\n", __FUNCTION__, noise,
663 state->snr >> 24, (((state->snr >> 8) & 0xffff) * 100) >> 16);
664
665 return 0;
666}
667
668static int lgdt330x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
669{
670 /* Calculate Strength from SNR up to 35dB */
671 /* Even though the SNR can go higher than 35dB, there is some comfort */
672 /* factor in having a range of strong signals that can show at 100% */
673 struct lgdt330x_state* state = (struct lgdt330x_state*) fe->demodulator_priv;
674 u16 snr;
675 int ret;
689 676
690 dprintk("%s: noise = 0x%05x, snr = %idb\n",__FUNCTION__, noise, *snr); 677 ret = fe->ops.read_snr(fe, &snr);
678 if (ret != 0)
679 return ret;
680 /* Rather than use the 8.8 value snr, use state->snr which is 8.24 */
681 /* scale the range 0 - 35*2^24 into 0 - 65535 */
682 if (state->snr >= 8960 * 0x10000)
683 *strength = 0xffff;
684 else
685 *strength = state->snr / 8960;
691 686
692 return 0; 687 return 0;
693} 688}