From f1b1eabff0eb3fc46b06668de8174c0f23b271fd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 5 Jul 2018 18:59:36 -0400 Subject: media: dvb: represent min/max/step/tolerance freqs in Hz Right now, satellite frontend drivers specify frequencies in kHz, while terrestrial/cable ones specify in Hz. That's confusing for developers. However, the main problem is that universal frontends capable of handling both satellite and non-satelite delivery systems are appearing. We end by needing to hack the drivers in order to support such hybrid frontends. So, convert everything to specify frontend frequencies in Hz. Tested-by: Katsuhiro Suzuki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb-core/dvb_frontend.c | 84 ++++++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 25 deletions(-) (limited to 'drivers/media/dvb-core/dvb_frontend.c') diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index 75e95b56f8b3..fe0fae482ba4 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -894,11 +894,28 @@ static int dvb_frontend_start(struct dvb_frontend *fe) } static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe, - u32 *freq_min, u32 *freq_max) + u32 *freq_min, u32 *freq_max, + u32 *tolerance) { struct dtv_frontend_properties *c = &fe->dtv_property_cache; - __u32 tuner_min = fe->ops.tuner_ops.info.frequency_min_hz; - __u32 tuner_max = fe->ops.tuner_ops.info.frequency_max_hz; + u32 tuner_min = fe->ops.tuner_ops.info.frequency_min_hz; + u32 tuner_max = fe->ops.tuner_ops.info.frequency_max_hz; + u32 frontend_min = fe->ops.info.frequency_min_hz; + u32 frontend_max = fe->ops.info.frequency_max_hz; + + *freq_min = max(frontend_min, tuner_min); + + if (frontend_max == 0) + *freq_max = tuner_max; + else if (tuner_max == 0) + *freq_max = frontend_max; + else + *freq_max = min(frontend_max, tuner_max); + + if (*freq_min == 0 || *freq_max == 0) + dev_warn(fe->dvb->device, + "DVB: adapter %i frontend %u frequency limits undefined - fix the driver\n", + fe->dvb->num, fe->id); /* If the standard is for satellite, convert frequencies to kHz */ switch (c->delivery_system) { @@ -906,26 +923,35 @@ static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe, case SYS_DVBS2: case SYS_TURBO: case SYS_ISDBS: - tuner_max /= kHz; - tuner_min /= kHz; + *freq_min /= kHz; + *freq_max /= kHz; + if (tolerance) + *tolerance = fe->ops.info.frequency_tolerance_hz / kHz; + break; default: + if (tolerance) + *tolerance = fe->ops.info.frequency_tolerance_hz; break; } +} - *freq_min = max(fe->ops.info.frequency_min, tuner_min); - - if (fe->ops.info.frequency_max == 0) - *freq_max = tuner_max; - else if (tuner_max == 0) - *freq_max = fe->ops.info.frequency_max; - else - *freq_max = min(fe->ops.info.frequency_max, tuner_max); +static u32 dvb_frontend_get_stepsize(struct dvb_frontend *fe) +{ + struct dtv_frontend_properties *c = &fe->dtv_property_cache; + u32 step = fe->ops.info.frequency_stepsize_hz; + switch (c->delivery_system) { + case SYS_DVBS: + case SYS_DVBS2: + case SYS_TURBO: + case SYS_ISDBS: + step /= kHz; + break; + default: + break; + } - if (*freq_min == 0 || *freq_max == 0) - dev_warn(fe->dvb->device, - "DVB: adapter %i frontend %u frequency limits undefined - fix the driver\n", - fe->dvb->num, fe->id); + return step; } static int dvb_frontend_check_parameters(struct dvb_frontend *fe) @@ -935,7 +961,7 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe) u32 freq_max; /* range check: frequency */ - dvb_frontend_get_frequency_limits(fe, &freq_min, &freq_max); + dvb_frontend_get_frequency_limits(fe, &freq_min, &freq_max, NULL); if ((freq_min && c->frequency < freq_min) || (freq_max && c->frequency > freq_max)) { dev_warn(fe->dvb->device, "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n", @@ -2261,8 +2287,8 @@ static int dtv_set_frontend(struct dvb_frontend *fe) case SYS_ISDBT: case SYS_DTMB: fepriv->min_delay = HZ / 20; - fepriv->step_size = fe->ops.info.frequency_stepsize * 2; - fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1; + fepriv->step_size = dvb_frontend_get_stepsize(fe) * 2; + fepriv->max_drift = (dvb_frontend_get_stepsize(fe) * 2) + 1; break; default: /* @@ -2391,9 +2417,17 @@ static int dvb_frontend_handle_ioctl(struct file *file, case FE_GET_INFO: { struct dvb_frontend_info *info = parg; - - memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info)); - dvb_frontend_get_frequency_limits(fe, &info->frequency_min, &info->frequency_max); + memset(info, 0, sizeof(*info)); + + strcpy(info->name, fe->ops.info.name); + info->symbol_rate_min = fe->ops.info.symbol_rate_min; + info->symbol_rate_max = fe->ops.info.symbol_rate_max; + info->symbol_rate_tolerance = fe->ops.info.symbol_rate_tolerance; + info->caps = fe->ops.info.caps; + info->frequency_stepsize = dvb_frontend_get_stepsize(fe); + dvb_frontend_get_frequency_limits(fe, &info->frequency_min, + &info->frequency_max, + &info->frequency_tolerance); /* * Associate the 4 delivery systems supported by DVBv3 @@ -2423,10 +2457,10 @@ static int dvb_frontend_handle_ioctl(struct file *file, dev_err(fe->dvb->device, "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n", __func__, c->delivery_system); - fe->ops.info.type = FE_OFDM; + info->type = FE_OFDM; } dev_dbg(fe->dvb->device, "%s: current delivery system on cache: %d, V3 type: %d\n", - __func__, c->delivery_system, fe->ops.info.type); + __func__, c->delivery_system, info->type); /* Set CAN_INVERSION_AUTO bit on in other than oneshot mode */ if (!(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) -- cgit