aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/em28xx
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2008-01-05 07:53:54 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-01-25 16:04:30 -0500
commit539c96d0fd86bfdcfac75c88b74aa5798439293d (patch)
treefb72c663b71fb2e9eef6eeaf859e774c8bb027a8 /drivers/media/video/em28xx
parent6596a4f6032f13f1bef47550fcf1d4134cd978a4 (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.c81
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c21
-rw-r--r--drivers/media/video/em28xx/em28xx.h35
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 */
255int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 * val) 255static 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
271int 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
271int em28xx_audio_analog_set(struct em28xx *dev) 331int 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}
355EXPORT_SYMBOL_GPL(em28xx_audio_analog_set);
281 356
282int em28xx_colorlevels_set_default(struct em28xx *dev) 357int 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
169static void video_mux(struct em28xx *dev, int index) 171static 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
154enum em28xx_amux {
155 EM28XX_AMUX_VIDEO,
156 EM28XX_AMUX_LINE_IN,
157 EM28XX_AMUX_AC97_VIDEO,
158 EM28XX_AMUX_AC97_LINE_IN,
159};
160
154struct em28xx_input { 161struct 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,
321int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len); 328int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len);
322int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val, 329int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
323 u8 bitmask); 330 u8 bitmask);
324int em28xx_write_ac97(struct em28xx *dev, u8 reg, u8 * val); 331int em28xx_set_audio_source(struct em28xx *dev);
325int em28xx_audio_analog_set(struct em28xx *dev); 332int em28xx_audio_analog_set(struct em28xx *dev);
333
326int em28xx_colorlevels_set_default(struct em28xx *dev); 334int em28xx_colorlevels_set_default(struct em28xx *dev);
327int em28xx_capture_start(struct em28xx *dev, int start); 335int em28xx_capture_start(struct em28xx *dev, int start);
328int em28xx_outfmt_set_yuv422(struct em28xx *dev); 336int 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
421inline 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
432inline 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
437inline 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
443inline static int em28xx_compression_disable(struct em28xx *dev) 430inline 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 */