diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-01-05 07:53:54 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-01-25 16:04:30 -0500 |
commit | 539c96d0fd86bfdcfac75c88b74aa5798439293d (patch) | |
tree | fb72c663b71fb2e9eef6eeaf859e774c8bb027a8 /drivers/media/video/em28xx | |
parent | 6596a4f6032f13f1bef47550fcf1d4134cd978a4 (diff) |
V4L/DVB (6947): Improve audio setup handling
It is possible to select audio inputs via em28xx or via ac97 functions.
This patch allows configuring a board to use either one way.
It also do some cleanups at audio setup configurations.
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/em28xx')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-core.c | 81 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 21 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx.h | 35 |
3 files changed, 95 insertions, 42 deletions
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index d56484f20467..70c5ec268f6a 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -252,7 +252,7 @@ int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, | |||
252 | * em28xx_write_ac97() | 252 | * em28xx_write_ac97() |
253 | * write a 16 bit value to the specified AC97 address (LSB first!) | 253 | * write a 16 bit value to the specified AC97 address (LSB first!) |
254 | */ | 254 | */ |
255 | int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 * val) | 255 | static int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 *val) |
256 | { | 256 | { |
257 | int ret; | 257 | int ret; |
258 | u8 addr = reg & 0x7f; | 258 | u8 addr = reg & 0x7f; |
@@ -268,16 +268,91 @@ int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 * val) | |||
268 | return 0; | 268 | return 0; |
269 | } | 269 | } |
270 | 270 | ||
271 | int em28xx_set_audio_source(struct em28xx *dev) | ||
272 | { | ||
273 | static char *enable = "\x08\x08"; | ||
274 | static char *disable = "\x08\x88"; | ||
275 | char *video = enable, *line = disable; | ||
276 | int ret, no_ac97; | ||
277 | u8 input; | ||
278 | |||
279 | if (dev->is_em2800) { | ||
280 | if (dev->ctl_ainput) | ||
281 | input = EM2800_AUDIO_SRC_LINE; | ||
282 | else | ||
283 | input = EM2800_AUDIO_SRC_TUNER; | ||
284 | |||
285 | ret = em28xx_write_regs(dev, EM2800_AUDIOSRC_REG, &input, 1); | ||
286 | if (ret < 0) | ||
287 | return ret; | ||
288 | } | ||
289 | |||
290 | if (dev->has_msp34xx) | ||
291 | input = EM28XX_AUDIO_SRC_TUNER; | ||
292 | else { | ||
293 | switch (dev->ctl_ainput) { | ||
294 | case EM28XX_AMUX_VIDEO: | ||
295 | input = EM28XX_AUDIO_SRC_TUNER; | ||
296 | no_ac97 = 1; | ||
297 | break; | ||
298 | case EM28XX_AMUX_LINE_IN: | ||
299 | input = EM28XX_AUDIO_SRC_LINE; | ||
300 | no_ac97 = 1; | ||
301 | break; | ||
302 | case EM28XX_AMUX_AC97_VIDEO: | ||
303 | input = EM28XX_AUDIO_SRC_LINE; | ||
304 | break; | ||
305 | case EM28XX_AMUX_AC97_LINE_IN: | ||
306 | input = EM28XX_AUDIO_SRC_LINE; | ||
307 | video = disable; | ||
308 | line = enable; | ||
309 | break; | ||
310 | } | ||
311 | } | ||
312 | |||
313 | ret = em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0); | ||
314 | if (ret < 0) | ||
315 | return ret; | ||
316 | |||
317 | if (no_ac97) | ||
318 | return 0; | ||
319 | |||
320 | /* Sets AC97 mixer registers */ | ||
321 | |||
322 | ret = em28xx_write_ac97(dev, VIDEO_AC97, video); | ||
323 | if (ret < 0) | ||
324 | return ret; | ||
325 | |||
326 | ret = em28xx_write_ac97(dev, LINE_IN_AC97, line); | ||
327 | |||
328 | return ret; | ||
329 | } | ||
330 | |||
271 | int em28xx_audio_analog_set(struct em28xx *dev) | 331 | int em28xx_audio_analog_set(struct em28xx *dev) |
272 | { | 332 | { |
333 | int ret; | ||
273 | char s[2] = { 0x00, 0x00 }; | 334 | char s[2] = { 0x00, 0x00 }; |
335 | |||
274 | s[0] |= 0x1f - dev->volume; | 336 | s[0] |= 0x1f - dev->volume; |
275 | s[1] |= 0x1f - dev->volume; | 337 | s[1] |= 0x1f - dev->volume; |
338 | |||
276 | if (dev->mute) | 339 | if (dev->mute) |
277 | s[1] |= 0x80; | 340 | s[1] |= 0x80; |
278 | return em28xx_write_ac97(dev, MASTER_AC97, s); | 341 | ret = em28xx_write_ac97(dev, MASTER_AC97, s); |
279 | } | 342 | if (ret < 0) |
343 | return ret; | ||
280 | 344 | ||
345 | ret = em28xx_write_reg_bits(dev, XCLK_REG, | ||
346 | dev->mute ? 0x00 : 0x80, 0x80); | ||
347 | if (ret < 0) | ||
348 | return ret; | ||
349 | |||
350 | /* Selects the proper audio input */ | ||
351 | ret = em28xx_set_audio_source(dev); | ||
352 | |||
353 | return ret; | ||
354 | } | ||
355 | EXPORT_SYMBOL_GPL(em28xx_audio_analog_set); | ||
281 | 356 | ||
282 | int em28xx_colorlevels_set_default(struct em28xx *dev) | 357 | int em28xx_colorlevels_set_default(struct em28xx *dev) |
283 | { | 358 | { |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index c2901f13eb25..1a284cb18c24 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -122,11 +122,13 @@ static int em28xx_config(struct em28xx *dev) | |||
122 | /* em28xx_write_regs_req(dev,0x00,0x0f,"\x80",1); clk register */ | 122 | /* em28xx_write_regs_req(dev,0x00,0x0f,"\x80",1); clk register */ |
123 | em28xx_write_regs_req(dev,0x00,0x11,"\x51",1); | 123 | em28xx_write_regs_req(dev,0x00,0x11,"\x51",1); |
124 | 124 | ||
125 | em28xx_audio_usb_mute(dev, 1); | ||
126 | dev->mute = 1; /* maybe not the right place... */ | 125 | dev->mute = 1; /* maybe not the right place... */ |
127 | dev->volume = 0x1f; | 126 | dev->volume = 0x1f; |
127 | |||
128 | /* Init XCLK_REG, audio muted */ | ||
129 | dev->em28xx_write_regs(dev, XCLK_REG, "\x87", 1); | ||
130 | |||
128 | em28xx_audio_analog_set(dev); | 131 | em28xx_audio_analog_set(dev); |
129 | em28xx_audio_analog_setup(dev); | ||
130 | em28xx_outfmt_set_yuv422(dev); | 132 | em28xx_outfmt_set_yuv422(dev); |
131 | em28xx_colorlevels_set_default(dev); | 133 | em28xx_colorlevels_set_default(dev); |
132 | em28xx_compression_disable(dev); | 134 | em28xx_compression_disable(dev); |
@@ -168,7 +170,6 @@ static void em28xx_empty_framequeues(struct em28xx *dev) | |||
168 | 170 | ||
169 | static void video_mux(struct em28xx *dev, int index) | 171 | static void video_mux(struct em28xx *dev, int index) |
170 | { | 172 | { |
171 | int ainput; | ||
172 | struct v4l2_routing route; | 173 | struct v4l2_routing route; |
173 | 174 | ||
174 | route.input = INPUT(index)->vmux; | 175 | route.input = INPUT(index)->vmux; |
@@ -185,18 +186,9 @@ static void video_mux(struct em28xx *dev, int index) | |||
185 | route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); | 186 | route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); |
186 | /* Note: this is msp3400 specific */ | 187 | /* Note: this is msp3400 specific */ |
187 | em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route); | 188 | em28xx_i2c_call_clients(dev, VIDIOC_INT_S_AUDIO_ROUTING, &route); |
188 | ainput = EM28XX_AUDIO_SRC_TUNER; | ||
189 | em28xx_audio_source(dev, ainput); | ||
190 | } else { | ||
191 | switch (dev->ctl_ainput) { | ||
192 | case 0: | ||
193 | ainput = EM28XX_AUDIO_SRC_TUNER; | ||
194 | break; | ||
195 | default: | ||
196 | ainput = EM28XX_AUDIO_SRC_LINE; | ||
197 | } | ||
198 | em28xx_audio_source(dev, ainput); | ||
199 | } | 189 | } |
190 | |||
191 | em28xx_set_audio_source(dev); | ||
200 | } | 192 | } |
201 | 193 | ||
202 | /* Usage lock check functions */ | 194 | /* Usage lock check functions */ |
@@ -292,7 +284,6 @@ static int em28xx_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl) | |||
292 | case V4L2_CID_AUDIO_MUTE: | 284 | case V4L2_CID_AUDIO_MUTE: |
293 | if (ctrl->value != dev->mute) { | 285 | if (ctrl->value != dev->mute) { |
294 | dev->mute = ctrl->value; | 286 | dev->mute = ctrl->value; |
295 | em28xx_audio_usb_mute(dev, ctrl->value); | ||
296 | return em28xx_audio_analog_set(dev); | 287 | return em28xx_audio_analog_set(dev); |
297 | } | 288 | } |
298 | return 0; | 289 | return 0; |
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 93007cc72f4d..abde13ecb4a8 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -151,10 +151,17 @@ enum enum28xx_itype { | |||
151 | EM28XX_RADIO, | 151 | EM28XX_RADIO, |
152 | }; | 152 | }; |
153 | 153 | ||
154 | enum em28xx_amux { | ||
155 | EM28XX_AMUX_VIDEO, | ||
156 | EM28XX_AMUX_LINE_IN, | ||
157 | EM28XX_AMUX_AC97_VIDEO, | ||
158 | EM28XX_AMUX_AC97_LINE_IN, | ||
159 | }; | ||
160 | |||
154 | struct em28xx_input { | 161 | struct em28xx_input { |
155 | enum enum28xx_itype type; | 162 | enum enum28xx_itype type; |
156 | unsigned int vmux; | 163 | unsigned int vmux; |
157 | unsigned int amux; | 164 | enum em28xx_amux amux; |
158 | }; | 165 | }; |
159 | 166 | ||
160 | #define INPUT(nr) (&em28xx_boards[dev->model].input[nr]) | 167 | #define INPUT(nr) (&em28xx_boards[dev->model].input[nr]) |
@@ -321,8 +328,9 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, | |||
321 | int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len); | 328 | int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len); |
322 | int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, | 329 | int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, |
323 | u8 bitmask); | 330 | u8 bitmask); |
324 | int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 * val); | 331 | int em28xx_set_audio_source(struct em28xx *dev); |
325 | int em28xx_audio_analog_set(struct em28xx *dev); | 332 | int em28xx_audio_analog_set(struct em28xx *dev); |
333 | |||
326 | int em28xx_colorlevels_set_default(struct em28xx *dev); | 334 | int em28xx_colorlevels_set_default(struct em28xx *dev); |
327 | int em28xx_capture_start(struct em28xx *dev, int start); | 335 | int em28xx_capture_start(struct em28xx *dev, int start); |
328 | int em28xx_outfmt_set_yuv422(struct em28xx *dev); | 336 | int em28xx_outfmt_set_yuv422(struct em28xx *dev); |
@@ -394,6 +402,7 @@ extern const unsigned int em28xx_bcount; | |||
394 | 402 | ||
395 | /* em202 registers */ | 403 | /* em202 registers */ |
396 | #define MASTER_AC97 0x02 | 404 | #define MASTER_AC97 0x02 |
405 | #define LINE_IN_AC97 0x10 | ||
397 | #define VIDEO_AC97 0x14 | 406 | #define VIDEO_AC97 0x14 |
398 | 407 | ||
399 | /* register settings */ | 408 | /* register settings */ |
@@ -418,28 +427,6 @@ extern const unsigned int em28xx_bcount; | |||
418 | printk(KERN_WARNING "%s: "fmt,\ | 427 | printk(KERN_WARNING "%s: "fmt,\ |
419 | dev->name , ##arg); } while (0) | 428 | dev->name , ##arg); } while (0) |
420 | 429 | ||
421 | inline static int em28xx_audio_source(struct em28xx *dev, int input) | ||
422 | { | ||
423 | if(dev->is_em2800){ | ||
424 | u8 tmp = EM2800_AUDIO_SRC_TUNER; | ||
425 | if(input == EM28XX_AUDIO_SRC_LINE) | ||
426 | tmp = EM2800_AUDIO_SRC_LINE; | ||
427 | em28xx_write_regs(dev, EM2800_AUDIOSRC_REG, &tmp, 1); | ||
428 | } | ||
429 | return em28xx_write_reg_bits(dev, AUDIOSRC_REG, input, 0xc0); | ||
430 | } | ||
431 | |||
432 | inline static int em28xx_audio_usb_mute(struct em28xx *dev, int mute) | ||
433 | { | ||
434 | return em28xx_write_reg_bits(dev, XCLK_REG, mute ? 0x00 : 0x80, 0x80); | ||
435 | } | ||
436 | |||
437 | inline static int em28xx_audio_analog_setup(struct em28xx *dev) | ||
438 | { | ||
439 | /* unmute video mixer with default volume level */ | ||
440 | return em28xx_write_ac97(dev, VIDEO_AC97, "\x08\x08"); | ||
441 | } | ||
442 | |||
443 | inline static int em28xx_compression_disable(struct em28xx *dev) | 430 | inline static int em28xx_compression_disable(struct em28xx *dev) |
444 | { | 431 | { |
445 | /* side effect of disabling scaler and mixer */ | 432 | /* side effect of disabling scaler and mixer */ |