[media] dvb_frontend: Fix DVBv3 emulation
For frontends with ISDB-T, DVB-T2, CMDBTH, etc, some code is needed, in order to provide emulation. Add such code, and check if the desired delivery system is supported by the frontend. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
@@ -1422,6 +1422,139 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
|
|||||||
|
|
||||||
static int dtv_set_frontend(struct dvb_frontend *fe);
|
static int dtv_set_frontend(struct dvb_frontend *fe);
|
||||||
|
|
||||||
|
static bool is_dvbv3_delsys(u32 delsys)
|
||||||
|
{
|
||||||
|
bool status;
|
||||||
|
|
||||||
|
status = (delsys == SYS_DVBT) || (delsys == SYS_DVBC_ANNEX_A) ||
|
||||||
|
(delsys == SYS_DVBS) || (delsys == SYS_ATSC);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
|
||||||
|
{
|
||||||
|
int ncaps, i;
|
||||||
|
u32 delsys = SYS_UNDEFINED;
|
||||||
|
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||||
|
enum dvbv3_emulation_type type;
|
||||||
|
|
||||||
|
if (desired_system == SYS_UNDEFINED) {
|
||||||
|
/*
|
||||||
|
* A DVBv3 call doesn't know what's the desired system.
|
||||||
|
* So, don't change the current delivery system. Instead,
|
||||||
|
* find the closest DVBv3 system that matches the delivery
|
||||||
|
* system.
|
||||||
|
*/
|
||||||
|
if (is_dvbv3_delsys(c->delivery_system)) {
|
||||||
|
dprintk("%s() Using delivery system to %d\n",
|
||||||
|
__func__, c->delivery_system);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
type = dvbv3_type(c->delivery_system);
|
||||||
|
switch (type) {
|
||||||
|
case DVBV3_QPSK:
|
||||||
|
desired_system = FE_QPSK;
|
||||||
|
break;
|
||||||
|
case DVBV3_QAM:
|
||||||
|
desired_system = FE_QAM;
|
||||||
|
break;
|
||||||
|
case DVBV3_ATSC:
|
||||||
|
desired_system = FE_ATSC;
|
||||||
|
break;
|
||||||
|
case DVBV3_OFDM:
|
||||||
|
desired_system = FE_OFDM;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dprintk("%s(): This frontend doesn't support DVBv3 calls\n",
|
||||||
|
__func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
delsys = c->delivery_system;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Check if the desired delivery system is supported
|
||||||
|
*/
|
||||||
|
ncaps = 0;
|
||||||
|
while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
|
||||||
|
if (fe->ops.delsys[ncaps] == desired_system) {
|
||||||
|
c->delivery_system = desired_system;
|
||||||
|
dprintk("%s() Changing delivery system to %d\n",
|
||||||
|
__func__, desired_system);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type = dvbv3_type(desired_system);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The delivery system is not supported. See if it can be
|
||||||
|
* emulated.
|
||||||
|
* The emulation only works if the desired system is one of the
|
||||||
|
* DVBv3 delivery systems
|
||||||
|
*/
|
||||||
|
if (!is_dvbv3_delsys(desired_system)) {
|
||||||
|
dprintk("%s() can't use a DVBv3 FE_SET_FRONTEND call on this frontend\n",
|
||||||
|
__func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the last non-DVBv3 delivery system that has the same type
|
||||||
|
* of the desired system
|
||||||
|
*/
|
||||||
|
ncaps = 0;
|
||||||
|
while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
|
||||||
|
if ((dvbv3_type(fe->ops.delsys[ncaps]) == type) &&
|
||||||
|
!is_dvbv3_delsys(fe->ops.delsys[ncaps]))
|
||||||
|
delsys = fe->ops.delsys[ncaps];
|
||||||
|
ncaps++;
|
||||||
|
}
|
||||||
|
/* There's nothing compatible with the desired delivery system */
|
||||||
|
if (delsys == SYS_UNDEFINED) {
|
||||||
|
dprintk("%s() Incompatible DVBv3 FE_SET_FRONTEND call for this frontend\n",
|
||||||
|
__func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
c->delivery_system = delsys;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Emulate newer delivery systems like ISDBT, DVBT and DMBTH
|
||||||
|
* for older DVBv5 applications. The emulation will try to use
|
||||||
|
* the auto mode for most things, and will assume that the desired
|
||||||
|
* delivery system is the last one at the ops.delsys[] array
|
||||||
|
*/
|
||||||
|
dprintk("%s() Using delivery system %d emulated as if it were a %d\n",
|
||||||
|
__func__, delsys, desired_system);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For now, uses it for ISDB-T, DMBTH and DVB-T2
|
||||||
|
* For DVB-S2 and DVB-TURBO, assumes that the DVB-S parameters are enough.
|
||||||
|
*/
|
||||||
|
if (type == DVBV3_OFDM) {
|
||||||
|
c->modulation = QAM_AUTO;
|
||||||
|
c->code_rate_HP = FEC_AUTO;
|
||||||
|
c->code_rate_LP = FEC_AUTO;
|
||||||
|
c->transmission_mode = TRANSMISSION_MODE_AUTO;
|
||||||
|
c->guard_interval = GUARD_INTERVAL_AUTO;
|
||||||
|
c->hierarchy = HIERARCHY_AUTO;
|
||||||
|
|
||||||
|
c->isdbt_partial_reception = -1;
|
||||||
|
c->isdbt_sb_mode = -1;
|
||||||
|
c->isdbt_sb_subchannel = -1;
|
||||||
|
c->isdbt_sb_segment_idx = -1;
|
||||||
|
c->isdbt_sb_segment_count = -1;
|
||||||
|
c->isdbt_layer_enabled = 0x7;
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
c->layer[i].fec = FEC_AUTO;
|
||||||
|
c->layer[i].modulation = QAM_AUTO;
|
||||||
|
c->layer[i].interleaving = -1;
|
||||||
|
c->layer[i].segment_count = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int dtv_property_process_set(struct dvb_frontend *fe,
|
static int dtv_property_process_set(struct dvb_frontend *fe,
|
||||||
struct dtv_property *tvp,
|
struct dtv_property *tvp,
|
||||||
struct file *file)
|
struct file *file)
|
||||||
@@ -1484,7 +1617,7 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
|
|||||||
c->rolloff = tvp->u.data;
|
c->rolloff = tvp->u.data;
|
||||||
break;
|
break;
|
||||||
case DTV_DELIVERY_SYSTEM:
|
case DTV_DELIVERY_SYSTEM:
|
||||||
c->delivery_system = tvp->u.data;
|
r = set_delivery_system(fe, tvp->u.data);
|
||||||
break;
|
break;
|
||||||
case DTV_VOLTAGE:
|
case DTV_VOLTAGE:
|
||||||
c->voltage = tvp->u.data;
|
c->voltage = tvp->u.data;
|
||||||
@@ -2043,6 +2176,11 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
|||||||
/* Synchronise DVBv5 parameters from DVBv3 */
|
/* Synchronise DVBv5 parameters from DVBv3 */
|
||||||
memcpy (&fepriv->parameters_in, parg,
|
memcpy (&fepriv->parameters_in, parg,
|
||||||
sizeof (struct dvb_frontend_parameters));
|
sizeof (struct dvb_frontend_parameters));
|
||||||
|
|
||||||
|
err = set_delivery_system(fe, SYS_UNDEFINED);
|
||||||
|
if (err)
|
||||||
|
break;
|
||||||
|
|
||||||
err = dtv_property_cache_sync(fe, c, &fepriv->parameters_in);
|
err = dtv_property_cache_sync(fe, c, &fepriv->parameters_in);
|
||||||
if (err)
|
if (err)
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user