aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb-frontends/dib8000.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <m.chehab@samsung.com>2013-12-16 17:10:59 -0500
committerMauro Carvalho Chehab <m.chehab@samsung.com>2013-12-19 05:17:45 -0500
commit6ef06e78c74cc4b2f45ea2e9adbe6d52cd246a6b (patch)
tree87732e7ebcc29f57ce464e8848bd43947a0af8bf /drivers/media/dvb-frontends/dib8000.c
parent51fea113429115977be274b0c3f8937bcc3eeae3 (diff)
[media] dib8000: add DVBv5 stats
The advantage of DVBv5 stats is that it allows adding proper scales to all measures. use it for this frontend. This patch adds a basic set of stats, basically cloning what's already provided by DVBv3 API. Latter patches will improve it. Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com> Acked-by: Patrick Boettcher <pboettcher@kernellabs.com>
Diffstat (limited to 'drivers/media/dvb-frontends/dib8000.c')
-rw-r--r--drivers/media/dvb-frontends/dib8000.c142
1 files changed, 141 insertions, 1 deletions
diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c
index 13fdc3d5f762..2dbf89365a97 100644
--- a/drivers/media/dvb-frontends/dib8000.c
+++ b/drivers/media/dvb-frontends/dib8000.c
@@ -124,6 +124,8 @@ struct dib8000_state {
124 u16 agc2_max; 124 u16 agc2_max;
125 u16 agc2_min; 125 u16 agc2_min;
126#endif 126#endif
127
128 unsigned long get_stats_time;
127}; 129};
128 130
129enum dib8000_power_mode { 131enum dib8000_power_mode {
@@ -804,7 +806,7 @@ int dib8000_update_pll(struct dvb_frontend *fe,
804 dprintk("PLL: Update ratio (prediv: %d, ratio: %d)", state->cfg.pll->pll_prediv, ratio); 806 dprintk("PLL: Update ratio (prediv: %d, ratio: %d)", state->cfg.pll->pll_prediv, ratio);
805 dib8000_write_word(state, 901, (state->cfg.pll->pll_prediv << 8) | (ratio << 0)); /* only the PLL ratio is updated. */ 807 dib8000_write_word(state, 901, (state->cfg.pll->pll_prediv << 8) | (ratio << 0)); /* only the PLL ratio is updated. */
806 } 808 }
807} 809 }
808 810
809 return 0; 811 return 0;
810} 812}
@@ -983,6 +985,32 @@ static u16 dib8000_identify(struct i2c_device *client)
983 return value; 985 return value;
984} 986}
985 987
988static void dib8000_reset_stats(struct dvb_frontend *fe)
989{
990 struct dib8000_state *state = fe->demodulator_priv;
991 struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
992
993 memset(&c->strength, 0, sizeof(c->strength));
994 memset(&c->cnr, 0, sizeof(c->cnr));
995 memset(&c->post_bit_error, 0, sizeof(c->post_bit_error));
996 memset(&c->post_bit_count, 0, sizeof(c->post_bit_count));
997 memset(&c->block_error, 0, sizeof(c->block_error));
998
999 c->strength.len = 1;
1000 c->cnr.len = 1;
1001 c->block_error.len = 1;
1002 c->post_bit_error.len = 1;
1003 c->post_bit_count.len = 1;
1004
1005 c->strength.stat[0].scale = FE_SCALE_RELATIVE;
1006 c->strength.stat[0].uvalue = 0;
1007
1008 c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1009 c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1010 c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1011 c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
1012}
1013
986static int dib8000_reset(struct dvb_frontend *fe) 1014static int dib8000_reset(struct dvb_frontend *fe)
987{ 1015{
988 struct dib8000_state *state = fe->demodulator_priv; 1016 struct dib8000_state *state = fe->demodulator_priv;
@@ -1088,6 +1116,8 @@ static int dib8000_reset(struct dvb_frontend *fe)
1088 1116
1089 dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY); 1117 dib8000_set_power_mode(state, DIB8000_POWER_INTERFACE_ONLY);
1090 1118
1119 dib8000_reset_stats(fe);
1120
1091 return 0; 1121 return 0;
1092} 1122}
1093 1123
@@ -2983,6 +3013,8 @@ static int dib8000_tune(struct dvb_frontend *fe)
2983 3013
2984 switch (*tune_state) { 3014 switch (*tune_state) {
2985 case CT_DEMOD_START: /* 30 */ 3015 case CT_DEMOD_START: /* 30 */
3016 dib8000_reset_stats(fe);
3017
2986 if (state->revision == 0x8090) 3018 if (state->revision == 0x8090)
2987 dib8090p_init_sdram(state); 3019 dib8090p_init_sdram(state);
2988 state->status = FE_STATUS_TUNE_PENDING; 3020 state->status = FE_STATUS_TUNE_PENDING;
@@ -3654,6 +3686,8 @@ static int dib8000_set_frontend(struct dvb_frontend *fe)
3654 return 0; 3686 return 0;
3655} 3687}
3656 3688
3689static int dib8000_get_stats(struct dvb_frontend *fe, fe_status_t stat);
3690
3657static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat) 3691static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
3658{ 3692{
3659 struct dib8000_state *state = fe->demodulator_priv; 3693 struct dib8000_state *state = fe->demodulator_priv;
@@ -3691,6 +3725,7 @@ static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
3691 if (lock & 0x01) 3725 if (lock & 0x01)
3692 *stat |= FE_HAS_VITERBI; 3726 *stat |= FE_HAS_VITERBI;
3693 } 3727 }
3728 dib8000_get_stats(fe, *stat);
3694 3729
3695 return 0; 3730 return 0;
3696} 3731}
@@ -3797,6 +3832,111 @@ static int dib8000_read_snr(struct dvb_frontend *fe, u16 * snr)
3797 return 0; 3832 return 0;
3798} 3833}
3799 3834
3835struct per_layer_regs {
3836 u16 lock, ber, per;
3837};
3838
3839static const struct per_layer_regs per_layer_regs[] = {
3840 { 554, 560, 562 },
3841 { 555, 576, 578 },
3842 { 556, 581, 583 },
3843};
3844
3845static int dib8000_get_stats(struct dvb_frontend *fe, fe_status_t stat)
3846{
3847 struct dib8000_state *state = fe->demodulator_priv;
3848 struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
3849 int i, lock;
3850 u32 snr, val;
3851 u16 strength;
3852
3853 /* Get Signal strength */
3854 dib8000_read_signal_strength(fe, &strength);
3855 c->strength.stat[0].uvalue = strength;
3856
3857 /* Check if 1 second was elapsed */
3858 if (!time_after(jiffies, state->get_stats_time))
3859 return 0;
3860 state->get_stats_time = jiffies + msecs_to_jiffies(1000);
3861
3862 /* Get SNR */
3863 snr = dib8000_get_snr(fe);
3864 for (i = 1; i < MAX_NUMBER_OF_FRONTENDS; i++) {
3865 if (state->fe[i])
3866 snr += dib8000_get_snr(state->fe[i]);
3867 }
3868 snr = snr >> 16;
3869
3870 if (snr) {
3871 snr = 10 * intlog10(snr);
3872 snr = (1000L * snr) >> 24;
3873 } else {
3874 snr = 0;
3875 }
3876 c->cnr.stat[0].svalue = snr;
3877 c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
3878
3879 /* UCB/BER measures require lock */
3880 if (!(stat & FE_HAS_LOCK)) {
3881 c->block_error.len = 1;
3882 c->post_bit_error.len = 1;
3883 c->post_bit_count.len = 1;
3884 c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
3885 c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
3886 c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
3887 return 0;
3888 }
3889
3890 /* Get UCB and post-BER measures */
3891
3892 /* FIXME: need to check if 1.25e6 bits already passed */
3893 dib8000_read_ber(fe, &val);
3894 c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
3895 c->post_bit_error.stat[0].uvalue += val;
3896
3897 c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
3898 c->post_bit_count.stat[0].uvalue += 100000000;
3899
3900 /*
3901 * FIXME: this is refreshed on every second, but a time
3902 * drift between dib8000 and PC clock may cause troubles
3903 */
3904 dib8000_read_unc_blocks(fe, &val);
3905
3906 c->block_error.stat[0].scale = FE_SCALE_COUNTER;
3907 c->block_error.stat[0].uvalue += val;
3908
3909 if (state->revision < 0x8002)
3910 return 0;
3911
3912 c->block_error.len = 4;
3913 c->post_bit_error.len = 4;
3914 c->post_bit_count.len = 4;
3915
3916 for (i = 0; i < 3; i++) {
3917 lock = dib8000_read_word(state, per_layer_regs[i].lock);
3918 if (lock & 0x01) {
3919 /* FIXME: need to check if 1.25e6 bits already passed */
3920 val = dib8000_read_word(state, per_layer_regs[i].ber);
3921 c->post_bit_error.stat[1 + i].scale = FE_SCALE_COUNTER;
3922 c->post_bit_error.stat[1 + i].uvalue += val;
3923
3924 c->post_bit_count.stat[1 + i].scale = FE_SCALE_COUNTER;
3925 c->post_bit_count.stat[1 + i].uvalue += 100000000;
3926
3927 /*
3928 * FIXME: this is refreshed on every second, but a time
3929 * drift between dib8000 and PC clock may cause troubles
3930 */
3931 val = dib8000_read_word(state, per_layer_regs[i].per);
3932
3933 c->block_error.stat[1 + i].scale = FE_SCALE_COUNTER;
3934 c->block_error.stat[1 + i].uvalue += val;
3935 }
3936 }
3937 return 0;
3938}
3939
3800int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave) 3940int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
3801{ 3941{
3802 struct dib8000_state *state = fe->demodulator_priv; 3942 struct dib8000_state *state = fe->demodulator_priv;