[media] dib7000p: avoid division by zero
dib7000p_read_word() may return zero on i2c errors, resulting in dib7000p_get_internal_freq() returning zero. So don't divide by the result of dib7000p_get_internal_freq() without checking it for zero in dib7000p_set_dds(). On one of my machines the device ID 2304:0229 Pinnacle Systems, Inc. PCTV Dual DVB-T 2001e about once a day/every two days gets into a state, where most (all?) I2C reads return with an error. Tuning during this state will result in a divide by zero without this patch. This patch doesn't fix the root cause for the device getting into a bad state, but it allows me to unload/reload the drivers, bringing it back into a usable state. Signed-off-by: Martin Wache <M.Wache@gmx.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:
parent
5610ced4f1
commit
5332b62637
1 changed files with 12 additions and 3 deletions
|
@ -805,13 +805,19 @@ static int dib7000p_set_agc_config(struct dib7000p_state *state, u8 band)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void dib7000p_set_dds(struct dib7000p_state *state, s32 offset_khz)
|
||||
static int dib7000p_set_dds(struct dib7000p_state *state, s32 offset_khz)
|
||||
{
|
||||
u32 internal = dib7000p_get_internal_freq(state);
|
||||
s32 unit_khz_dds_val = 67108864 / (internal); /* 2**26 / Fsampling is the unit 1KHz offset */
|
||||
s32 unit_khz_dds_val;
|
||||
u32 abs_offset_khz = ABS(offset_khz);
|
||||
u32 dds = state->cfg.bw->ifreq & 0x1ffffff;
|
||||
u8 invert = !!(state->cfg.bw->ifreq & (1 << 25));
|
||||
if (internal == 0) {
|
||||
pr_warn("DIB7000P: dib7000p_get_internal_freq returned 0\n");
|
||||
return -1;
|
||||
}
|
||||
/* 2**26 / Fsampling is the unit 1KHz offset */
|
||||
unit_khz_dds_val = 67108864 / (internal);
|
||||
|
||||
dprintk("setting a frequency offset of %dkHz internal freq = %d invert = %d\n", offset_khz, internal, invert);
|
||||
|
||||
|
@ -828,6 +834,7 @@ static void dib7000p_set_dds(struct dib7000p_state *state, s32 offset_khz)
|
|||
dib7000p_write_word(state, 21, (u16) (((dds >> 16) & 0x1ff) | (0 << 10) | (invert << 9)));
|
||||
dib7000p_write_word(state, 22, (u16) (dds & 0xffff));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dib7000p_agc_startup(struct dvb_frontend *demod)
|
||||
|
@ -867,7 +874,9 @@ static int dib7000p_agc_startup(struct dvb_frontend *demod)
|
|||
frequency_offset = (s32)frequency_tuner / 1000 - ch->frequency / 1000;
|
||||
}
|
||||
|
||||
dib7000p_set_dds(state, frequency_offset);
|
||||
if (dib7000p_set_dds(state, frequency_offset) < 0)
|
||||
return -1;
|
||||
|
||||
ret = 7;
|
||||
(*agc_state)++;
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue