aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/tda9840.c
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2012-05-01 09:06:40 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-14 13:57:02 -0400
commit8bb5bafa8057a91613d50f7b0bec025852360237 (patch)
tree8e71d9c2852b0d27ee7d4b3c168d374d16315031 /drivers/media/video/tda9840.c
parentaaab4951a688e4c3f43e0ce09855718e9ad5060d (diff)
[media] tda9840: fix setting of the audio mode
You have to first detect the current rxsubchans (mono, stereo or bilingual), and depending on that you can set the audio mode. It does not automatically switch when the audio channels change. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/tda9840.c')
-rw-r--r--drivers/media/video/tda9840.c75
1 files changed, 44 insertions, 31 deletions
diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c
index 465d7086babf..3d7ddd93282d 100644
--- a/drivers/media/video/tda9840.c
+++ b/drivers/media/video/tda9840.c
@@ -66,29 +66,53 @@ static void tda9840_write(struct v4l2_subdev *sd, u8 reg, u8 val)
66 val, reg); 66 val, reg);
67} 67}
68 68
69static int tda9840_status(struct v4l2_subdev *sd)
70{
71 struct i2c_client *client = v4l2_get_subdevdata(sd);
72 u8 byte;
73
74 if (1 != i2c_master_recv(client, &byte, 1)) {
75 v4l2_dbg(1, debug, sd,
76 "i2c_master_recv() failed\n");
77 return -EIO;
78 }
79
80 if (byte & 0x80) {
81 v4l2_dbg(1, debug, sd,
82 "TDA9840_DETECT: register contents invalid\n");
83 return -EINVAL;
84 }
85
86 v4l2_dbg(1, debug, sd, "TDA9840_DETECT: byte: 0x%02x\n", byte);
87 return byte & 0x60;
88}
89
69static int tda9840_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t) 90static int tda9840_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t)
70{ 91{
92 int stat = tda9840_status(sd);
71 int byte; 93 int byte;
72 94
73 if (t->index) 95 if (t->index)
74 return -EINVAL; 96 return -EINVAL;
75 97
76 switch (t->audmode) { 98 stat = stat < 0 ? 0 : stat;
77 case V4L2_TUNER_MODE_STEREO: 99 if (stat == 0 || stat == 0x60) /* mono input */
78 byte = TDA9840_SET_STEREO;
79 break;
80 case V4L2_TUNER_MODE_LANG1_LANG2:
81 byte = TDA9840_SET_BOTH;
82 break;
83 case V4L2_TUNER_MODE_LANG1:
84 byte = TDA9840_SET_LANG1;
85 break;
86 case V4L2_TUNER_MODE_LANG2:
87 byte = TDA9840_SET_LANG2;
88 break;
89 default:
90 byte = TDA9840_SET_MONO; 100 byte = TDA9840_SET_MONO;
91 break; 101 else if (stat == 0x40) /* stereo input */
102 byte = (t->audmode == V4L2_TUNER_MODE_MONO) ?
103 TDA9840_SET_MONO : TDA9840_SET_STEREO;
104 else { /* bilingual */
105 switch (t->audmode) {
106 case V4L2_TUNER_MODE_LANG1_LANG2:
107 byte = TDA9840_SET_BOTH;
108 break;
109 case V4L2_TUNER_MODE_LANG2:
110 byte = TDA9840_SET_LANG2;
111 break;
112 default:
113 byte = TDA9840_SET_LANG1;
114 break;
115 }
92 } 116 }
93 v4l2_dbg(1, debug, sd, "TDA9840_SWITCH: 0x%02x\n", byte); 117 v4l2_dbg(1, debug, sd, "TDA9840_SWITCH: 0x%02x\n", byte);
94 tda9840_write(sd, SWITCH, byte); 118 tda9840_write(sd, SWITCH, byte);
@@ -97,25 +121,14 @@ static int tda9840_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t)
97 121
98static int tda9840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t) 122static int tda9840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t)
99{ 123{
100 struct i2c_client *client = v4l2_get_subdevdata(sd); 124 int stat = tda9840_status(sd);
101 u8 byte;
102
103 t->rxsubchans = V4L2_TUNER_SUB_MONO;
104 if (1 != i2c_master_recv(client, &byte, 1)) {
105 v4l2_dbg(1, debug, sd,
106 "i2c_master_recv() failed\n");
107 return -EIO;
108 }
109 125
110 if (byte & 0x80) { 126 if (stat < 0)
111 v4l2_dbg(1, debug, sd, 127 return stat;
112 "TDA9840_DETECT: register contents invalid\n");
113 return -EINVAL;
114 }
115 128
116 v4l2_dbg(1, debug, sd, "TDA9840_DETECT: byte: 0x%02x\n", byte); 129 t->rxsubchans = V4L2_TUNER_SUB_MONO;
117 130
118 switch (byte & 0x60) { 131 switch (stat & 0x60) {
119 case 0x00: 132 case 0x00:
120 t->rxsubchans = V4L2_TUNER_SUB_MONO; 133 t->rxsubchans = V4L2_TUNER_SUB_MONO;
121 break; 134 break;