aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorMiroslav Slugen <thunder.mmm@gmail.com>2011-12-20 19:18:38 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-01-16 09:23:15 -0500
commit8a538a8855aa95e5a12ae232a140e6b30c56d0c5 (patch)
tree8a2d55244d7ba6ebeb65e308f8269742a59195f9 /drivers/media
parentcd4ca7afc61d3b18fcd635002459fb6b1d701099 (diff)
[media] xc4000: add support for signal strength measures
In xc4000 chipsets real signal and noise level is stored in register 0x0A and 0x0B,so we can use those registers to monitor signal strength. I tested this patch on 2 different cards Leadtek DVR3200 and DTV2000H Plus, both with same results, I used special antenna hubs (toner 4x, 6x, 8x and 12x) with mesured signal lost, both registers are in dB value, first represent signal with limit value -113.5dB (should be -114dB) and exactly match with test results. Second represents noise level also in dB and there is no maximum value, but from tests we can drop everything above 32dB which tuner realy can't use, signal was usable till 20dB noise level. In digital mode we can take signal strength but sadly noise level is not relevant and real value is stored in demodulator for now just zl10353, also digital mode is just for testing, because it needs changing other parts of code which reads data only from demodulator. In analog mode I was able to test only FM radio, signal level is not important, it says something about cable and hub losts, but nothing about real quality of reception, so even if we have signal level at minimum 113dB we can still here radio, because of that it is displaied only in debug mode, but for real signal level is used noise register which is again very accurate, radio noise level was betwen 6-20dB for good signal, 20-25dB for medium signal, and above 25dB signal is unusable. For now real benefit of this patch is only for FM radio mode. Signed-off-by: Miroslav Slugen <thunder.mmm@gmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/common/tuners/xc4000.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/drivers/media/common/tuners/xc4000.c b/drivers/media/common/tuners/xc4000.c
index d218c1d68c33..68397110b7d9 100644
--- a/drivers/media/common/tuners/xc4000.c
+++ b/drivers/media/common/tuners/xc4000.c
@@ -154,6 +154,8 @@ struct xc4000_priv {
154#define XREG_SNR 0x06 154#define XREG_SNR 0x06
155#define XREG_VERSION 0x07 155#define XREG_VERSION 0x07
156#define XREG_PRODUCT_ID 0x08 156#define XREG_PRODUCT_ID 0x08
157#define XREG_SIGNAL_LEVEL 0x0A
158#define XREG_NOISE_LEVEL 0x0B
157 159
158/* 160/*
159 Basic firmware description. This will remain with 161 Basic firmware description. This will remain with
@@ -486,6 +488,16 @@ static int xc_get_quality(struct xc4000_priv *priv, u16 *quality)
486 return xc4000_readreg(priv, XREG_QUALITY, quality); 488 return xc4000_readreg(priv, XREG_QUALITY, quality);
487} 489}
488 490
491static int xc_get_signal_level(struct xc4000_priv *priv, u16 *signal)
492{
493 return xc4000_readreg(priv, XREG_SIGNAL_LEVEL, signal);
494}
495
496static int xc_get_noise_level(struct xc4000_priv *priv, u16 *noise)
497{
498 return xc4000_readreg(priv, XREG_NOISE_LEVEL, noise);
499}
500
489static u16 xc_wait_for_lock(struct xc4000_priv *priv) 501static u16 xc_wait_for_lock(struct xc4000_priv *priv)
490{ 502{
491 u16 lock_state = 0; 503 u16 lock_state = 0;
@@ -1089,6 +1101,8 @@ static void xc_debug_dump(struct xc4000_priv *priv)
1089 u32 hsync_freq_hz = 0; 1101 u32 hsync_freq_hz = 0;
1090 u16 frame_lines; 1102 u16 frame_lines;
1091 u16 quality; 1103 u16 quality;
1104 u16 signal = 0;
1105 u16 noise = 0;
1092 u8 hw_majorversion = 0, hw_minorversion = 0; 1106 u8 hw_majorversion = 0, hw_minorversion = 0;
1093 u8 fw_majorversion = 0, fw_minorversion = 0; 1107 u8 fw_majorversion = 0, fw_minorversion = 0;
1094 1108
@@ -1119,6 +1133,12 @@ static void xc_debug_dump(struct xc4000_priv *priv)
1119 1133
1120 xc_get_quality(priv, &quality); 1134 xc_get_quality(priv, &quality);
1121 dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality); 1135 dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
1136
1137 xc_get_signal_level(priv, &signal);
1138 dprintk(1, "*** Signal level = -%ddB (%d)\n", signal >> 8, signal);
1139
1140 xc_get_noise_level(priv, &noise);
1141 dprintk(1, "*** Noise level = %ddB (%d)\n", noise >> 8, noise);
1122} 1142}
1123 1143
1124static int xc4000_set_params(struct dvb_frontend *fe) 1144static int xc4000_set_params(struct dvb_frontend *fe)
@@ -1432,6 +1452,71 @@ fail:
1432 return ret; 1452 return ret;
1433} 1453}
1434 1454
1455static int xc4000_get_signal(struct dvb_frontend *fe, u16 *strength)
1456{
1457 struct xc4000_priv *priv = fe->tuner_priv;
1458 u16 value = 0;
1459 int rc;
1460
1461 mutex_lock(&priv->lock);
1462 rc = xc4000_readreg(priv, XREG_SIGNAL_LEVEL, &value);
1463 mutex_unlock(&priv->lock);
1464
1465 if (rc < 0)
1466 goto ret;
1467
1468 /* Informations from real testing of DVB-T and radio part,
1469 coeficient for one dB is 0xff.
1470 */
1471 tuner_dbg("Signal strength: -%ddB (%05d)\n", value >> 8, value);
1472
1473 /* all known digital modes */
1474 if ((priv->video_standard == XC4000_DTV6) ||
1475 (priv->video_standard == XC4000_DTV7) ||
1476 (priv->video_standard == XC4000_DTV7_8) ||
1477 (priv->video_standard == XC4000_DTV8))
1478 goto digital;
1479
1480 /* Analog mode has NOISE LEVEL important, signal
1481 depends only on gain of antenna and amplifiers,
1482 but it doesn't tell anything about real quality
1483 of reception.
1484 */
1485 mutex_lock(&priv->lock);
1486 rc = xc4000_readreg(priv, XREG_NOISE_LEVEL, &value);
1487 mutex_unlock(&priv->lock);
1488
1489 tuner_dbg("Noise level: %ddB (%05d)\n", value >> 8, value);
1490
1491 /* highest noise level: 32dB */
1492 if (value >= 0x2000) {
1493 value = 0;
1494 } else {
1495 value = ~value << 3;
1496 }
1497
1498 goto ret;
1499
1500 /* Digital mode has SIGNAL LEVEL important and real
1501 noise level is stored in demodulator registers.
1502 */
1503digital:
1504 /* best signal: -50dB */
1505 if (value <= 0x3200) {
1506 value = 0xffff;
1507 /* minimum: -114dB - should be 0x7200 but real zero is 0x713A */
1508 } else if (value >= 0x713A) {
1509 value = 0;
1510 } else {
1511 value = ~(value - 0x3200) << 2;
1512 }
1513
1514ret:
1515 *strength = value;
1516
1517 return rc;
1518}
1519
1435static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq) 1520static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq)
1436{ 1521{
1437 struct xc4000_priv *priv = fe->tuner_priv; 1522 struct xc4000_priv *priv = fe->tuner_priv;
@@ -1559,6 +1644,7 @@ static const struct dvb_tuner_ops xc4000_tuner_ops = {
1559 .set_params = xc4000_set_params, 1644 .set_params = xc4000_set_params,
1560 .set_analog_params = xc4000_set_analog_params, 1645 .set_analog_params = xc4000_set_analog_params,
1561 .get_frequency = xc4000_get_frequency, 1646 .get_frequency = xc4000_get_frequency,
1647 .get_rf_strength = xc4000_get_signal,
1562 .get_bandwidth = xc4000_get_bandwidth, 1648 .get_bandwidth = xc4000_get_bandwidth,
1563 .get_status = xc4000_get_status 1649 .get_status = xc4000_get_status
1564}; 1650};