Skip to content

Commit

Permalink
[media] tuner-core/simple: get_rf_strength can be tuner mode specific
Browse files Browse the repository at this point in the history
The get_rf_strength op in tuner-simple is valid only for the radio mode.
But due to the way get_signal in analog_demod_ops was designed it would
overwrite the signal value with a bogus value when in TV mode.
Pass a pointer to the signal value instead, and when not in radio mode
leave it alone in the tuner-simple.
This broke in commit 030755b
(tuner-core: call has_signal for both TV and radio) in kernel 3.6. Before
that this was working correctly. That commit did the right thing, but what
wasn't realized at the time was that tuner-simple should have been updated
as well to restrict setting the signal strength to the radio mode only.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Hans Verkuil authored and Mauro Carvalho Chehab committed Apr 14, 2013
1 parent a2192cf commit dfc2e12
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 24 deletions.
2 changes: 1 addition & 1 deletion drivers/media/dvb-core/dvb_frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ struct analog_demod_ops {

void (*set_params)(struct dvb_frontend *fe,
struct analog_parameters *params);
int (*has_signal)(struct dvb_frontend *fe);
int (*has_signal)(struct dvb_frontend *fe, u16 *signal);
int (*get_afc)(struct dvb_frontend *fe, s32 *afc);
void (*tuner_status)(struct dvb_frontend *fe);
void (*standby)(struct dvb_frontend *fe);
Expand Down
15 changes: 9 additions & 6 deletions drivers/media/tuners/tda8290.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,15 +391,16 @@ static void tda8295_agc2_out(struct dvb_frontend *fe, int enable)
tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_val, 2);
}

static int tda8295_has_signal(struct dvb_frontend *fe)
static int tda8295_has_signal(struct dvb_frontend *fe, u16 *signal)
{
struct tda8290_priv *priv = fe->analog_demod_priv;

unsigned char hvpll_stat = 0x26;
unsigned char ret;

tuner_i2c_xfer_send_recv(&priv->i2c_props, &hvpll_stat, 1, &ret, 1);
return (ret & 0x01) ? 65535 : 0;
*signal = (ret & 0x01) ? 65535 : 0;
return 0;
}

/*---------------------------------------------------------------------*/
Expand All @@ -408,7 +409,7 @@ static void tda8295_set_params(struct dvb_frontend *fe,
struct analog_parameters *params)
{
struct tda8290_priv *priv = fe->analog_demod_priv;

u16 signal = 0;
unsigned char blanking_mode[] = { 0x1d, 0x00 };

set_audio(fe, params);
Expand Down Expand Up @@ -436,7 +437,8 @@ static void tda8295_set_params(struct dvb_frontend *fe,
if (priv->cfg.agcf)
priv->cfg.agcf(fe);

if (tda8295_has_signal(fe))
tda8295_has_signal(fe, &signal);
if (signal)
tuner_dbg("tda8295 is locked\n");
else
tuner_dbg("tda8295 not locked, no signal?\n");
Expand All @@ -447,7 +449,7 @@ static void tda8295_set_params(struct dvb_frontend *fe,

/*---------------------------------------------------------------------*/

static int tda8290_has_signal(struct dvb_frontend *fe)
static int tda8290_has_signal(struct dvb_frontend *fe, u16 *signal)
{
struct tda8290_priv *priv = fe->analog_demod_priv;

Expand All @@ -456,7 +458,8 @@ static int tda8290_has_signal(struct dvb_frontend *fe)

tuner_i2c_xfer_send_recv(&priv->i2c_props,
i2c_get_afc, ARRAY_SIZE(i2c_get_afc), &afc, 1);
return (afc & 0x80)? 65535:0;
*signal = (afc & 0x80) ? 65535 : 0;
return 0;
}

/*---------------------------------------------------------------------*/
Expand Down
5 changes: 4 additions & 1 deletion drivers/media/tuners/tuner-simple.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ struct tuner_simple_priv {

u32 frequency;
u32 bandwidth;
bool radio_mode;
};

/* ---------------------------------------------------------------------- */
Expand Down Expand Up @@ -189,7 +190,7 @@ static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
struct tuner_simple_priv *priv = fe->tuner_priv;
int signal;

if (priv->i2c_props.adap == NULL)
if (priv->i2c_props.adap == NULL || !priv->radio_mode)
return -EINVAL;

signal = tuner_signal(tuner_read_status(fe));
Expand Down Expand Up @@ -776,11 +777,13 @@ static int simple_set_params(struct dvb_frontend *fe,

switch (params->mode) {
case V4L2_TUNER_RADIO:
priv->radio_mode = true;
ret = simple_set_radio_freq(fe, params);
priv->frequency = params->frequency * 125 / 2;
break;
case V4L2_TUNER_ANALOG_TV:
case V4L2_TUNER_DIGITAL_TV:
priv->radio_mode = false;
ret = simple_set_tv_freq(fe, params);
priv->frequency = params->frequency * 62500;
break;
Expand Down
29 changes: 13 additions & 16 deletions drivers/media/v4l2-core/tuner-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,16 +218,6 @@ static void fe_standby(struct dvb_frontend *fe)
fe_tuner_ops->sleep(fe);
}

static int fe_has_signal(struct dvb_frontend *fe)
{
u16 strength;

if (fe->ops.tuner_ops.get_rf_strength(fe, &strength) < 0)
return 0;

return strength;
}

static int fe_set_config(struct dvb_frontend *fe, void *priv_cfg)
{
struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
Expand Down Expand Up @@ -436,7 +426,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
sizeof(struct analog_demod_ops));

if (fe_tuner_ops->get_rf_strength)
analog_ops->has_signal = fe_has_signal;
analog_ops->has_signal = fe_tuner_ops->get_rf_strength;
if (fe_tuner_ops->get_afc)
analog_ops->get_afc = fe_tuner_ops->get_afc;

Expand Down Expand Up @@ -1060,9 +1050,12 @@ static void tuner_status(struct dvb_frontend *fe)
if (tuner_status & TUNER_STATUS_STEREO)
tuner_info("Stereo: yes\n");
}
if (analog_ops->has_signal)
tuner_info("Signal strength: %d\n",
analog_ops->has_signal(fe));
if (analog_ops->has_signal) {
u16 signal;

if (!analog_ops->has_signal(fe, &signal))
tuner_info("Signal strength: %hu\n", signal);
}
}

/*
Expand Down Expand Up @@ -1181,8 +1174,12 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
return 0;
if (vt->type == t->mode && analog_ops->get_afc)
analog_ops->get_afc(&t->fe, &vt->afc);
if (analog_ops->has_signal)
vt->signal = analog_ops->has_signal(&t->fe);
if (vt->type == t->mode && analog_ops->has_signal) {
u16 signal = (u16)vt->signal;

if (!analog_ops->has_signal(&t->fe, &signal))
vt->signal = signal;
}
if (vt->type != V4L2_TUNER_RADIO) {
vt->capability |= V4L2_TUNER_CAP_NORM;
vt->rangelow = tv_range[0] * 16;
Expand Down

0 comments on commit dfc2e12

Please sign in to comment.