diff options
Diffstat (limited to 'recipes/linux/linux-vusolo2-2.6.37/dvb-core.patch')
-rw-r--r-- | recipes/linux/linux-vusolo2-2.6.37/dvb-core.patch | 1330 |
1 files changed, 1330 insertions, 0 deletions
diff --git a/recipes/linux/linux-vusolo2-2.6.37/dvb-core.patch b/recipes/linux/linux-vusolo2-2.6.37/dvb-core.patch new file mode 100644 index 0000000..87b1738 --- /dev/null +++ b/recipes/linux/linux-vusolo2-2.6.37/dvb-core.patch @@ -0,0 +1,1330 @@ +diff --git a/drivers/media/dvb/dvb-core/Makefile b/drivers/media/dvb/dvb-core/Makefile +index 0b51828..8f22bcd 100644 +--- a/drivers/media/dvb/dvb-core/Makefile ++++ b/drivers/media/dvb/dvb-core/Makefile +@@ -2,8 +2,10 @@ + # Makefile for the kernel DVB device drivers. + # + ++dvb-net-$(CONFIG_DVB_NET) := dvb_net.o ++ + dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \ + dvb_ca_en50221.o dvb_frontend.o \ +- dvb_net.o dvb_ringbuffer.o dvb_math.o ++ $(dvb-net-y) dvb_ringbuffer.o dvb_math.o + + obj-$(CONFIG_DVB_CORE) += dvb-core.o +diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c +index ad1f61d..cb59681 100644 +--- a/drivers/media/dvb/dvb-core/dmxdev.c ++++ b/drivers/media/dvb/dvb-core/dmxdev.c +@@ -83,7 +83,11 @@ static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src, + + ret = wait_event_interruptible(src->queue, + !dvb_ringbuffer_empty(src) || +- (src->error != 0)); ++ (src->error != 0) || ++ (src->do_wait != 1)); ++ if (src->do_wait != 1) ++ ret = -EINTR; ++ + if (ret < 0) + break; + +@@ -572,13 +576,13 @@ static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev, + dmx_output_t otype; + int ret; + int ts_type; +- enum dmx_ts_pes ts_pes; ++ dmx_pes_type_t ts_pes; + struct dmx_ts_feed *tsfeed; + + feed->ts = NULL; + otype = para->output; + +- ts_pes = (enum dmx_ts_pes)para->pes_type; ++ ts_pes = para->pes_type; + + if (ts_pes < DMX_PES_OTHER) + ts_type = TS_DECODER; +@@ -963,6 +967,22 @@ dvb_demux_read(struct file *file, char __user *buf, size_t count, + return ret; + } + ++static int dvb_demux_lock_filter(struct dmxdev_filter *dmxdevfilter) ++{ ++ int ret; ++ ++ dmxdevfilter->buffer.do_wait = 0; ++ ++ if (waitqueue_active(&dmxdevfilter->buffer.queue)) ++ wake_up(&dmxdevfilter->buffer.queue); ++ ++ ret = mutex_lock_interruptible(&dmxdevfilter->mutex); ++ ++ dmxdevfilter->buffer.do_wait = 1; ++ ++ return ret; ++} ++ + static int dvb_demux_do_ioctl(struct file *file, + unsigned int cmd, void *parg) + { +@@ -976,7 +996,7 @@ static int dvb_demux_do_ioctl(struct file *file, + + switch (cmd) { + case DMX_START: +- if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { ++ if (dvb_demux_lock_filter(dmxdevfilter)) { + mutex_unlock(&dmxdev->mutex); + return -ERESTARTSYS; + } +@@ -988,7 +1008,7 @@ static int dvb_demux_do_ioctl(struct file *file, + break; + + case DMX_STOP: +- if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { ++ if (dvb_demux_lock_filter(dmxdevfilter)) { + mutex_unlock(&dmxdev->mutex); + return -ERESTARTSYS; + } +@@ -997,7 +1017,7 @@ static int dvb_demux_do_ioctl(struct file *file, + break; + + case DMX_SET_FILTER: +- if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { ++ if (dvb_demux_lock_filter(dmxdevfilter)) { + mutex_unlock(&dmxdev->mutex); + return -ERESTARTSYS; + } +@@ -1006,7 +1026,7 @@ static int dvb_demux_do_ioctl(struct file *file, + break; + + case DMX_SET_PES_FILTER: +- if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { ++ if (dvb_demux_lock_filter(dmxdevfilter)) { + mutex_unlock(&dmxdev->mutex); + return -ERESTARTSYS; + } +@@ -1015,7 +1035,7 @@ static int dvb_demux_do_ioctl(struct file *file, + break; + + case DMX_SET_BUFFER_SIZE: +- if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { ++ if (dvb_demux_lock_filter(dmxdevfilter)) { + mutex_unlock(&dmxdev->mutex); + return -ERESTARTSYS; + } +@@ -1059,7 +1079,7 @@ static int dvb_demux_do_ioctl(struct file *file, + break; + + case DMX_ADD_PID: +- if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { ++ if (dvb_demux_lock_filter(dmxdevfilter)) { + ret = -ERESTARTSYS; + break; + } +@@ -1068,7 +1088,7 @@ static int dvb_demux_do_ioctl(struct file *file, + break; + + case DMX_REMOVE_PID: +- if (mutex_lock_interruptible(&dmxdevfilter->mutex)) { ++ if (dvb_demux_lock_filter(dmxdevfilter)) { + ret = -ERESTARTSYS; + break; + } +diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c +index 4a88a3e..faa3671 100644 +--- a/drivers/media/dvb/dvb-core/dvb_demux.c ++++ b/drivers/media/dvb/dvb-core/dvb_demux.c +@@ -478,97 +478,94 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, + + EXPORT_SYMBOL(dvb_dmx_swfilter_packets); + +-void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) ++static inline int find_next_packet(const u8 *buf, int pos, size_t count, ++ const int pktsize) + { +- int p = 0, i, j; ++ int start = pos, lost; + +- spin_lock(&demux->lock); +- +- if (demux->tsbufp) { +- i = demux->tsbufp; +- j = 188 - i; +- if (count < j) { +- memcpy(&demux->tsbuf[i], buf, count); +- demux->tsbufp += count; +- goto bailout; +- } +- memcpy(&demux->tsbuf[i], buf, j); +- if (demux->tsbuf[0] == 0x47) +- dvb_dmx_swfilter_packet(demux, demux->tsbuf); +- demux->tsbufp = 0; +- p += j; ++ while (pos < count) { ++ if (buf[pos] == 0x47 || ++ (pktsize == 204 && buf[pos] == 0xB8)) ++ break; ++ pos++; + } + +- while (p < count) { +- if (buf[p] == 0x47) { +- if (count - p >= 188) { +- dvb_dmx_swfilter_packet(demux, &buf[p]); +- p += 188; +- } else { +- i = count - p; +- memcpy(demux->tsbuf, &buf[p], i); +- demux->tsbufp = i; +- goto bailout; +- } +- } else +- p++; ++ lost = pos - start; ++ if (lost) { ++ /* This garbage is part of a valid packet? */ ++ int backtrack = pos - pktsize; ++ if (backtrack >= 0 && (buf[backtrack] == 0x47 || ++ (pktsize == 204 && buf[backtrack] == 0xB8))) ++ return backtrack; + } + +-bailout: +- spin_unlock(&demux->lock); ++ return pos; + } + +-EXPORT_SYMBOL(dvb_dmx_swfilter); +- +-void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) ++/* Filter all pktsize= 188 or 204 sized packets and skip garbage. */ ++static inline void _dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, ++ size_t count, const int pktsize) + { + int p = 0, i, j; +- u8 tmppack[188]; ++ const u8 *q; + + spin_lock(&demux->lock); + +- if (demux->tsbufp) { ++ if (demux->tsbufp) { /* tsbuf[0] is now 0x47. */ + i = demux->tsbufp; +- j = 204 - i; ++ j = pktsize - i; + if (count < j) { + memcpy(&demux->tsbuf[i], buf, count); + demux->tsbufp += count; + goto bailout; + } + memcpy(&demux->tsbuf[i], buf, j); +- if ((demux->tsbuf[0] == 0x47) || (demux->tsbuf[0] == 0xB8)) { +- memcpy(tmppack, demux->tsbuf, 188); +- if (tmppack[0] == 0xB8) +- tmppack[0] = 0x47; +- dvb_dmx_swfilter_packet(demux, tmppack); +- } ++ if (demux->tsbuf[0] == 0x47) /* double check */ ++ dvb_dmx_swfilter_packet(demux, demux->tsbuf); + demux->tsbufp = 0; + p += j; + } + +- while (p < count) { +- if ((buf[p] == 0x47) || (buf[p] == 0xB8)) { +- if (count - p >= 204) { +- memcpy(tmppack, &buf[p], 188); +- if (tmppack[0] == 0xB8) +- tmppack[0] = 0x47; +- dvb_dmx_swfilter_packet(demux, tmppack); +- p += 204; +- } else { +- i = count - p; +- memcpy(demux->tsbuf, &buf[p], i); +- demux->tsbufp = i; +- goto bailout; +- } +- } else { +- p++; ++ while (1) { ++ p = find_next_packet(buf, p, count, pktsize); ++ if (p >= count) ++ break; ++ if (count - p < pktsize) ++ break; ++ ++ q = &buf[p]; ++ ++ if (pktsize == 204 && (*q == 0xB8)) { ++ memcpy(demux->tsbuf, q, 188); ++ demux->tsbuf[0] = 0x47; ++ q = demux->tsbuf; + } ++ dvb_dmx_swfilter_packet(demux, q); ++ p += pktsize; ++ } ++ ++ i = count - p; ++ if (i) { ++ memcpy(demux->tsbuf, &buf[p], i); ++ demux->tsbufp = i; ++ if (pktsize == 204 && demux->tsbuf[0] == 0xB8) ++ demux->tsbuf[0] = 0x47; + } + + bailout: + spin_unlock(&demux->lock); + } + ++void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count) ++{ ++ _dvb_dmx_swfilter(demux, buf, count, 188); ++} ++EXPORT_SYMBOL(dvb_dmx_swfilter); ++ ++void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count) ++{ ++ _dvb_dmx_swfilter(demux, buf, count, 204); ++} + EXPORT_SYMBOL(dvb_dmx_swfilter_204); + + static struct dvb_demux_filter *dvb_dmx_filter_alloc(struct dvb_demux *demux) +diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c +index cad6634..efe9c30 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; +@@ -901,7 +904,7 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe) + .buffer = b \ + } + +-static struct dtv_cmds_h dtv_cmds[] = { ++static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = { + _DTV_CMD(DTV_TUNE, 1, 0), + _DTV_CMD(DTV_CLEAR, 1, 0), + +@@ -963,6 +966,7 @@ static struct dtv_cmds_h dtv_cmds[] = { + _DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 0, 0), + + _DTV_CMD(DTV_ISDBS_TS_ID, 1, 0), ++ _DTV_CMD(DTV_DVBT2_PLP_ID, 1, 0), + + /* Get */ + _DTV_CMD(DTV_DISEQC_SLAVE_REPLY, 0, 1), +@@ -1020,10 +1024,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 +1077,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 +1089,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 +1112,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 +1125,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 +1144,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 +1166,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 +1199,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 +1349,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 +1373,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 +1506,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 +1526,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 +1539,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 +1571,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 +1605,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))) { +@@ -1638,7 +1659,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file, + case FE_READ_STATUS: { + fe_status_t* status = parg; + +- /* if retune was requested but hasn't occured yet, prevent ++ /* if retune was requested but hasn't occurred yet, prevent + * that user get signal state from previous tuning */ + if (fepriv->state == FESTATE_RETUNE || + fepriv->state == FESTATE_ERROR) { +@@ -1729,7 +1750,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file, + * Dish network legacy switches (as used by Dish500) + * are controlled by sending 9-bit command words + * spaced 8msec apart. +- * the actual command word is switch/port dependant ++ * the actual command word is switch/port dependent + * so it is up to the userspace application to send + * the right command. + * The command must always start with a '0' after +@@ -1787,10 +1808,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 +1822,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 +1833,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 +1854,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 +1897,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; + +@@ -1967,6 +1989,14 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) + if (dvbdev->users == -1 && fe->ops.ts_bus_ctrl) { + if ((ret = fe->ops.ts_bus_ctrl(fe, 1)) < 0) + goto err0; ++ ++ /* If we took control of the bus, we need to force ++ reinitialization. This is because many ts_bus_ctrl() ++ functions strobe the RESET pin on the demod, and if the ++ frontend thread already exists then the dvb_init() routine ++ won't get called (which is what usually does initial ++ register configuration). */ ++ fepriv->reinitialise = 1; + } + + if ((ret = dvb_generic_open (inode, file)) < 0) +diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h +index f9f19be..5590eb6 100644 +--- a/drivers/media/dvb/dvb-core/dvb_frontend.h ++++ b/drivers/media/dvb/dvb-core/dvb_frontend.h +@@ -239,7 +239,6 @@ struct analog_demod_ops { + void (*set_params)(struct dvb_frontend *fe, + struct analog_parameters *params); + int (*has_signal)(struct dvb_frontend *fe); +- int (*is_stereo)(struct dvb_frontend *fe); + int (*get_afc)(struct dvb_frontend *fe); + void (*tuner_status)(struct dvb_frontend *fe); + void (*standby)(struct dvb_frontend *fe); +@@ -359,6 +358,9 @@ struct dtv_frontend_properties { + + /* ISDB-T specifics */ + u32 isdbs_ts_id; ++ ++ /* DVB-T2 specifics */ ++ u32 dvbt2_plp_id; + }; + + struct dvb_frontend { +diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c +index 4df42aa..51752a9 100644 +--- a/drivers/media/dvb/dvb-core/dvb_net.c ++++ b/drivers/media/dvb/dvb-core/dvb_net.c +@@ -1329,7 +1329,8 @@ static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned long num) + return -EBUSY; + + dvb_net_stop(net); +- flush_scheduled_work(); ++ flush_work_sync(&priv->set_multicast_list_wq); ++ flush_work_sync(&priv->restart_net_feed_wq); + printk("dvb_net: removed network interface %s\n", net->name); + unregister_netdev(net); + dvbnet->state[num]=0; +diff --git a/drivers/media/dvb/dvb-core/dvb_net.h b/drivers/media/dvb/dvb-core/dvb_net.h +index 3a3126c..1e53acd 100644 +--- a/drivers/media/dvb/dvb-core/dvb_net.h ++++ b/drivers/media/dvb/dvb-core/dvb_net.h +@@ -32,6 +32,8 @@ + + #define DVB_NET_DEVICES_MAX 10 + ++#ifdef CONFIG_DVB_NET ++ + struct dvb_net { + struct dvb_device *dvbdev; + struct net_device *device[DVB_NET_DEVICES_MAX]; +@@ -40,8 +42,25 @@ struct dvb_net { + struct dmx_demux *demux; + }; + +- + void dvb_net_release(struct dvb_net *); + int dvb_net_init(struct dvb_adapter *, struct dvb_net *, struct dmx_demux *); + ++#else ++ ++struct dvb_net { ++ struct dvb_device *dvbdev; ++}; ++ ++static inline void dvb_net_release(struct dvb_net *dvbnet) ++{ ++} ++ ++static inline int dvb_net_init(struct dvb_adapter *adap, ++ struct dvb_net *dvbnet, struct dmx_demux *dmx) ++{ ++ return 0; ++} ++ ++#endif /* ifdef CONFIG_DVB_NET */ ++ + #endif +diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c +index a5712cd..d5333f3 100644 +--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c ++++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c +@@ -45,6 +45,7 @@ void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len) + rbuf->data=data; + rbuf->size=len; + rbuf->error=0; ++ rbuf->do_wait=1; + + init_waitqueue_head(&rbuf->queue); + +diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h +index 41f04da..6951dd3 100644 +--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h ++++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h +@@ -39,6 +39,7 @@ struct dvb_ringbuffer { + + wait_queue_head_t queue; + spinlock_t lock; ++ int do_wait; + }; + + #define DVB_RINGBUFFER_PKTHDRSIZE 3 +diff --git a/include/linux/dvb/audio.h b/include/linux/dvb/audio.h +index fec66bd..d47bccd 100644 +--- a/include/linux/dvb/audio.h ++++ b/include/linux/dvb/audio.h +@@ -67,7 +67,7 @@ typedef struct audio_status { + + + typedef +-struct audio_karaoke{ /* if Vocal1 or Vocal2 are non-zero, they get mixed */ ++struct audio_karaoke { /* if Vocal1 or Vocal2 are non-zero, they get mixed */ + int vocal1; /* into left and right t at 70% each */ + int vocal2; /* if both, Vocal1 and Vocal2 are non-zero, Vocal1 gets*/ + int melody; /* mixed into the left channel and */ +diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h +index 493a2bf..36a3ed6 100644 +--- a/include/linux/dvb/frontend.h ++++ b/include/linux/dvb/frontend.h +@@ -175,14 +175,20 @@ typedef enum fe_transmit_mode { + TRANSMISSION_MODE_2K, + TRANSMISSION_MODE_8K, + TRANSMISSION_MODE_AUTO, +- TRANSMISSION_MODE_4K ++ TRANSMISSION_MODE_4K, ++ TRANSMISSION_MODE_1K, ++ TRANSMISSION_MODE_16K, ++ TRANSMISSION_MODE_32K, + } fe_transmit_mode_t; + + typedef enum fe_bandwidth { + BANDWIDTH_8_MHZ, + BANDWIDTH_7_MHZ, + BANDWIDTH_6_MHZ, +- BANDWIDTH_AUTO ++ BANDWIDTH_AUTO, ++ BANDWIDTH_5_MHZ, ++ BANDWIDTH_10_MHZ, ++ BANDWIDTH_1_712_MHZ, + } fe_bandwidth_t; + + +@@ -191,7 +197,10 @@ typedef enum fe_guard_interval { + GUARD_INTERVAL_1_16, + GUARD_INTERVAL_1_8, + GUARD_INTERVAL_1_4, +- GUARD_INTERVAL_AUTO ++ GUARD_INTERVAL_AUTO, ++ GUARD_INTERVAL_1_128, ++ GUARD_INTERVAL_19_128, ++ GUARD_INTERVAL_19_256, + } fe_guard_interval_t; + + +@@ -305,7 +314,9 @@ struct dvb_frontend_event { + + #define DTV_ISDBS_TS_ID 42 + +-#define DTV_MAX_COMMAND DTV_ISDBS_TS_ID ++#define DTV_DVBT2_PLP_ID 43 ++ ++#define DTV_MAX_COMMAND DTV_DVBT2_PLP_ID + + typedef enum fe_pilot { + PILOT_ON, +@@ -337,6 +348,7 @@ typedef enum fe_delivery_system { + SYS_DMBTH, + SYS_CMMB, + SYS_DAB, ++ SYS_DVBT2, + } fe_delivery_system_t; + + struct dtv_cmds_h { +diff --git a/include/linux/dvb/version.h b/include/linux/dvb/version.h +index 5a7546c..1421cc8 100644 +--- a/include/linux/dvb/version.h ++++ b/include/linux/dvb/version.h +@@ -24,6 +24,6 @@ + #define _DVBVERSION_H_ + + #define DVB_API_VERSION 5 +-#define DVB_API_VERSION_MINOR 2 ++#define DVB_API_VERSION_MINOR 3 + + #endif /*_DVBVERSION_H_*/ |