diff options
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/tda9840.c | 75 |
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 | ||
69 | static 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 | |||
69 | static int tda9840_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t) | 90 | static 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 | ||
98 | static int tda9840_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *t) | 122 | static 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; |