aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
authorTorsten Schenk <torsten.schenk@zoho.com>2012-02-22 09:21:23 -0500
committerTakashi Iwai <tiwai@suse.de>2012-02-22 09:51:16 -0500
commitd97c735a1047fa06165e55da32154cf0e6b9419c (patch)
tree859d77d248e5d15442dd7282be51dc522a1ad74b /sound/usb
parentf90ffbf3c68a69714b4273b203d4deb5ae81d8d6 (diff)
ALSA: snd-usb-6fire: add mute control for analog outputs
Add a mute control for every analog output channel. Signed-off-by: Torsten Schenk <torsten.schenk@zoho.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/6fire/control.c95
-rw-r--r--sound/usb/6fire/control.h1
2 files changed, 96 insertions, 0 deletions
diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c
index c22cc29e33d7..a2bbf48c6413 100644
--- a/sound/usb/6fire/control.c
+++ b/sound/usb/6fire/control.c
@@ -74,6 +74,14 @@ static void usb6fire_control_output_vol_update(struct control_runtime *rt)
74 } 74 }
75} 75}
76 76
77static void usb6fire_control_output_mute_update(struct control_runtime *rt)
78{
79 struct comm_runtime *comm_rt = rt->chip->comm;
80
81 if (comm_rt)
82 comm_rt->write8(comm_rt, 0x12, 0x0e, ~rt->output_mute);
83}
84
77static void usb6fire_control_line_phono_update(struct control_runtime *rt) 85static void usb6fire_control_line_phono_update(struct control_runtime *rt)
78{ 86{
79 struct comm_runtime *comm_rt = rt->chip->comm; 87 struct comm_runtime *comm_rt = rt->chip->comm;
@@ -208,6 +216,51 @@ static int usb6fire_control_output_vol_get(struct snd_kcontrol *kcontrol,
208 return 0; 216 return 0;
209} 217}
210 218
219static int usb6fire_control_output_mute_put(struct snd_kcontrol *kcontrol,
220 struct snd_ctl_elem_value *ucontrol)
221{
222 struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
223 unsigned int ch = kcontrol->private_value;
224 u8 old = rt->output_mute;
225 u8 value = 0;
226
227 if (ch > 4) {
228 snd_printk(KERN_ERR PREFIX "Invalid channel in volume control.");
229 return -EINVAL;
230 }
231
232 rt->output_mute &= ~(3 << ch);
233 if (ucontrol->value.integer.value[0])
234 value |= 1;
235 if (ucontrol->value.integer.value[1])
236 value |= 2;
237 rt->output_mute |= value << ch;
238
239 if (rt->output_mute != old)
240 usb6fire_control_output_mute_update(rt);
241
242 return rt->output_mute != old;
243}
244
245static int usb6fire_control_output_mute_get(struct snd_kcontrol *kcontrol,
246 struct snd_ctl_elem_value *ucontrol)
247{
248 struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
249 unsigned int ch = kcontrol->private_value;
250 u8 value = rt->output_mute >> ch;
251
252 if (ch > 4) {
253 snd_printk(KERN_ERR PREFIX "Invalid channel in volume control.");
254 return -EINVAL;
255 }
256
257 ucontrol->value.integer.value[0] = 1 & value;
258 value >>= 1;
259 ucontrol->value.integer.value[1] = 1 & value;
260
261 return 0;
262}
263
211static int usb6fire_control_line_phono_info(struct snd_kcontrol *kcontrol, 264static int usb6fire_control_line_phono_info(struct snd_kcontrol *kcontrol,
212 struct snd_ctl_elem_info *uinfo) 265 struct snd_ctl_elem_info *uinfo)
213{ 266{
@@ -339,6 +392,40 @@ static struct __devinitdata snd_kcontrol_new vol_elements[] = {
339 {} 392 {}
340}; 393};
341 394
395static struct __devinitdata snd_kcontrol_new mute_elements[] = {
396 {
397 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
398 .name = "Analog Playback Switch",
399 .index = 0,
400 .private_value = 0,
401 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
402 .info = snd_ctl_boolean_stereo_info,
403 .get = usb6fire_control_output_mute_get,
404 .put = usb6fire_control_output_mute_put,
405 },
406 {
407 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
408 .name = "Analog Playback Switch",
409 .index = 1,
410 .private_value = 2,
411 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
412 .info = snd_ctl_boolean_stereo_info,
413 .get = usb6fire_control_output_mute_get,
414 .put = usb6fire_control_output_mute_put,
415 },
416 {
417 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
418 .name = "Analog Playback Switch",
419 .index = 2,
420 .private_value = 4,
421 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
422 .info = snd_ctl_boolean_stereo_info,
423 .get = usb6fire_control_output_mute_get,
424 .put = usb6fire_control_output_mute_put,
425 },
426 {}
427};
428
342static struct __devinitdata snd_kcontrol_new elements[] = { 429static struct __devinitdata snd_kcontrol_new elements[] = {
343 { 430 {
344 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 431 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -430,13 +517,21 @@ int __devinit usb6fire_control_init(struct sfire_chip *chip)
430 usb6fire_control_opt_coax_update(rt); 517 usb6fire_control_opt_coax_update(rt);
431 usb6fire_control_line_phono_update(rt); 518 usb6fire_control_line_phono_update(rt);
432 usb6fire_control_output_vol_update(rt); 519 usb6fire_control_output_vol_update(rt);
520 usb6fire_control_output_mute_update(rt);
433 usb6fire_control_streaming_update(rt); 521 usb6fire_control_streaming_update(rt);
434 522
435 ret = usb6fire_control_add_virtual(rt, chip->card, 523 ret = usb6fire_control_add_virtual(rt, chip->card,
436 "Master Playback Volume", vol_elements); 524 "Master Playback Volume", vol_elements);
437 if (ret) { 525 if (ret) {
526 snd_printk(KERN_ERR PREFIX "cannot add control.\n");
438 kfree(rt); 527 kfree(rt);
528 return ret;
529 }
530 ret = usb6fire_control_add_virtual(rt, chip->card,
531 "Master Playback Switch", mute_elements);
532 if (ret) {
439 snd_printk(KERN_ERR PREFIX "cannot add control.\n"); 533 snd_printk(KERN_ERR PREFIX "cannot add control.\n");
534 kfree(rt);
440 return ret; 535 return ret;
441 } 536 }
442 537
diff --git a/sound/usb/6fire/control.h b/sound/usb/6fire/control.h
index ce024113c98f..9f9eb647bc6b 100644
--- a/sound/usb/6fire/control.h
+++ b/sound/usb/6fire/control.h
@@ -45,6 +45,7 @@ struct control_runtime {
45 bool usb_streaming; 45 bool usb_streaming;
46 u8 output_vol[6]; 46 u8 output_vol[6];
47 u8 ovol_updated; 47 u8 ovol_updated;
48 u8 output_mute;
48}; 49};
49 50
50int __devinit usb6fire_control_init(struct sfire_chip *chip); 51int __devinit usb6fire_control_init(struct sfire_chip *chip);