* DVB Update [PATCH 3/31] frontend core update
@ 2008-09-04 20:23 Manu Abraham
0 siblings, 0 replies; only message in thread
From: Manu Abraham @ 2008-09-04 20:23 UTC (permalink / raw)
To: linux-kernel, v4l-dvb-maintainer, akpm
[-- Attachment #1: Type: text/plain, Size: 511 bytes --]
>From 6a505dda50ecd5eddffdabb79a9a32ccaf9fe29b Mon Sep 17 00:00:00 2001
From: Manu Abraham <manu@linuxtv.org>
Date: Thu, 4 Sep 2008 12:11:15 +0200
Subject: [PATCH] DVB Frontend API update: Frontend core support
* Add support for the new datastuctures and ioctls,
for the updated API
From: Manu Abraham <abraham.manu@gmail.com>
Signed-off-by: Manu Abraham <manu@linuxtv.org>
dvb_frontend.c | 495
+++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 443 insertions(+), 52 deletions(-)
[-- Attachment #2: 3.patch --]
[-- Type: text/x-patch, Size: 24238 bytes --]
>From 6a505dda50ecd5eddffdabb79a9a32ccaf9fe29b Mon Sep 17 00:00:00 2001
From: Manu Abraham <manu@linuxtv.org>
Date: Thu, 4 Sep 2008 12:11:15 +0200
Subject: [PATCH] DVB Frontend API update: Frontend core support
* Add support for the new datastuctures and ioctls,
for the updated API
From: Manu Abraham <abraham.manu@gmail.com>
Signed-off-by: Manu Abraham <manu@linuxtv.org>
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 8cbdb21..da7283c 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -8,6 +8,7 @@
* for convergence integrated media GmbH
*
* Copyright (C) 2004 Andrew de Quincey (tuning thread cleanup)
+ * Copyright (C) Manu Abraham (Multi protocol support)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -95,7 +96,12 @@ struct dvb_frontend_private {
/* thread/frontend values */
struct dvb_device *dvbdev;
+ /* Legacy datatype, superseded by dvbfe_params */
struct dvb_frontend_parameters parameters;
+ /* dvbfe_params supersedes dvb_frontend_parameters */
+ struct dvbfe_params fe_params;
+ struct dvbfe_info fe_info;
+
struct dvb_fe_events events;
struct semaphore sem;
struct list_head list_head;
@@ -124,10 +130,64 @@ struct dvb_frontend_private {
unsigned int step_size;
int quality;
unsigned int check_wrapped;
+
+ enum dvbfe_search algo_status;
};
static void dvb_frontend_wakeup(struct dvb_frontend *fe);
+struct modcod_table {
+ u32 dvbfe_modcod;
+ u32 dvbfe_modulation;
+ u32 dvbfe_fec;
+};
+
+static struct modcod_table dvbs2_modcod_lookup[] = {
+ { DVBFE_MODCOD_DUMMY_PLFRAME, DVBFE_MOD_NONE, DVBFE_FEC_NONE },
+ { DVBFE_MODCOD_QPSK_1_4, DVBFE_MOD_QPSK, DVBFE_FEC_1_4 },
+ { DVBFE_MODCOD_QPSK_1_3, DVBFE_MOD_QPSK, DVBFE_FEC_1_3 },
+ { DVBFE_MODCOD_QPSK_2_5, DVBFE_MOD_QPSK, DVBFE_FEC_2_5 },
+ { DVBFE_MODCOD_QPSK_1_2, DVBFE_MOD_QPSK, DVBFE_FEC_1_2 },
+ { DVBFE_MODCOD_QPSK_3_5, DVBFE_MOD_QPSK, DVBFE_FEC_3_5 },
+ { DVBFE_MODCOD_QPSK_2_3, DVBFE_MOD_QPSK, DVBFE_FEC_2_3 },
+ { DVBFE_MODCOD_QPSK_3_4, DVBFE_MOD_QPSK, DVBFE_FEC_3_4 },
+ { DVBFE_MODCOD_QPSK_4_5, DVBFE_MOD_QPSK, DVBFE_FEC_4_5 },
+ { DVBFE_MODCOD_QPSK_5_6, DVBFE_MOD_QPSK, DVBFE_FEC_5_6 },
+ { DVBFE_MODCOD_QPSK_8_9, DVBFE_MOD_QPSK, DVBFE_FEC_8_9 },
+ { DVBFE_MODCOD_QPSK_9_10, DVBFE_MOD_QPSK, DVBFE_FEC_9_10 },
+ { DVBFE_MODCOD_8PSK_3_5, DVBFE_MOD_8PSK, DVBFE_FEC_3_5 },
+ { DVBFE_MODCOD_8PSK_2_3, DVBFE_MOD_8PSK, DVBFE_FEC_2_3 },
+ { DVBFE_MODCOD_8PSK_3_4, DVBFE_MOD_8PSK, DVBFE_FEC_3_4 },
+ { DVBFE_MODCOD_8PSK_5_6, DVBFE_MOD_8PSK, DVBFE_FEC_5_6 },
+ { DVBFE_MODCOD_8PSK_8_9, DVBFE_MOD_8PSK, DVBFE_FEC_8_9 },
+ { DVBFE_MODCOD_8PSK_9_10, DVBFE_MOD_8PSK, DVBFE_FEC_9_10 },
+ { DVBFE_MODCOD_16APSK_2_3, DVBFE_MOD_16APSK, DVBFE_FEC_2_3 },
+ { DVBFE_MODCOD_16APSK_3_4, DVBFE_MOD_16APSK, DVBFE_FEC_3_4 },
+ { DVBFE_MODCOD_16APSK_4_5, DVBFE_MOD_16APSK, DVBFE_FEC_4_5 },
+ { DVBFE_MODCOD_16APSK_5_6, DVBFE_MOD_16APSK, DVBFE_FEC_5_6 },
+ { DVBFE_MODCOD_16APSK_8_9, DVBFE_MOD_16APSK, DVBFE_FEC_8_9 },
+ { DVBFE_MODCOD_16APSK_9_10, DVBFE_MOD_16APSK, DVBFE_FEC_9_10 },
+ { DVBFE_MODCOD_32APSK_3_4, DVBFE_MOD_32APSK, DVBFE_FEC_3_4 },
+ { DVBFE_MODCOD_32APSK_4_5, DVBFE_MOD_32APSK, DVBFE_FEC_4_5 },
+ { DVBFE_MODCOD_32APSK_5_6, DVBFE_MOD_32APSK, DVBFE_FEC_5_6 },
+ { DVBFE_MODCOD_32APSK_8_9, DVBFE_MOD_32APSK, DVBFE_FEC_8_9 },
+ { DVBFE_MODCOD_32APSK_9_10, DVBFE_MOD_32APSK, DVBFE_FEC_9_10 },
+ { DVBFE_MODCOD_RESERVED_1, DVBFE_MOD_NONE, DVBFE_FEC_NONE },
+ { DVBFE_MODCOD_BPSK_1_3, DVBFE_MOD_BPSK, DVBFE_FEC_1_3 },
+ { DVBFE_MODCOD_BPSK_1_4, DVBFE_MOD_BPSK, DVBFE_FEC_1_4 },
+ { DVBFE_MODCOD_RESERVED_2, DVBFE_MOD_NONE, DVBFE_FEC_NONE }
+};
+
+void decode_dvbs2_modcod(u32 dvbfe_modcod,
+ enum dvbfe_modulation *modulation,
+ enum dvbfe_fec *fec)
+{
+ BUG_ON(dvbfe_modcod >= ARRAY_SIZE(dvbs2_modcod_lookup));
+ *modulation = dvbs2_modcod_lookup[dvbfe_modcod].dvbfe_modulation;
+ *fec = dvbs2_modcod_lookup[dvbfe_modcod].dvbfe_fec;
+}
+EXPORT_SYMBOL(decode_dvbs2_modcod);
+
static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
@@ -149,12 +209,21 @@ 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 (fe->legacy)
+ memcpy(&e->parameters, &fepriv->parameters, sizeof (struct dvb_frontend_parameters));
+ else
+ memcpy(&e->fe_params, &fepriv->fe_params, sizeof (struct dvbfe_params));
- if (status & FE_HAS_LOCK)
- if (fe->ops.get_frontend)
- fe->ops.get_frontend(fe, &e->parameters);
+ if (fe->legacy) {
+ /* Legacy */
+ if (status & FE_HAS_LOCK)
+ if (fe->ops.get_frontend)
+ fe->ops.get_frontend(fe, &e->parameters);
+ } else {
+ if (status & FE_HAS_LOCK)
+ if (fe->ops.get_params)
+ fe->ops.get_params(fe, &e->fe_params);
+ }
events->eventw = wp;
@@ -165,6 +234,73 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
wake_up_interruptible (&events->wait_queue);
}
+static int dvbfe_sanity_check(struct dvb_frontend *fe)
+{
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+ /* Sanity checks */
+ if ((fepriv->fe_params.frequency < fepriv->fe_info.frequency_min) ||
+ (fepriv->fe_params.frequency > fepriv->fe_info.frequency_max))
+ return -EINVAL;
+
+ switch (fepriv->fe_params.delivery) {
+ case DVBFE_DELSYS_DVBS:
+ if (!(fepriv->fe_params.delsys.dvbs.modulation &
+ fepriv->fe_info.delsys.dvbs.modulation))
+ return -EINVAL;
+ if (!(fepriv->fe_params.delsys.dvbs.fec &
+ fepriv->fe_info.delsys.dvbs.fec))
+ return -EINVAL;
+ break;
+ case DVBFE_DELSYS_DVBS2:
+ if (!(fepriv->fe_params.delsys.dvbs2.modulation &
+ fepriv->fe_info.delsys.dvbs2.modulation))
+ return -EINVAL;
+ if (!(fepriv->fe_params.delsys.dvbs2.fec &
+ fepriv->fe_info.delsys.dvbs2.fec))
+ return -EINVAL;
+ break;
+ case DVBFE_DELSYS_DSS:
+ if (!(fepriv->fe_params.delsys.dss.modulation &
+ fepriv->fe_info.delsys.dss.modulation))
+ return -EINVAL;
+ if (!(fepriv->fe_params.delsys.dss.fec &
+ fepriv->fe_info.delsys.dss.fec))
+ return -EINVAL;
+ break;
+ case DVBFE_DELSYS_DVBC:
+ if (!(fepriv->fe_params.delsys.dvbc.modulation &
+ fepriv->fe_info.delsys.dvbc.modulation))
+ return -EINVAL;
+ break;
+ case DVBFE_DELSYS_DVBT:
+ if (!(fepriv->fe_params.delsys.dvbt.constellation &
+ fepriv->fe_info.delsys.dvbt.modulation))
+ return -EINVAL;
+ if (!(fepriv->fe_params.delsys.dvbt.priority &
+ fepriv->fe_info.delsys.dvbt.stream_priority))
+ return -EINVAL;
+ break;
+ case DVBFE_DELSYS_DVBH:
+ if (!(fepriv->fe_params.delsys.dvbh.constellation &
+ fepriv->fe_info.delsys.dvbh.modulation))
+ return -EINVAL;
+ if (!(fepriv->fe_params.delsys.dvbh.priority &
+ fepriv->fe_info.delsys.dvbh.stream_priority))
+ return -EINVAL;
+ break;
+ case DVBFE_DELSYS_ATSC:
+ if (!(fepriv->fe_params.delsys.atsc.modulation &
+ fepriv->fe_info.delsys.atsc.modulation))
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int dvb_frontend_get_event(struct dvb_frontend *fe,
struct dvb_frontend_event *event, int flags)
{
@@ -261,13 +397,29 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
{
int autoinversion;
int ready = 0;
+ int original_inversion;
+ u32 original_frequency;
+
struct dvb_frontend_private *fepriv = fe->frontend_priv;
- int original_inversion = fepriv->parameters.inversion;
- u32 original_frequency = fepriv->parameters.frequency;
- /* are we using autoinversion? */
- autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
- (fepriv->parameters.inversion == INVERSION_AUTO));
+ if (fe->legacy) {
+ /* Legacy */
+ original_inversion = fepriv->parameters.inversion;
+ original_frequency = fepriv->parameters.frequency;
+ /* are we using autoinversion ? */
+ /* Legacy */
+ autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
+ (fepriv->parameters.inversion == INVERSION_AUTO));
+ } else {
+ /* Superseding */
+ original_inversion = fepriv->fe_params.inversion;
+ original_frequency = fepriv->fe_params.frequency;
+ if (fe->ops.get_info) {
+ fe->ops.get_info(fe, &fepriv->fe_info);
+ }
+ autoinversion = ((!(fepriv->fe_info.inversion & INVERSION_AUTO)) &&
+ (fepriv->fe_params.inversion == INVERSION_AUTO));
+ }
/* setup parameters correctly */
while(!ready) {
@@ -330,17 +482,46 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
dprintk("%s: drift:%i inversion:%i auto_step:%i "
"auto_sub_step:%i started_auto_step:%i\n",
__func__, fepriv->lnb_drift, fepriv->inversion,
- fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step);
+ fepriv->auto_step, fepriv->auto_sub_step,
+ fepriv->started_auto_step);
- /* set the frontend itself */
- fepriv->parameters.frequency += fepriv->lnb_drift;
- if (autoinversion)
- fepriv->parameters.inversion = fepriv->inversion;
- if (fe->ops.set_frontend)
- fe->ops.set_frontend(fe, &fepriv->parameters);
+ /* set the frontend itself */
+ /* Legacy */
+ if (fe->legacy)
+ fepriv->parameters.frequency += fepriv->lnb_drift;
+ else
+ /* Supeseding */
+ fepriv->fe_params.frequency += fepriv->lnb_drift;
- fepriv->parameters.frequency = original_frequency;
- fepriv->parameters.inversion = original_inversion;
+ if (autoinversion) {
+ /* Legacy */
+ if (fe->legacy)
+ fepriv->parameters.inversion = fepriv->inversion;
+ else
+ /* Superseding */
+ fepriv->fe_params.inversion = fepriv->inversion;
+ }
+ /* Legacy */
+ if (fe->legacy) {
+ if (fe->ops.set_frontend)
+ fe->ops.set_frontend(fe, &fepriv->parameters);
+ } else {
+// if ((dvbfe_sanity_check(fe) == 0)) {
+ /* Superseding */
+ if (fe->ops.set_params)
+ fe->ops.set_params(fe, &fepriv->fe_params);
+// } else
+// return -EINVAL;
+ }
+ /* Legacy */
+ if (fe->legacy) {
+ fepriv->parameters.frequency = original_frequency;
+ fepriv->parameters.inversion = original_inversion;
+ } else {
+ /* Superseding */
+ fepriv->fe_params.frequency = original_frequency;
+ fepriv->fe_params.inversion = original_inversion;
+ }
fepriv->auto_sub_step++;
return 0;
@@ -355,19 +536,30 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
if (fepriv->state & FESTATE_IDLE) {
fepriv->delay = 3*HZ;
fepriv->quality = 0;
- return;
+ return 0;
}
/* in SCAN mode, we just set the frontend when asked and leave it alone */
if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) {
if (fepriv->state & FESTATE_RETUNE) {
- if (fe->ops.set_frontend)
- fe->ops.set_frontend(fe, &fepriv->parameters);
+
+ if (fe->legacy) {
+ /* Legacy */
+ if (fe->ops.set_frontend)
+ fe->ops.set_frontend(fe, &fepriv->parameters);
+ } else {
+ if (dvbfe_sanity_check(fe) == 0) {
+ /* Superseding */
+ if (fe->ops.set_params)
+ fe->ops.set_params(fe, &fepriv->fe_params);
+ } else
+ return -EINVAL;
+ }
fepriv->state = FESTATE_TUNED;
}
fepriv->delay = 3*HZ;
fepriv->quality = 0;
- return;
+ return 0;
}
/* get the frontend status */
@@ -388,11 +580,22 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
fepriv->state = FESTATE_TUNED;
/* 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;
+ /* Legacy */
+ if (fe->legacy) {
+ if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
+ (fepriv->parameters.inversion == INVERSION_AUTO)) {
+ fepriv->parameters.inversion = fepriv->inversion;
+ }
+ } else {
+ /* Superseding */
+ if (fe->ops.get_info) {
+ fe->ops.get_info(fe, &fepriv->fe_info);
+ if ((!(fepriv->fe_info.inversion & INVERSION_AUTO)) &&
+ (fepriv->fe_params.inversion == INVERSION_AUTO))
+ fepriv->fe_params.inversion = fepriv->inversion;
+ }
}
- return;
+ return 0;
}
/* if we are tuned already, check we're still locked */
@@ -401,7 +604,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
/* we're tuned, and the lock is still good... */
if (s & FE_HAS_LOCK) {
- return;
+ return 0;
} else { /* if we _WERE_ tuned, but now don't have a lock */
fepriv->state = FESTATE_ZIGZAG_FAST;
fepriv->started_auto_step = fepriv->auto_step;
@@ -410,24 +613,43 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
}
/* don't actually do anything if we're in the LOSTLOCK state,
- * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
- if ((fepriv->state & FESTATE_LOSTLOCK) &&
- (fe->ops.info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
- dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
- return;
+ * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0
+ */
+ /* Legacy */
+ if (fe->legacy) {
+ if ((fepriv->state & FESTATE_LOSTLOCK) && (fepriv->max_drift == 0)) {
+ if (fe->ops.get_frontend_algo)
+ if (fe->ops.get_frontend_algo(fe) == DVBFE_ALGO_RECOVERY)
+ dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+
+ return 0;
+ }
+ } else {
+ if (fepriv->state & FESTATE_LOSTLOCK) {
+ if (fe->ops.get_frontend_algo) {
+ if ((fe->ops.get_frontend_algo(fe) == DVBFE_ALGO_RECOVERY) &&
+ (fepriv->max_drift == 0)) {
+
+ dvb_frontend_swzigzag_update_delay(fepriv, s & DVBFE_HAS_LOCK);
+ return 0;
+ }
+ }
+ }
}
/* don't do anything if we're in the DISEQC state, since this
* might be someone with a motorized dish controlled by DISEQC.
- * If its actually a re-tune, there will be a SET_FRONTEND soon enough. */
+ * If its actually a re-tune, there will be a SET_FRONTEND soon enough.
+ */
if (fepriv->state & FESTATE_DISEQC) {
dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
- return;
+ return 0;
}
/* if we're in the RETUNE state, set everything up for a brand
* new scan, keeping the current inversion setting, as the next
- * tune is _very_ likely to require the same */
+ * tune is _very_ likely to require the same
+ */
if (fepriv->state & FESTATE_RETUNE) {
fepriv->lnb_drift = 0;
fepriv->auto_step = 0;
@@ -443,17 +665,19 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
/* peform a tune */
if (dvb_frontend_swzigzag_autotune(fe, fepriv->check_wrapped)) {
/* OK, if we've run out of trials at the fast speed.
- * Drop back to slow for the _next_ attempt */
+ * Drop back to slow for the _next_ attempt
+ */
fepriv->state = FESTATE_SEARCHING_SLOW;
fepriv->started_auto_step = fepriv->auto_step;
- return;
+ return 0;
}
fepriv->check_wrapped = 1;
/* if we've just retuned, enter the ZIGZAG_FAST state.
* This ensures we cannot return from an
* FE_SET_FRONTEND ioctl before the first frontend tune
- * occurs */
+ * occurs
+ */
if (fepriv->state & FESTATE_RETUNE) {
fepriv->state = FESTATE_TUNING_FAST;
}
@@ -464,9 +688,12 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
/* Note: don't bother checking for wrapping; we stay in this
- * state until we get a lock */
+ * state until we get a lock
+ */
dvb_frontend_swzigzag_autotune(fe, 0);
}
+
+ return 0;
}
static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
@@ -509,7 +736,13 @@ static int dvb_frontend_thread(void *data)
struct dvb_frontend_private *fepriv = fe->frontend_priv;
unsigned long timeout;
fe_status_t s;
+
+ enum dvbfe_algo algo;
+
+ /* Legacy datatype */
struct dvb_frontend_parameters *params;
+ /* Superseding datatype */
+ struct dvbfe_params *fe_params = &fepriv->fe_params;
dprintk("%s\n", __func__);
@@ -555,23 +788,78 @@ restart:
/* do an iteration of the tuning loop */
if (fe->ops.get_frontend_algo) {
- if (fe->ops.get_frontend_algo(fe) == FE_ALGO_HW) {
- /* have we been asked to retune? */
- params = NULL;
+ algo = fe->ops.get_frontend_algo(fe);
+ switch (algo) {
+ case DVBFE_ALGO_HW:
+ dprintk("%s: Frontend ALGO = DVBFE_ALGO_HW\n", __func__);
+ params = NULL; /* have we been asked to RETUNE ? */
+
if (fepriv->state & FESTATE_RETUNE) {
+ dprintk("%s: Retune requested, FESTAT_RETUNE\n", __func__);
params = &fepriv->parameters;
fepriv->state = FESTATE_TUNED;
}
-
- fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
+ if (fe->ops.tune) {
+ fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
+ dprintk("%s: TUNE callback exists at 0x%p\n", __func__, fe->ops.tune);
+ }
if (s != fepriv->status) {
+ dprintk("%s: state changed, adding current state\n", __func__);
dvb_frontend_add_event(fe, s);
fepriv->status = s;
}
- } else
+ break;
+ case DVBFE_ALGO_SW:
+ dprintk("%s: Frontend ALGO = DVBFE_ALGO_SW\n", __func__);
dvb_frontend_swzigzag(fe);
- } else
+ 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__);
+ fe_params = &fepriv->fe_params;
+ fepriv->state = FESTATE_TUNED;
+ }
+ /* Case where we are going to search for a carrier
+ *
+ * User asked us to retune again for some reason, possibly
+ * requesting a search with a new set of parameters
+ */
+ if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) {
+ if (fe->ops.search) {
+ fepriv->algo_status = fe->ops.search(fe, fe_params);
+ dprintk("%s: SEARCH callback exists at 0x%p\n", __func__, fe->ops.search);
+ /* We did do a search as was requested, the flags are
+ * now unset as well and has the flags wrt to search.
+ */
+ }
+ fepriv->algo_status &= ~DVBFE_ALGO_SEARCH_AGAIN;
+ }
+ /* Track the carrier if the search was successful */
+ if (fepriv->algo_status == DVBFE_ALGO_SEARCH_SUCCESS) {
+ if (fepriv->algo_status & DVBFE_ALGO_SEARCH_SUCCESS)
+ dprintk("%s: status = DVBFE_ALGO_SEARCH_SUCCESS\n", __func__);
+ if (fepriv->algo_status & DVBFE_ALGO_SEARCH_FAILED)
+ fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
+
+ fe->ops.read_status(fe, &s);
+ dvb_frontend_add_event(fe, s); /* update event list */
+ fepriv->status = s;
+ if (fe->ops.track) {
+ dprintk("%s: TRACK callback exists at 0x%p\n", __func__, fe->ops.track);
+ fe->ops.track(fe, fe_params);
+ }
+ }
+ break;
+ default:
+ dprintk("%s: UNDEFINED ALGO !\n", __func__);
+ break;
+ }
+
+ } else {
dvb_frontend_swzigzag(fe);
+ }
}
if (dvb_powerdown_on_sleep) {
@@ -589,6 +877,7 @@ restart:
fepriv->thread = NULL;
mb();
+ dprintk("%s: frontend_wakeup\n", __func__);
dvb_frontend_wakeup(fe);
return 0;
}
@@ -762,6 +1051,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
struct dvb_frontend *fe = dvbdev->priv;
struct dvb_frontend_private *fepriv = fe->frontend_priv;
int err = -EOPNOTSUPP;
+ enum dvbfe_delsys delsys = 0;
dprintk ("%s\n", __func__);
@@ -947,12 +1237,10 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
break;
}
- memcpy (&fepriv->parameters, parg,
- sizeof (struct dvb_frontend_parameters));
-
+ fe->legacy = 1;
+ memcpy(&fepriv->parameters, parg, sizeof (struct dvb_frontend_parameters));
memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
- memcpy(&fetunesettings.parameters, parg,
- sizeof (struct dvb_frontend_parameters));
+ memcpy(&fetunesettings.parameters, parg, sizeof (struct dvb_frontend_parameters));
/* force auto frequency inversion if requested */
if (dvb_force_auto_inversion) {
@@ -1015,6 +1303,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
break;
case FE_GET_FRONTEND:
+ fe->legacy = 1;
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);
@@ -1025,6 +1314,108 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
fepriv->tune_mode_flags = (unsigned long) parg;
err = 0;
break;
+
+ case DVBFE_SET_PARAMS: {
+ struct dvb_frontend_tune_settings fetunesettings;
+
+ fe->legacy = 0;
+ memcpy(&fepriv->fe_params, parg, sizeof (struct dvbfe_params));
+ memset(&fetunesettings, 0, sizeof (struct dvb_frontend_tune_settings));
+ memcpy(&fetunesettings.fe_params, parg, sizeof (struct dvbfe_params));
+
+ /* Request the search algorithm to search */
+ fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
+
+ /* force auto frequency inversion if requested */
+ if (dvb_force_auto_inversion) {
+ fepriv->fe_params.inversion = DVBFE_INVERSION_AUTO;
+ fetunesettings.fe_params.inversion = DVBFE_INVERSION_AUTO;
+ }
+ if (fe->ops.get_delsys) {
+ fe->ops.get_delsys(fe, &delsys);
+ if ((delsys == DVBFE_DELSYS_DVBT) ||
+ (delsys == DVBFE_DELSYS_DVBH)) {
+
+ /* without hierachical coding code_rate_LP is irrelevant,
+ * so we tolerate the otherwise invalid FEC_NONE setting */
+ if (fepriv->fe_params.delsys.dvbt.hierarchy == DVBFE_HIERARCHY_OFF &&
+ fepriv->fe_params.delsys.dvbt.code_rate_LP == DVBFE_FEC_NONE)
+
+ fepriv->fe_params.delsys.dvbt.code_rate_LP = DVBFE_FEC_AUTO;
+ }
+ }
+
+ /* get frontend-specific tuning settings */
+ if (fe->ops.get_tune_settings &&
+ (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) {
+
+ fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
+ fepriv->max_drift = fetunesettings.max_drift;
+ fepriv->step_size = fetunesettings.step_size;
+ } else {
+ /* default values */
+ switch (fepriv->fe_info.delivery) {
+ case DVBFE_DELSYS_DVBS:
+ case DVBFE_DELSYS_DSS:
+ case DVBFE_DELSYS_DVBS2:
+ fepriv->min_delay = HZ / 20;
+ fepriv->step_size = fepriv->fe_params.delsys.dvbs.symbol_rate / 16000;
+ fepriv->max_drift = fepriv->fe_params.delsys.dvbs.symbol_rate / 2000;
+ break;
+ case DVBFE_DELSYS_DVBC:
+ fepriv->min_delay = HZ / 20;
+ fepriv->step_size = 0; /* no zigzag */
+ fepriv->max_drift = 0;
+ break;
+ case DVBFE_DELSYS_DVBT:
+ case DVBFE_DELSYS_DVBH:
+ fepriv->min_delay = HZ / 20;
+ fepriv->step_size = fepriv->fe_info.frequency_step * 2;
+ fepriv->max_drift = (fepriv->fe_info.frequency_step * 2) + 1;
+ break;
+ case DVBFE_DELSYS_ATSC:
+ fepriv->min_delay = HZ / 20;
+ fepriv->step_size = 0;
+ fepriv->max_drift = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ if (dvb_override_tune_delay > 0)
+ fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000;
+
+ fepriv->state = FESTATE_RETUNE;
+ printk("%s: FESTATE_RETUNE: fepriv->state=%d\n", __func__, fepriv->state);
+ dvb_frontend_wakeup(fe);
+ dvb_frontend_add_event(fe, 0);
+ fepriv->status = 0;
+ err = 0;
+ break;
+ }
+
+ case DVBFE_GET_PARAMS:
+ fe->legacy = 0;
+ if (fe->ops.get_params) {
+ memcpy(parg, &fepriv->fe_params, sizeof (struct dvbfe_params));
+ err = fe->ops.get_params(fe, (struct dvbfe_params *) parg);
+ }
+ break;
+ case DVBFE_GET_DELSYS:
+ fe->legacy = 0;
+ if (fe->ops.get_delsys) {
+ err = fe->ops.get_delsys(fe, (enum dvbfe_delsys *) parg);
+ }
+ break;
+ case DVBFE_GET_INFO:
+ printk("%s: DVBFE_GET_INFO\n", __func__);
+ fe->legacy = 0;
+ if (fe->ops.get_info) {
+ memcpy(&fepriv->fe_info, (struct dvbfe_info *) parg, sizeof (struct dvbfe_info));
+ err = fe->ops.get_info(fe, &fepriv->fe_info);
+ memcpy((struct dvbfe_info *) parg, &fepriv->fe_info, sizeof (struct dvbfe_info));
+ }
+ break;
};
up (&fepriv->sem);
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2008-09-04 20:24 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-04 20:23 DVB Update [PATCH 3/31] frontend core update Manu Abraham
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.