aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2013-04-06 03:41:29 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-04-14 18:44:50 -0400
commitdfc2e12df02d49a1567bc90989ceef870cf5b147 (patch)
tree772748f182a85c71d118f94c8e38a2a8ef05f8f7
parenta2192cf47f593681cd65798880853c5224066c81 (diff)
[media] tuner-core/simple: get_rf_strength can be tuner mode specific
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 030755bde42bbed133182b0ece7c7a9c759478e8 (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>
-rw-r--r--drivers/media/dvb-core/dvb_frontend.h2
-rw-r--r--drivers/media/tuners/tda8290.c15
-rw-r--r--drivers/media/tuners/tuner-simple.c5
-rw-r--r--drivers/media/v4l2-core/tuner-core.c29
4 files changed, 27 insertions, 24 deletions
diff --git a/drivers/media/dvb-core/dvb_frontend.h b/drivers/media/dvb-core/dvb_frontend.h
index 44fad1cbcb09..371b6caf486c 100644
--- a/drivers/media/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb-core/dvb_frontend.h
@@ -245,7 +245,7 @@ struct analog_demod_ops {
245 245
246 void (*set_params)(struct dvb_frontend *fe, 246 void (*set_params)(struct dvb_frontend *fe,
247 struct analog_parameters *params); 247 struct analog_parameters *params);
248 int (*has_signal)(struct dvb_frontend *fe); 248 int (*has_signal)(struct dvb_frontend *fe, u16 *signal);
249 int (*get_afc)(struct dvb_frontend *fe, s32 *afc); 249 int (*get_afc)(struct dvb_frontend *fe, s32 *afc);
250 void (*tuner_status)(struct dvb_frontend *fe); 250 void (*tuner_status)(struct dvb_frontend *fe);
251 void (*standby)(struct dvb_frontend *fe); 251 void (*standby)(struct dvb_frontend *fe);
diff --git a/drivers/media/tuners/tda8290.c b/drivers/media/tuners/tda8290.c
index 20cc7dad6b4e..ab4106c17b4c 100644
--- a/drivers/media/tuners/tda8290.c
+++ b/drivers/media/tuners/tda8290.c
@@ -391,7 +391,7 @@ static void tda8295_agc2_out(struct dvb_frontend *fe, int enable)
391 tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_val, 2); 391 tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_val, 2);
392} 392}
393 393
394static int tda8295_has_signal(struct dvb_frontend *fe) 394static int tda8295_has_signal(struct dvb_frontend *fe, u16 *signal)
395{ 395{
396 struct tda8290_priv *priv = fe->analog_demod_priv; 396 struct tda8290_priv *priv = fe->analog_demod_priv;
397 397
@@ -399,7 +399,8 @@ static int tda8295_has_signal(struct dvb_frontend *fe)
399 unsigned char ret; 399 unsigned char ret;
400 400
401 tuner_i2c_xfer_send_recv(&priv->i2c_props, &hvpll_stat, 1, &ret, 1); 401 tuner_i2c_xfer_send_recv(&priv->i2c_props, &hvpll_stat, 1, &ret, 1);
402 return (ret & 0x01) ? 65535 : 0; 402 *signal = (ret & 0x01) ? 65535 : 0;
403 return 0;
403} 404}
404 405
405/*---------------------------------------------------------------------*/ 406/*---------------------------------------------------------------------*/
@@ -408,7 +409,7 @@ static void tda8295_set_params(struct dvb_frontend *fe,
408 struct analog_parameters *params) 409 struct analog_parameters *params)
409{ 410{
410 struct tda8290_priv *priv = fe->analog_demod_priv; 411 struct tda8290_priv *priv = fe->analog_demod_priv;
411 412 u16 signal = 0;
412 unsigned char blanking_mode[] = { 0x1d, 0x00 }; 413 unsigned char blanking_mode[] = { 0x1d, 0x00 };
413 414
414 set_audio(fe, params); 415 set_audio(fe, params);
@@ -436,7 +437,8 @@ static void tda8295_set_params(struct dvb_frontend *fe,
436 if (priv->cfg.agcf) 437 if (priv->cfg.agcf)
437 priv->cfg.agcf(fe); 438 priv->cfg.agcf(fe);
438 439
439 if (tda8295_has_signal(fe)) 440 tda8295_has_signal(fe, &signal);
441 if (signal)
440 tuner_dbg("tda8295 is locked\n"); 442 tuner_dbg("tda8295 is locked\n");
441 else 443 else
442 tuner_dbg("tda8295 not locked, no signal?\n"); 444 tuner_dbg("tda8295 not locked, no signal?\n");
@@ -447,7 +449,7 @@ static void tda8295_set_params(struct dvb_frontend *fe,
447 449
448/*---------------------------------------------------------------------*/ 450/*---------------------------------------------------------------------*/
449 451
450static int tda8290_has_signal(struct dvb_frontend *fe) 452static int tda8290_has_signal(struct dvb_frontend *fe, u16 *signal)
451{ 453{
452 struct tda8290_priv *priv = fe->analog_demod_priv; 454 struct tda8290_priv *priv = fe->analog_demod_priv;
453 455
@@ -456,7 +458,8 @@ static int tda8290_has_signal(struct dvb_frontend *fe)
456 458
457 tuner_i2c_xfer_send_recv(&priv->i2c_props, 459 tuner_i2c_xfer_send_recv(&priv->i2c_props,
458 i2c_get_afc, ARRAY_SIZE(i2c_get_afc), &afc, 1); 460 i2c_get_afc, ARRAY_SIZE(i2c_get_afc), &afc, 1);
459 return (afc & 0x80)? 65535:0; 461 *signal = (afc & 0x80) ? 65535 : 0;
462 return 0;
460} 463}
461 464
462/*---------------------------------------------------------------------*/ 465/*---------------------------------------------------------------------*/
diff --git a/drivers/media/tuners/tuner-simple.c b/drivers/media/tuners/tuner-simple.c
index 39e7e583c8c0..ca274c2d8c70 100644
--- a/drivers/media/tuners/tuner-simple.c
+++ b/drivers/media/tuners/tuner-simple.c
@@ -115,6 +115,7 @@ struct tuner_simple_priv {
115 115
116 u32 frequency; 116 u32 frequency;
117 u32 bandwidth; 117 u32 bandwidth;
118 bool radio_mode;
118}; 119};
119 120
120/* ---------------------------------------------------------------------- */ 121/* ---------------------------------------------------------------------- */
@@ -189,7 +190,7 @@ static int simple_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
189 struct tuner_simple_priv *priv = fe->tuner_priv; 190 struct tuner_simple_priv *priv = fe->tuner_priv;
190 int signal; 191 int signal;
191 192
192 if (priv->i2c_props.adap == NULL) 193 if (priv->i2c_props.adap == NULL || !priv->radio_mode)
193 return -EINVAL; 194 return -EINVAL;
194 195
195 signal = tuner_signal(tuner_read_status(fe)); 196 signal = tuner_signal(tuner_read_status(fe));
@@ -776,11 +777,13 @@ static int simple_set_params(struct dvb_frontend *fe,
776 777
777 switch (params->mode) { 778 switch (params->mode) {
778 case V4L2_TUNER_RADIO: 779 case V4L2_TUNER_RADIO:
780 priv->radio_mode = true;
779 ret = simple_set_radio_freq(fe, params); 781 ret = simple_set_radio_freq(fe, params);
780 priv->frequency = params->frequency * 125 / 2; 782 priv->frequency = params->frequency * 125 / 2;
781 break; 783 break;
782 case V4L2_TUNER_ANALOG_TV: 784 case V4L2_TUNER_ANALOG_TV:
783 case V4L2_TUNER_DIGITAL_TV: 785 case V4L2_TUNER_DIGITAL_TV:
786 priv->radio_mode = false;
784 ret = simple_set_tv_freq(fe, params); 787 ret = simple_set_tv_freq(fe, params);
785 priv->frequency = params->frequency * 62500; 788 priv->frequency = params->frequency * 62500;
786 break; 789 break;
diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c
index a0b10e6b55ed..ddc9379eb276 100644
--- a/drivers/media/v4l2-core/tuner-core.c
+++ b/drivers/media/v4l2-core/tuner-core.c
@@ -218,16 +218,6 @@ static void fe_standby(struct dvb_frontend *fe)
218 fe_tuner_ops->sleep(fe); 218 fe_tuner_ops->sleep(fe);
219} 219}
220 220
221static int fe_has_signal(struct dvb_frontend *fe)
222{
223 u16 strength;
224
225 if (fe->ops.tuner_ops.get_rf_strength(fe, &strength) < 0)
226 return 0;
227
228 return strength;
229}
230
231static int fe_set_config(struct dvb_frontend *fe, void *priv_cfg) 221static int fe_set_config(struct dvb_frontend *fe, void *priv_cfg)
232{ 222{
233 struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops; 223 struct dvb_tuner_ops *fe_tuner_ops = &fe->ops.tuner_ops;
@@ -436,7 +426,7 @@ static void set_type(struct i2c_client *c, unsigned int type,
436 sizeof(struct analog_demod_ops)); 426 sizeof(struct analog_demod_ops));
437 427
438 if (fe_tuner_ops->get_rf_strength) 428 if (fe_tuner_ops->get_rf_strength)
439 analog_ops->has_signal = fe_has_signal; 429 analog_ops->has_signal = fe_tuner_ops->get_rf_strength;
440 if (fe_tuner_ops->get_afc) 430 if (fe_tuner_ops->get_afc)
441 analog_ops->get_afc = fe_tuner_ops->get_afc; 431 analog_ops->get_afc = fe_tuner_ops->get_afc;
442 432
@@ -1060,9 +1050,12 @@ static void tuner_status(struct dvb_frontend *fe)
1060 if (tuner_status & TUNER_STATUS_STEREO) 1050 if (tuner_status & TUNER_STATUS_STEREO)
1061 tuner_info("Stereo: yes\n"); 1051 tuner_info("Stereo: yes\n");
1062 } 1052 }
1063 if (analog_ops->has_signal) 1053 if (analog_ops->has_signal) {
1064 tuner_info("Signal strength: %d\n", 1054 u16 signal;
1065 analog_ops->has_signal(fe)); 1055
1056 if (!analog_ops->has_signal(fe, &signal))
1057 tuner_info("Signal strength: %hu\n", signal);
1058 }
1066} 1059}
1067 1060
1068/* 1061/*
@@ -1181,8 +1174,12 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
1181 return 0; 1174 return 0;
1182 if (vt->type == t->mode && analog_ops->get_afc) 1175 if (vt->type == t->mode && analog_ops->get_afc)
1183 analog_ops->get_afc(&t->fe, &vt->afc); 1176 analog_ops->get_afc(&t->fe, &vt->afc);
1184 if (analog_ops->has_signal) 1177 if (vt->type == t->mode && analog_ops->has_signal) {
1185 vt->signal = analog_ops->has_signal(&t->fe); 1178 u16 signal = (u16)vt->signal;
1179
1180 if (!analog_ops->has_signal(&t->fe, &signal))
1181 vt->signal = signal;
1182 }
1186 if (vt->type != V4L2_TUNER_RADIO) { 1183 if (vt->type != V4L2_TUNER_RADIO) {
1187 vt->capability |= V4L2_TUNER_CAP_NORM; 1184 vt->capability |= V4L2_TUNER_CAP_NORM;
1188 vt->rangelow = tv_range[0] * 16; 1185 vt->rangelow = tv_range[0] * 16;