[media] tuner-core/tda9887: get_afc can be tuner mode specific
The get_afc op in tda9887 is valid only for the radio mode.
But due to the way get_afc in analog_demod_ops was designed it would
overwrite the afc value with a bogus value when in TV mode.
Pass a pointer to the afc value instead, and when not in radio mode
leave it alone in the tda9887.
This broke a long time ago in 2.6.19 when the get_afc op was introduced.
Before that the afc was only set for radio mode in the tda9887.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
diff --git a/drivers/media/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h
index b34922a..44fad1c 100644
--- a/drivers/media/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb-core/dvb_frontend.h
@@ -246,7 +246,7 @@
void (*set_params)(struct dvb_frontend *fe,
struct analog_parameters *params);
int (*has_signal)(struct dvb_frontend *fe);
- int (*get_afc)(struct dvb_frontend *fe);
+ int (*get_afc)(struct dvb_frontend *fe, s32 *afc);
void (*tuner_status)(struct dvb_frontend *fe);
void (*standby)(struct dvb_frontend *fe);
void (*release)(struct dvb_frontend *fe);
diff --git a/drivers/media/tuners/tda9887.c b/drivers/media/tuners/tda9887.c
index cdb645d..300005c 100644
--- a/drivers/media/tuners/tda9887.c
+++ b/drivers/media/tuners/tda9887.c
@@ -596,22 +596,22 @@
priv->data[1], priv->data[2], priv->data[3]);
}
-static int tda9887_get_afc(struct dvb_frontend *fe)
+static int tda9887_get_afc(struct dvb_frontend *fe, s32 *afc)
{
struct tda9887_priv *priv = fe->analog_demod_priv;
- static int AFC_BITS_2_kHz[] = {
+ static const int AFC_BITS_2_kHz[] = {
-12500, -37500, -62500, -97500,
-112500, -137500, -162500, -187500,
187500, 162500, 137500, 112500,
97500 , 62500, 37500 , 12500
};
- int afc=0;
__u8 reg = 0;
- if (1 == tuner_i2c_xfer_recv(&priv->i2c_props,®,1))
- afc = AFC_BITS_2_kHz[(reg>>1)&0x0f];
-
- return afc;
+ if (priv->mode != V4L2_TUNER_RADIO)
+ return 0;
+ if (1 == tuner_i2c_xfer_recv(&priv->i2c_props, ®, 1))
+ *afc = AFC_BITS_2_kHz[(reg >> 1) & 0x0f];
+ return 0;
}
static void tda9887_standby(struct dvb_frontend *fe)
diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c
index 7d60c5d..a0b10e6 100644
--- a/drivers/media/v4l2-core/tuner-core.c
+++ b/drivers/media/v4l2-core/tuner-core.c
@@ -228,16 +228,6 @@
return strength;
}
-static int fe_get_afc(struct dvb_frontend *fe)
-{
- s32 afc;
-
- if (fe->ops.tuner_ops.get_afc(fe, &afc) < 0)
- return 0;
-
- return afc;
-}
-
static int fe_set_config(struct dvb_frontend *fe, void *priv_cfg)
{
struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
@@ -448,7 +438,7 @@
if (fe_tuner_ops->get_rf_strength)
analog_ops->has_signal = fe_has_signal;
if (fe_tuner_ops->get_afc)
- analog_ops->get_afc = fe_get_afc;
+ analog_ops->get_afc = fe_tuner_ops->get_afc;
} else {
t->name = analog_ops->info.name;
@@ -1190,7 +1180,7 @@
if (check_mode(t, vt->type) == -EINVAL)
return 0;
if (vt->type == t->mode && analog_ops->get_afc)
- vt->afc = analog_ops->get_afc(&t->fe);
+ analog_ops->get_afc(&t->fe, &vt->afc);
if (analog_ops->has_signal)
vt->signal = analog_ops->has_signal(&t->fe);
if (vt->type != V4L2_TUNER_RADIO) {