From 4d8317876d5f53ef792e90f89d8f162d7bca5c81 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 27 Sep 2009 14:05:12 -0300 Subject: V4L/DVB (13107): tda18271: fix overflow in FM radio frequency calculation Multiplication by 62500 causes an overflow in the 32 bit freq variable, which is later divided by 1000 when using FM radio. This patch prevents the overflow by scaling the frequency value correctly upfront. Thanks to Henk Vergonet for spotting the problem and providing a preliminary patch, which this changeset was based upon. Cc: Henk Vergonet Signed-off-by: Michael Krufky CC: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18271-fe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/common') diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index 64595112000..cccaf164a8f 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -1000,12 +1000,12 @@ static int tda18271_set_analog_params(struct dvb_frontend *fe, struct tda18271_std_map_item *map; char *mode; int ret; - u32 freq = params->frequency * 62500; + u32 freq = params->frequency * 125 * + ((params->mode == V4L2_TUNER_RADIO) ? 1 : 1000) / 2; priv->mode = TDA18271_ANALOG; if (params->mode == V4L2_TUNER_RADIO) { - freq = freq / 1000; map = &std_map->fm_radio; mode = "fm"; } else if (params->std & V4L2_STD_MN) { -- cgit v1.2.3 From a57c1dcb93e43357ed3f666e5a2b5d5071dd3930 Mon Sep 17 00:00:00 2001 From: Seth Barry Date: Sun, 27 Sep 2009 16:42:29 -0300 Subject: V4L/DVB (13109): tda18271: fix signedness issue in tda18271_rf_tracking_filters_init While having tda18271 module set with debug=17 (cal & info prints) and cal=0 (delay calibration process until first use) - I discovered that during the calibration process, if the frequency test for 69750000 returned a bcal of 0 (see tda18721-fe.c in tda18271_powerscan func) that the tuner wouldn't be able to pickup any of the frequencies in the range (all the other frequencies bands returned bcal=1). I spent some time going over the code and the NXP's tda18271 spec (ver.4 of it i think) and adding a lot of debug prints and walking/stepping through the calibration process. I found that when the powerscan fails to find a frequency, the rf calibration is not run and the default value is supposed to be used in its place (pulled from the RF_CAL_map table) - but something was getting goofed up there. Now, my c coding skills are very rusty, but i think root of the problem is a signedness issue with the math operation for calculating the rf_a1 and rf_a2 values in tda18271_rf_tracking_filters_init func, which results in values like 20648 for rf_a1 (when it should probably have a value like 0, or so slightly negative that it should be zero - this bad value for rf_a1 would in turn makes the approx calc within tda18271c2_rf_tracking_filters_correction go out of whack). The simplest solution i found was to explicitly convert the signedness of the denominator to avoid the implicit conversion. The values placed into the u32 rf_freq array should never exceed about 900mhz, so i think the s32 max value shouldn't be an issue in this case. I've tested it out a little, and even when i get a bcal=0 with the modified code, the default calibration value gets used, rf_a1 is zero, and the tuner seems to lock on the stream and mythtv seems to play it fine. Signed-off-by: Seth Barry Signed-off-by: Michael Krufky CC: stable@kernel.org Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18271-fe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/media/common') diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index cccaf164a8f..3a50ce96fcb 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -616,13 +616,13 @@ static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq) case RF2: map[i].rf_a1 = (prog_cal[RF2] - prog_tab[RF2] - prog_cal[RF1] + prog_tab[RF1]) / - ((rf_freq[RF2] - rf_freq[RF1]) / 1000); + (s32)((rf_freq[RF2] - rf_freq[RF1]) / 1000); map[i].rf2 = rf_freq[RF2] / 1000; break; case RF3: map[i].rf_a2 = (prog_cal[RF3] - prog_tab[RF3] - prog_cal[RF2] + prog_tab[RF2]) / - ((rf_freq[RF3] - rf_freq[RF2]) / 1000); + (s32)((rf_freq[RF3] - rf_freq[RF2]) / 1000); map[i].rf_b2 = prog_cal[RF2] - prog_tab[RF2]; map[i].rf3 = rf_freq[RF3] / 1000; break; -- cgit v1.2.3