diff options
author | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2013-12-16 17:10:59 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2013-12-19 05:17:45 -0500 |
commit | 6ef06e78c74cc4b2f45ea2e9adbe6d52cd246a6b (patch) | |
tree | 87732e7ebcc29f57ce464e8848bd43947a0af8bf /drivers/media/dvb-frontends/dib8000.c | |
parent | 51fea113429115977be274b0c3f8937bcc3eeae3 (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.c | 142 |
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 | ||
129 | enum dib8000_power_mode { | 131 | enum 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 | ||
988 | static 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 | |||
986 | static int dib8000_reset(struct dvb_frontend *fe) | 1014 | static 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 | ||
3689 | static int dib8000_get_stats(struct dvb_frontend *fe, fe_status_t stat); | ||
3690 | |||
3657 | static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat) | 3691 | static 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 | ||
3835 | struct per_layer_regs { | ||
3836 | u16 lock, ber, per; | ||
3837 | }; | ||
3838 | |||
3839 | static const struct per_layer_regs per_layer_regs[] = { | ||
3840 | { 554, 560, 562 }, | ||
3841 | { 555, 576, 578 }, | ||
3842 | { 556, 581, 583 }, | ||
3843 | }; | ||
3844 | |||
3845 | static 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 | |||
3800 | int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave) | 3940 | int 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; |