diff options
Diffstat (limited to 'drivers/media/dvb/dvb-core/dvb_frontend.c')
-rw-r--r-- | drivers/media/dvb/dvb-core/dvb_frontend.c | 365 |
1 files changed, 193 insertions, 172 deletions
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 31e2c0d45db3..98278041d75f 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -105,7 +105,8 @@ struct dvb_frontend_private { /* thread/frontend values */ struct dvb_device *dvbdev; - struct dvb_frontend_parameters parameters; + struct dvb_frontend_parameters parameters_in; + struct dvb_frontend_parameters parameters_out; struct dvb_fe_events events; struct semaphore sem; struct list_head list_head; @@ -160,12 +161,11 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status) e = &events->events[events->eventw]; - memcpy (&e->parameters, &fepriv->parameters, - sizeof (struct dvb_frontend_parameters)); - if (status & FE_HAS_LOCK) if (fe->ops.get_frontend) - fe->ops.get_frontend(fe, &e->parameters); + fe->ops.get_frontend(fe, &fepriv->parameters_out); + + e->parameters = fepriv->parameters_out; events->eventw = wp; @@ -277,12 +277,12 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra int ready = 0; int fe_set_err = 0; struct dvb_frontend_private *fepriv = fe->frontend_priv; - int original_inversion = fepriv->parameters.inversion; - u32 original_frequency = fepriv->parameters.frequency; + int original_inversion = fepriv->parameters_in.inversion; + u32 original_frequency = fepriv->parameters_in.frequency; /* are we using autoinversion? */ autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && - (fepriv->parameters.inversion == INVERSION_AUTO)); + (fepriv->parameters_in.inversion == INVERSION_AUTO)); /* setup parameters correctly */ while(!ready) { @@ -348,18 +348,19 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step); /* set the frontend itself */ - fepriv->parameters.frequency += fepriv->lnb_drift; + fepriv->parameters_in.frequency += fepriv->lnb_drift; if (autoinversion) - fepriv->parameters.inversion = fepriv->inversion; + fepriv->parameters_in.inversion = fepriv->inversion; if (fe->ops.set_frontend) - fe_set_err = fe->ops.set_frontend(fe, &fepriv->parameters); + fe_set_err = fe->ops.set_frontend(fe, &fepriv->parameters_in); + fepriv->parameters_out = fepriv->parameters_in; if (fe_set_err < 0) { fepriv->state = FESTATE_ERROR; return fe_set_err; } - fepriv->parameters.frequency = original_frequency; - fepriv->parameters.inversion = original_inversion; + fepriv->parameters_in.frequency = original_frequency; + fepriv->parameters_in.inversion = original_inversion; fepriv->auto_sub_step++; return 0; @@ -383,7 +384,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe) if (fepriv->state & FESTATE_RETUNE) { if (fe->ops.set_frontend) retval = fe->ops.set_frontend(fe, - &fepriv->parameters); + &fepriv->parameters_in); + fepriv->parameters_out = fepriv->parameters_in; if (retval < 0) fepriv->state = FESTATE_ERROR; else @@ -413,8 +415,8 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe) /* if we're tuned, then we have determined the correct inversion */ if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) && - (fepriv->parameters.inversion == INVERSION_AUTO)) { - fepriv->parameters.inversion = fepriv->inversion; + (fepriv->parameters_in.inversion == INVERSION_AUTO)) { + fepriv->parameters_in.inversion = fepriv->inversion; } return; } @@ -594,12 +596,14 @@ restart: if (fepriv->state & FESTATE_RETUNE) { dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__); - params = &fepriv->parameters; + params = &fepriv->parameters_in; fepriv->state = FESTATE_TUNED; } if (fe->ops.tune) fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s); + if (params) + fepriv->parameters_out = *params; if (s != fepriv->status && !(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) { dprintk("%s: state changed, adding current state\n", __func__); @@ -612,11 +616,9 @@ restart: dvb_frontend_swzigzag(fe); break; case DVBFE_ALGO_CUSTOM: - params = NULL; /* have we been asked to RETUNE ? */ dprintk("%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state); if (fepriv->state & FESTATE_RETUNE) { dprintk("%s: Retune requested, FESTAT_RETUNE\n", __func__); - params = &fepriv->parameters; fepriv->state = FESTATE_TUNED; } /* Case where we are going to search for a carrier @@ -625,7 +627,7 @@ restart: */ if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) { if (fe->ops.search) { - fepriv->algo_status = fe->ops.search(fe, &fepriv->parameters); + fepriv->algo_status = fe->ops.search(fe, &fepriv->parameters_in); /* We did do a search as was requested, the flags are * now unset as well and has the flags wrt to search. */ @@ -636,11 +638,12 @@ restart: /* Track the carrier if the search was successful */ if (fepriv->algo_status == DVBFE_ALGO_SEARCH_SUCCESS) { if (fe->ops.track) - fe->ops.track(fe, &fepriv->parameters); + fe->ops.track(fe, &fepriv->parameters_in); } else { fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; fepriv->delay = HZ / 2; } + fepriv->parameters_out = fepriv->parameters_in; fe->ops.read_status(fe, &s); if (s != fepriv->status) { dvb_frontend_add_event(fe, s); /* update event list */ @@ -860,34 +863,34 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe, static int dvb_frontend_clear_cache(struct dvb_frontend *fe) { + struct dtv_frontend_properties *c = &fe->dtv_property_cache; int i; - memset(&(fe->dtv_property_cache), 0, - sizeof(struct dtv_frontend_properties)); - - fe->dtv_property_cache.state = DTV_CLEAR; - fe->dtv_property_cache.delivery_system = SYS_UNDEFINED; - fe->dtv_property_cache.inversion = INVERSION_AUTO; - fe->dtv_property_cache.fec_inner = FEC_AUTO; - fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO; - fe->dtv_property_cache.bandwidth_hz = BANDWIDTH_AUTO; - fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO; - fe->dtv_property_cache.hierarchy = HIERARCHY_AUTO; - fe->dtv_property_cache.symbol_rate = QAM_AUTO; - fe->dtv_property_cache.code_rate_HP = FEC_AUTO; - fe->dtv_property_cache.code_rate_LP = FEC_AUTO; - - fe->dtv_property_cache.isdbt_partial_reception = -1; - fe->dtv_property_cache.isdbt_sb_mode = -1; - fe->dtv_property_cache.isdbt_sb_subchannel = -1; - fe->dtv_property_cache.isdbt_sb_segment_idx = -1; - fe->dtv_property_cache.isdbt_sb_segment_count = -1; - fe->dtv_property_cache.isdbt_layer_enabled = 0x7; + memset(c, 0, sizeof(struct dtv_frontend_properties)); + + c->state = DTV_CLEAR; + c->delivery_system = SYS_UNDEFINED; + c->inversion = INVERSION_AUTO; + c->fec_inner = FEC_AUTO; + c->transmission_mode = TRANSMISSION_MODE_AUTO; + c->bandwidth_hz = BANDWIDTH_AUTO; + c->guard_interval = GUARD_INTERVAL_AUTO; + c->hierarchy = HIERARCHY_AUTO; + c->symbol_rate = QAM_AUTO; + c->code_rate_HP = FEC_AUTO; + c->code_rate_LP = FEC_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++) { - fe->dtv_property_cache.layer[i].fec = FEC_AUTO; - fe->dtv_property_cache.layer[i].modulation = QAM_AUTO; - fe->dtv_property_cache.layer[i].interleaving = -1; - fe->dtv_property_cache.layer[i].segment_count = -1; + 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; @@ -1020,10 +1023,9 @@ static int is_legacy_delivery_system(fe_delivery_system_t s) * it's being used for the legacy or new API, reducing code and complexity. */ static void dtv_property_cache_sync(struct dvb_frontend *fe, - struct dvb_frontend_parameters *p) + struct dtv_frontend_properties *c, + const struct dvb_frontend_parameters *p) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; - c->frequency = p->frequency; c->inversion = p->inversion; @@ -1074,9 +1076,9 @@ static void dtv_property_cache_sync(struct dvb_frontend *fe, */ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; + const struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dvb_frontend_private *fepriv = fe->frontend_priv; - struct dvb_frontend_parameters *p = &fepriv->parameters; + struct dvb_frontend_parameters *p = &fepriv->parameters_in; p->frequency = c->frequency; p->inversion = c->inversion; @@ -1086,14 +1088,12 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe) dprintk("%s() Preparing QPSK req\n", __func__); p->u.qpsk.symbol_rate = c->symbol_rate; p->u.qpsk.fec_inner = c->fec_inner; - c->delivery_system = SYS_DVBS; break; case FE_QAM: dprintk("%s() Preparing QAM req\n", __func__); p->u.qam.symbol_rate = c->symbol_rate; p->u.qam.fec_inner = c->fec_inner; p->u.qam.modulation = c->modulation; - c->delivery_system = SYS_DVBC_ANNEX_AC; break; case FE_OFDM: dprintk("%s() Preparing OFDM req\n", __func__); @@ -1111,15 +1111,10 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe) p->u.ofdm.transmission_mode = c->transmission_mode; p->u.ofdm.guard_interval = c->guard_interval; p->u.ofdm.hierarchy_information = c->hierarchy; - c->delivery_system = SYS_DVBT; break; case FE_ATSC: dprintk("%s() Preparing VSB req\n", __func__); p->u.vsb.modulation = c->modulation; - if ((c->modulation == VSB_8) || (c->modulation == VSB_16)) - c->delivery_system = SYS_ATSC; - else - c->delivery_system = SYS_DVBC_ANNEX_B; break; } } @@ -1129,9 +1124,9 @@ static void dtv_property_legacy_params_sync(struct dvb_frontend *fe) */ static void dtv_property_adv_params_sync(struct dvb_frontend *fe) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; + const struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dvb_frontend_private *fepriv = fe->frontend_priv; - struct dvb_frontend_parameters *p = &fepriv->parameters; + struct dvb_frontend_parameters *p = &fepriv->parameters_in; p->frequency = c->frequency; p->inversion = c->inversion; @@ -1148,10 +1143,9 @@ static void dtv_property_adv_params_sync(struct dvb_frontend *fe) break; } - if(c->delivery_system == SYS_ISDBT) { - /* Fake out a generic DVB-T request so we pass validation in the ioctl */ - p->frequency = c->frequency; - p->inversion = c->inversion; + /* Fake out a generic DVB-T request so we pass validation in the ioctl */ + if ((c->delivery_system == SYS_ISDBT) || + (c->delivery_system == SYS_DVBT2)) { p->u.ofdm.constellation = QAM_AUTO; p->u.ofdm.code_rate_HP = FEC_AUTO; p->u.ofdm.code_rate_LP = FEC_AUTO; @@ -1171,7 +1165,7 @@ static void dtv_property_adv_params_sync(struct dvb_frontend *fe) static void dtv_property_cache_submit(struct dvb_frontend *fe) { - struct dtv_frontend_properties *c = &fe->dtv_property_cache; + const struct dtv_frontend_properties *c = &fe->dtv_property_cache; /* For legacy delivery systems we don't need the delivery_system to * be specified, but we populate the older structures from the cache @@ -1204,133 +1198,149 @@ static int dtv_property_process_get(struct dvb_frontend *fe, struct dtv_property *tvp, struct file *file) { - int r = 0; - - /* Allow the frontend to validate incoming properties */ - if (fe->ops.get_property) - r = fe->ops.get_property(fe, tvp); + const struct dtv_frontend_properties *c = &fe->dtv_property_cache; + struct dvb_frontend_private *fepriv = fe->frontend_priv; + struct dtv_frontend_properties cdetected; + int r; - if (r < 0) - return r; + /* + * If the driver implements a get_frontend function, then convert + * detected parameters to S2API properties. + */ + if (fe->ops.get_frontend) { + cdetected = *c; + dtv_property_cache_sync(fe, &cdetected, &fepriv->parameters_out); + c = &cdetected; + } switch(tvp->cmd) { case DTV_FREQUENCY: - tvp->u.data = fe->dtv_property_cache.frequency; + tvp->u.data = c->frequency; break; case DTV_MODULATION: - tvp->u.data = fe->dtv_property_cache.modulation; + tvp->u.data = c->modulation; break; case DTV_BANDWIDTH_HZ: - tvp->u.data = fe->dtv_property_cache.bandwidth_hz; + tvp->u.data = c->bandwidth_hz; break; case DTV_INVERSION: - tvp->u.data = fe->dtv_property_cache.inversion; + tvp->u.data = c->inversion; break; case DTV_SYMBOL_RATE: - tvp->u.data = fe->dtv_property_cache.symbol_rate; + tvp->u.data = c->symbol_rate; break; case DTV_INNER_FEC: - tvp->u.data = fe->dtv_property_cache.fec_inner; + tvp->u.data = c->fec_inner; break; case DTV_PILOT: - tvp->u.data = fe->dtv_property_cache.pilot; + tvp->u.data = c->pilot; break; case DTV_ROLLOFF: - tvp->u.data = fe->dtv_property_cache.rolloff; + tvp->u.data = c->rolloff; break; case DTV_DELIVERY_SYSTEM: - tvp->u.data = fe->dtv_property_cache.delivery_system; + tvp->u.data = c->delivery_system; break; case DTV_VOLTAGE: - tvp->u.data = fe->dtv_property_cache.voltage; + tvp->u.data = c->voltage; break; case DTV_TONE: - tvp->u.data = fe->dtv_property_cache.sectone; + tvp->u.data = c->sectone; break; case DTV_API_VERSION: tvp->u.data = (DVB_API_VERSION << 8) | DVB_API_VERSION_MINOR; break; case DTV_CODE_RATE_HP: - tvp->u.data = fe->dtv_property_cache.code_rate_HP; + tvp->u.data = c->code_rate_HP; break; case DTV_CODE_RATE_LP: - tvp->u.data = fe->dtv_property_cache.code_rate_LP; + tvp->u.data = c->code_rate_LP; break; case DTV_GUARD_INTERVAL: - tvp->u.data = fe->dtv_property_cache.guard_interval; + tvp->u.data = c->guard_interval; break; case DTV_TRANSMISSION_MODE: - tvp->u.data = fe->dtv_property_cache.transmission_mode; + tvp->u.data = c->transmission_mode; break; case DTV_HIERARCHY: - tvp->u.data = fe->dtv_property_cache.hierarchy; + tvp->u.data = c->hierarchy; break; /* ISDB-T Support here */ case DTV_ISDBT_PARTIAL_RECEPTION: - tvp->u.data = fe->dtv_property_cache.isdbt_partial_reception; + tvp->u.data = c->isdbt_partial_reception; break; case DTV_ISDBT_SOUND_BROADCASTING: - tvp->u.data = fe->dtv_property_cache.isdbt_sb_mode; + tvp->u.data = c->isdbt_sb_mode; break; case DTV_ISDBT_SB_SUBCHANNEL_ID: - tvp->u.data = fe->dtv_property_cache.isdbt_sb_subchannel; + tvp->u.data = c->isdbt_sb_subchannel; break; case DTV_ISDBT_SB_SEGMENT_IDX: - tvp->u.data = fe->dtv_property_cache.isdbt_sb_segment_idx; + tvp->u.data = c->isdbt_sb_segment_idx; break; case DTV_ISDBT_SB_SEGMENT_COUNT: - tvp->u.data = fe->dtv_property_cache.isdbt_sb_segment_count; + tvp->u.data = c->isdbt_sb_segment_count; break; case DTV_ISDBT_LAYER_ENABLED: - tvp->u.data = fe->dtv_property_cache.isdbt_layer_enabled; + tvp->u.data = c->isdbt_layer_enabled; break; case DTV_ISDBT_LAYERA_FEC: - tvp->u.data = fe->dtv_property_cache.layer[0].fec; + tvp->u.data = c->layer[0].fec; break; case DTV_ISDBT_LAYERA_MODULATION: - tvp->u.data = fe->dtv_property_cache.layer[0].modulation; + tvp->u.data = c->layer[0].modulation; break; case DTV_ISDBT_LAYERA_SEGMENT_COUNT: - tvp->u.data = fe->dtv_property_cache.layer[0].segment_count; + tvp->u.data = c->layer[0].segment_count; break; case DTV_ISDBT_LAYERA_TIME_INTERLEAVING: - tvp->u.data = fe->dtv_property_cache.layer[0].interleaving; + tvp->u.data = c->layer[0].interleaving; break; case DTV_ISDBT_LAYERB_FEC: - tvp->u.data = fe->dtv_property_cache.layer[1].fec; + tvp->u.data = c->layer[1].fec; break; case DTV_ISDBT_LAYERB_MODULATION: - tvp->u.data = fe->dtv_property_cache.layer[1].modulation; + tvp->u.data = c->layer[1].modulation; break; case DTV_ISDBT_LAYERB_SEGMENT_COUNT: - tvp->u.data = fe->dtv_property_cache.layer[1].segment_count; + tvp->u.data = c->layer[1].segment_count; break; case DTV_ISDBT_LAYERB_TIME_INTERLEAVING: - tvp->u.data = fe->dtv_property_cache.layer[1].interleaving; + tvp->u.data = c->layer[1].interleaving; break; case DTV_ISDBT_LAYERC_FEC: - tvp->u.data = fe->dtv_property_cache.layer[2].fec; + tvp->u.data = c->layer[2].fec; break; case DTV_ISDBT_LAYERC_MODULATION: - tvp->u.data = fe->dtv_property_cache.layer[2].modulation; + tvp->u.data = c->layer[2].modulation; break; case DTV_ISDBT_LAYERC_SEGMENT_COUNT: - tvp->u.data = fe->dtv_property_cache.layer[2].segment_count; + tvp->u.data = c->layer[2].segment_count; break; case DTV_ISDBT_LAYERC_TIME_INTERLEAVING: - tvp->u.data = fe->dtv_property_cache.layer[2].interleaving; + tvp->u.data = c->layer[2].interleaving; break; case DTV_ISDBS_TS_ID: - tvp->u.data = fe->dtv_property_cache.isdbs_ts_id; + tvp->u.data = c->isdbs_ts_id; + break; + case DTV_DVBT2_PLP_ID: + tvp->u.data = c->dvbt2_plp_id; break; default: - r = -1; + return -EINVAL; + } + + /* Allow the frontend to override outgoing properties */ + if (fe->ops.get_property) { + r = fe->ops.get_property(fe, tvp); + if (r < 0) + return r; } dtv_property_dump(tvp); - return r; + return 0; } static int dtv_property_process_set(struct dvb_frontend *fe, @@ -1338,15 +1348,16 @@ static int dtv_property_process_set(struct dvb_frontend *fe, struct file *file) { int r = 0; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dvb_frontend_private *fepriv = fe->frontend_priv; dtv_property_dump(tvp); /* Allow the frontend to validate incoming properties */ - if (fe->ops.set_property) + if (fe->ops.set_property) { r = fe->ops.set_property(fe, tvp); - - if (r < 0) - return r; + if (r < 0) + return r; + } switch(tvp->cmd) { case DTV_CLEAR: @@ -1361,126 +1372,129 @@ static int dtv_property_process_set(struct dvb_frontend *fe, * tunerequest so we can pass validation in the FE_SET_FRONTEND * ioctl. */ - fe->dtv_property_cache.state = tvp->cmd; + c->state = tvp->cmd; dprintk("%s() Finalised property cache\n", __func__); dtv_property_cache_submit(fe); - r |= dvb_frontend_ioctl_legacy(file, FE_SET_FRONTEND, - &fepriv->parameters); + r = dvb_frontend_ioctl_legacy(file, FE_SET_FRONTEND, + &fepriv->parameters_in); break; case DTV_FREQUENCY: - fe->dtv_property_cache.frequency = tvp->u.data; + c->frequency = tvp->u.data; break; case DTV_MODULATION: - fe->dtv_property_cache.modulation = tvp->u.data; + c->modulation = tvp->u.data; break; case DTV_BANDWIDTH_HZ: - fe->dtv_property_cache.bandwidth_hz = tvp->u.data; + c->bandwidth_hz = tvp->u.data; break; case DTV_INVERSION: - fe->dtv_property_cache.inversion = tvp->u.data; + c->inversion = tvp->u.data; break; case DTV_SYMBOL_RATE: - fe->dtv_property_cache.symbol_rate = tvp->u.data; + c->symbol_rate = tvp->u.data; break; case DTV_INNER_FEC: - fe->dtv_property_cache.fec_inner = tvp->u.data; + c->fec_inner = tvp->u.data; break; case DTV_PILOT: - fe->dtv_property_cache.pilot = tvp->u.data; + c->pilot = tvp->u.data; break; case DTV_ROLLOFF: - fe->dtv_property_cache.rolloff = tvp->u.data; + c->rolloff = tvp->u.data; break; case DTV_DELIVERY_SYSTEM: - fe->dtv_property_cache.delivery_system = tvp->u.data; + c->delivery_system = tvp->u.data; break; case DTV_VOLTAGE: - fe->dtv_property_cache.voltage = tvp->u.data; + c->voltage = tvp->u.data; r = dvb_frontend_ioctl_legacy(file, FE_SET_VOLTAGE, - (void *)fe->dtv_property_cache.voltage); + (void *)c->voltage); break; case DTV_TONE: - fe->dtv_property_cache.sectone = tvp->u.data; + c->sectone = tvp->u.data; r = dvb_frontend_ioctl_legacy(file, FE_SET_TONE, - (void *)fe->dtv_property_cache.sectone); + (void *)c->sectone); break; case DTV_CODE_RATE_HP: - fe->dtv_property_cache.code_rate_HP = tvp->u.data; + c->code_rate_HP = tvp->u.data; break; case DTV_CODE_RATE_LP: - fe->dtv_property_cache.code_rate_LP = tvp->u.data; + c->code_rate_LP = tvp->u.data; break; case DTV_GUARD_INTERVAL: - fe->dtv_property_cache.guard_interval = tvp->u.data; + c->guard_interval = tvp->u.data; break; case DTV_TRANSMISSION_MODE: - fe->dtv_property_cache.transmission_mode = tvp->u.data; + c->transmission_mode = tvp->u.data; break; case DTV_HIERARCHY: - fe->dtv_property_cache.hierarchy = tvp->u.data; + c->hierarchy = tvp->u.data; break; /* ISDB-T Support here */ case DTV_ISDBT_PARTIAL_RECEPTION: - fe->dtv_property_cache.isdbt_partial_reception = tvp->u.data; + c->isdbt_partial_reception = tvp->u.data; break; case DTV_ISDBT_SOUND_BROADCASTING: - fe->dtv_property_cache.isdbt_sb_mode = tvp->u.data; + c->isdbt_sb_mode = tvp->u.data; break; case DTV_ISDBT_SB_SUBCHANNEL_ID: - fe->dtv_property_cache.isdbt_sb_subchannel = tvp->u.data; + c->isdbt_sb_subchannel = tvp->u.data; break; case DTV_ISDBT_SB_SEGMENT_IDX: - fe->dtv_property_cache.isdbt_sb_segment_idx = tvp->u.data; + c->isdbt_sb_segment_idx = tvp->u.data; break; case DTV_ISDBT_SB_SEGMENT_COUNT: - fe->dtv_property_cache.isdbt_sb_segment_count = tvp->u.data; + c->isdbt_sb_segment_count = tvp->u.data; break; case DTV_ISDBT_LAYER_ENABLED: - fe->dtv_property_cache.isdbt_layer_enabled = tvp->u.data; + c->isdbt_layer_enabled = tvp->u.data; break; case DTV_ISDBT_LAYERA_FEC: - fe->dtv_property_cache.layer[0].fec = tvp->u.data; + c->layer[0].fec = tvp->u.data; break; case DTV_ISDBT_LAYERA_MODULATION: - fe->dtv_property_cache.layer[0].modulation = tvp->u.data; + c->layer[0].modulation = tvp->u.data; break; case DTV_ISDBT_LAYERA_SEGMENT_COUNT: - fe->dtv_property_cache.layer[0].segment_count = tvp->u.data; + c->layer[0].segment_count = tvp->u.data; break; case DTV_ISDBT_LAYERA_TIME_INTERLEAVING: - fe->dtv_property_cache.layer[0].interleaving = tvp->u.data; + c->layer[0].interleaving = tvp->u.data; break; case DTV_ISDBT_LAYERB_FEC: - fe->dtv_property_cache.layer[1].fec = tvp->u.data; + c->layer[1].fec = tvp->u.data; break; case DTV_ISDBT_LAYERB_MODULATION: - fe->dtv_property_cache.layer[1].modulation = tvp->u.data; + c->layer[1].modulation = tvp->u.data; break; case DTV_ISDBT_LAYERB_SEGMENT_COUNT: - fe->dtv_property_cache.layer[1].segment_count = tvp->u.data; + c->layer[1].segment_count = tvp->u.data; break; case DTV_ISDBT_LAYERB_TIME_INTERLEAVING: - fe->dtv_property_cache.layer[1].interleaving = tvp->u.data; + c->layer[1].interleaving = tvp->u.data; break; case DTV_ISDBT_LAYERC_FEC: - fe->dtv_property_cache.layer[2].fec = tvp->u.data; + c->layer[2].fec = tvp->u.data; break; case DTV_ISDBT_LAYERC_MODULATION: - fe->dtv_property_cache.layer[2].modulation = tvp->u.data; + c->layer[2].modulation = tvp->u.data; break; case DTV_ISDBT_LAYERC_SEGMENT_COUNT: - fe->dtv_property_cache.layer[2].segment_count = tvp->u.data; + c->layer[2].segment_count = tvp->u.data; break; case DTV_ISDBT_LAYERC_TIME_INTERLEAVING: - fe->dtv_property_cache.layer[2].interleaving = tvp->u.data; + c->layer[2].interleaving = tvp->u.data; break; case DTV_ISDBS_TS_ID: - fe->dtv_property_cache.isdbs_ts_id = tvp->u.data; + c->isdbs_ts_id = tvp->u.data; + break; + case DTV_DVBT2_PLP_ID: + c->dvbt2_plp_id = tvp->u.data; break; default: - r = -1; + return -EINVAL; } return r; @@ -1491,6 +1505,7 @@ static int dvb_frontend_ioctl(struct file *file, { struct dvb_device *dvbdev = file->private_data; struct dvb_frontend *fe = dvbdev->priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dvb_frontend_private *fepriv = fe->frontend_priv; int err = -EOPNOTSUPP; @@ -1510,7 +1525,7 @@ static int dvb_frontend_ioctl(struct file *file, if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY)) err = dvb_frontend_ioctl_properties(file, cmd, parg); else { - fe->dtv_property_cache.state = DTV_UNDEFINED; + c->state = DTV_UNDEFINED; err = dvb_frontend_ioctl_legacy(file, cmd, parg); } @@ -1523,6 +1538,7 @@ static int dvb_frontend_ioctl_properties(struct file *file, { struct dvb_device *dvbdev = file->private_data; struct dvb_frontend *fe = dvbdev->priv; + struct dtv_frontend_properties *c = &fe->dtv_property_cache; int err = 0; struct dtv_properties *tvps = NULL; @@ -1554,11 +1570,13 @@ static int dvb_frontend_ioctl_properties(struct file *file, } for (i = 0; i < tvps->num; i++) { - (tvp + i)->result = dtv_property_process_set(fe, tvp + i, file); - err |= (tvp + i)->result; + err = dtv_property_process_set(fe, tvp + i, file); + if (err < 0) + goto out; + (tvp + i)->result = err; } - if(fe->dtv_property_cache.state == DTV_TUNE) + if (c->state == DTV_TUNE) dprintk("%s() Property cache is full, tuning\n", __func__); } else @@ -1586,8 +1604,10 @@ static int dvb_frontend_ioctl_properties(struct file *file, } for (i = 0; i < tvps->num; i++) { - (tvp + i)->result = dtv_property_process_get(fe, tvp + i, file); - err |= (tvp + i)->result; + err = dtv_property_process_get(fe, tvp + i, file); + if (err < 0) + goto out; + (tvp + i)->result = err; } if (copy_to_user(tvps->props, tvp, tvps->num * sizeof(struct dtv_property))) { @@ -1787,10 +1807,11 @@ static int dvb_frontend_ioctl_legacy(struct file *file, break; case FE_SET_FRONTEND: { + struct dtv_frontend_properties *c = &fe->dtv_property_cache; struct dvb_frontend_tune_settings fetunesettings; - if(fe->dtv_property_cache.state == DTV_TUNE) { - if (dvb_frontend_check_parameters(fe, &fepriv->parameters) < 0) { + if (c->state == DTV_TUNE) { + if (dvb_frontend_check_parameters(fe, &fepriv->parameters_in) < 0) { err = -EINVAL; break; } @@ -1800,9 +1821,9 @@ static int dvb_frontend_ioctl_legacy(struct file *file, break; } - memcpy (&fepriv->parameters, parg, + memcpy (&fepriv->parameters_in, parg, sizeof (struct dvb_frontend_parameters)); - dtv_property_cache_sync(fe, &fepriv->parameters); + dtv_property_cache_sync(fe, c, &fepriv->parameters_in); } memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings)); @@ -1811,15 +1832,15 @@ static int dvb_frontend_ioctl_legacy(struct file *file, /* force auto frequency inversion if requested */ if (dvb_force_auto_inversion) { - fepriv->parameters.inversion = INVERSION_AUTO; + fepriv->parameters_in.inversion = INVERSION_AUTO; fetunesettings.parameters.inversion = INVERSION_AUTO; } if (fe->ops.info.type == FE_OFDM) { /* without hierarchical coding code_rate_LP is irrelevant, * so we tolerate the otherwise invalid FEC_NONE setting */ - if (fepriv->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE && - fepriv->parameters.u.ofdm.code_rate_LP == FEC_NONE) - fepriv->parameters.u.ofdm.code_rate_LP = FEC_AUTO; + if (fepriv->parameters_in.u.ofdm.hierarchy_information == HIERARCHY_NONE && + fepriv->parameters_in.u.ofdm.code_rate_LP == FEC_NONE) + fepriv->parameters_in.u.ofdm.code_rate_LP = FEC_AUTO; } /* get frontend-specific tuning settings */ @@ -1832,8 +1853,8 @@ static int dvb_frontend_ioctl_legacy(struct file *file, switch(fe->ops.info.type) { case FE_QPSK: fepriv->min_delay = HZ/20; - fepriv->step_size = fepriv->parameters.u.qpsk.symbol_rate / 16000; - fepriv->max_drift = fepriv->parameters.u.qpsk.symbol_rate / 2000; + fepriv->step_size = fepriv->parameters_in.u.qpsk.symbol_rate / 16000; + fepriv->max_drift = fepriv->parameters_in.u.qpsk.symbol_rate / 2000; break; case FE_QAM: @@ -1875,8 +1896,8 @@ static int dvb_frontend_ioctl_legacy(struct file *file, case FE_GET_FRONTEND: if (fe->ops.get_frontend) { - memcpy (parg, &fepriv->parameters, sizeof (struct dvb_frontend_parameters)); - err = fe->ops.get_frontend(fe, (struct dvb_frontend_parameters*) parg); + err = fe->ops.get_frontend(fe, &fepriv->parameters_out); + memcpy(parg, &fepriv->parameters_out, sizeof(struct dvb_frontend_parameters)); } break; |