[media] tuner-core: fix a 2.6.39 regression with mt20xx
authorMauro Carvalho Chehab <mchehab@redhat.com>
Wed, 13 Jul 2011 04:23:11 +0000 (01:23 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Wed, 13 Jul 2011 23:21:00 +0000 (20:21 -0300)
As Simon reported, digital TV broke with mt20xx tuner due to
commit ad020dc2fe9039628cf6cef42cd1b76531ee8411.

The mt20xx tuner passes V4L2_TUNER_DIGITAL_TV to tuner core. However, the
check_mode code now doesn't handle it well. Change the logic there to
avoid the breakage, and fix a test for analog-only at g_tuner.

Reported-by: Simon Arlott <simon@fire.lp0.eu>
Tested-by: Simon Arlott <simon@fire.lp0.eu>
Cc: stable@kernel.org
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/tuner-core.c

index cfa9f7e..a03945a 100644 (file)
@@ -714,10 +714,19 @@ static int tuner_remove(struct i2c_client *client)
  * returns 0.
  * This function is needed for boards that have a separate tuner for
  * radio (like devices with tea5767).
+ * NOTE: mt20xx uses V4L2_TUNER_DIGITAL_TV and calls set_tv_freq to
+ *       select a TV frequency. So, t_mode = T_ANALOG_TV could actually
+ *      be used to represent a Digital TV too.
  */
 static inline int check_mode(struct tuner *t, enum v4l2_tuner_type mode)
 {
-       if ((1 << mode & t->mode_mask) == 0)
+       int t_mode;
+       if (mode == V4L2_TUNER_RADIO)
+               t_mode = T_RADIO;
+       else
+               t_mode = T_ANALOG_TV;
+
+       if ((t_mode & t->mode_mask) == 0)
                return -EINVAL;
 
        return 0;
@@ -984,7 +993,7 @@ static void tuner_status(struct dvb_frontend *fe)
        case V4L2_TUNER_RADIO:
                p = "radio";
                break;
-       case V4L2_TUNER_DIGITAL_TV:
+       case V4L2_TUNER_DIGITAL_TV: /* Used by mt20xx */
                p = "digital TV";
                break;
        case V4L2_TUNER_ANALOG_TV:
@@ -1135,9 +1144,8 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
                return 0;
        if (vt->type == t->mode && analog_ops->get_afc)
                vt->afc = analog_ops->get_afc(&t->fe);
-       if (vt->type == V4L2_TUNER_ANALOG_TV)
+       if (t->mode != V4L2_TUNER_RADIO) {
                vt->capability |= V4L2_TUNER_CAP_NORM;
-       if (vt->type != V4L2_TUNER_RADIO) {
                vt->rangelow = tv_range[0] * 16;
                vt->rangehigh = tv_range[1] * 16;
                return 0;