From 6e8d5d2f17e707ecfabd33fd5fa167ac7739326e Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Wed, 15 Feb 2012 00:38:55 +0900 Subject: ALSA: usx2y: Fix typo in usbusx2yaudio.c and usx2yhwdeppcm.c Correct spelling "propably" to "probably" and "activ" to "active" in sound/usb/usx2y/usbusx2yaudio.c and usx2yhwdeppcm.c Signed-off-by: Masanari Iida Signed-off-by: Takashi Iwai --- sound/usb/usx2y/usbusx2yaudio.c | 4 ++-- sound/usb/usx2y/usx2yhwdeppcm.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'sound/usb') diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index 6ffb3713b60c..520ef96d7c75 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -80,7 +80,7 @@ static int usX2Y_urb_capt_retire(struct snd_usX2Y_substream *subs) cp = (unsigned char*)urb->transfer_buffer + urb->iso_frame_desc[i].offset; if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */ snd_printk(KERN_ERR "active frame status %i. " - "Most propably some hardware problem.\n", + "Most probably some hardware problem.\n", urb->iso_frame_desc[i].status); return urb->iso_frame_desc[i].status; } @@ -300,7 +300,7 @@ static void usX2Y_error_sequence(struct usX2Ydev *usX2Y, { snd_printk(KERN_ERR "Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n" -"Most propably some urb of usb-frame %i is still missing.\n" +"Most probably some urb of usb-frame %i is still missing.\n" "Cause could be too long delays in usb-hcd interrupt handling.\n", usb_get_current_frame_number(usX2Y->dev), subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index a51340f6f2db..8e40b6e67e9e 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c @@ -74,7 +74,7 @@ static int usX2Y_usbpcm_urb_capt_retire(struct snd_usX2Y_substream *subs) } for (i = 0; i < nr_of_packs(); i++) { if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */ - snd_printk(KERN_ERR "activ frame status %i. Most propably some hardware problem.\n", urb->iso_frame_desc[i].status); + snd_printk(KERN_ERR "active frame status %i. Most probably some hardware problem.\n", urb->iso_frame_desc[i].status); return urb->iso_frame_desc[i].status; } lens += urb->iso_frame_desc[i].actual_length / usX2Y->stride; -- cgit v1.2.1 From c596758f57aa33e5e89c006867ae66fa2f9c357c Mon Sep 17 00:00:00 2001 From: Torsten Schenk Date: Wed, 22 Feb 2012 15:20:45 +0100 Subject: ALSA: snd-usb-6fire: remove driver version information Remove unused driver version information from the individual files. Signed-off-by: Torsten Schenk Signed-off-by: Takashi Iwai --- sound/usb/6fire/chip.c | 3 +-- sound/usb/6fire/chip.h | 1 - sound/usb/6fire/comm.c | 1 - sound/usb/6fire/comm.h | 1 - sound/usb/6fire/common.h | 1 - sound/usb/6fire/control.c | 1 - sound/usb/6fire/control.h | 1 - sound/usb/6fire/firmware.c | 1 - sound/usb/6fire/midi.c | 1 - sound/usb/6fire/midi.h | 1 - sound/usb/6fire/pcm.c | 1 - sound/usb/6fire/pcm.h | 1 - 12 files changed, 1 insertion(+), 13 deletions(-) (limited to 'sound/usb') diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c index 8af92e3e9c18..fc8cc823e438 100644 --- a/sound/usb/6fire/chip.c +++ b/sound/usb/6fire/chip.c @@ -5,7 +5,6 @@ * * Author: Torsten Schenk * Created: Jan 01, 2011 - * Version: 0.3.0 * Copyright: (C) Torsten Schenk * * This program is free software; you can redistribute it and/or modify @@ -29,7 +28,7 @@ #include MODULE_AUTHOR("Torsten Schenk "); -MODULE_DESCRIPTION("TerraTec DMX 6Fire USB audio driver, version 0.3.0"); +MODULE_DESCRIPTION("TerraTec DMX 6Fire USB audio driver"); MODULE_LICENSE("GPL v2"); MODULE_SUPPORTED_DEVICE("{{TerraTec, DMX 6Fire USB}}"); diff --git a/sound/usb/6fire/chip.h b/sound/usb/6fire/chip.h index d11e5cb520f0..bde02d105a51 100644 --- a/sound/usb/6fire/chip.h +++ b/sound/usb/6fire/chip.h @@ -3,7 +3,6 @@ * * Author: Torsten Schenk * Created: Jan 01, 2011 - * Version: 0.3.0 * Copyright: (C) Torsten Schenk * * This program is free software; you can redistribute it and/or modify diff --git a/sound/usb/6fire/comm.c b/sound/usb/6fire/comm.c index c994daa57af2..6c3d531a250e 100644 --- a/sound/usb/6fire/comm.c +++ b/sound/usb/6fire/comm.c @@ -5,7 +5,6 @@ * * Author: Torsten Schenk * Created: Jan 01, 2011 - * Version: 0.3.0 * Copyright: (C) Torsten Schenk * * This program is free software; you can redistribute it and/or modify diff --git a/sound/usb/6fire/comm.h b/sound/usb/6fire/comm.h index edc5dc84b888..d2af0a5ddcf3 100644 --- a/sound/usb/6fire/comm.h +++ b/sound/usb/6fire/comm.h @@ -3,7 +3,6 @@ * * Author: Torsten Schenk * Created: Jan 01, 2011 - * Version: 0.3.0 * Copyright: (C) Torsten Schenk * * This program is free software; you can redistribute it and/or modify diff --git a/sound/usb/6fire/common.h b/sound/usb/6fire/common.h index 7dbeb4a37831..b6eb03ed1c2c 100644 --- a/sound/usb/6fire/common.h +++ b/sound/usb/6fire/common.h @@ -3,7 +3,6 @@ * * Author: Torsten Schenk * Created: Jan 01, 2011 - * Version: 0.3.0 * Copyright: (C) Torsten Schenk * * This program is free software; you can redistribute it and/or modify diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c index ac828eff1a63..8111844c4b16 100644 --- a/sound/usb/6fire/control.c +++ b/sound/usb/6fire/control.c @@ -5,7 +5,6 @@ * * Author: Torsten Schenk * Created: Jan 01, 2011 - * Version: 0.3.0 * Copyright: (C) Torsten Schenk * * This program is free software; you can redistribute it and/or modify diff --git a/sound/usb/6fire/control.h b/sound/usb/6fire/control.h index 8f5aeead2e3d..0dcb1d2f522c 100644 --- a/sound/usb/6fire/control.h +++ b/sound/usb/6fire/control.h @@ -3,7 +3,6 @@ * * Author: Torsten Schenk * Created: Jan 01, 2011 - * Version: 0.3.0 * Copyright: (C) Torsten Schenk * * This program is free software; you can redistribute it and/or modify diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c index 3b5f517a3972..6f9715ab32fe 100644 --- a/sound/usb/6fire/firmware.c +++ b/sound/usb/6fire/firmware.c @@ -5,7 +5,6 @@ * * Author: Torsten Schenk * Created: Jan 01, 2011 - * Version: 0.3.0 * Copyright: (C) Torsten Schenk * * This program is free software; you can redistribute it and/or modify diff --git a/sound/usb/6fire/midi.c b/sound/usb/6fire/midi.c index 13f4509dce2b..f0e5179b242b 100644 --- a/sound/usb/6fire/midi.c +++ b/sound/usb/6fire/midi.c @@ -5,7 +5,6 @@ * * Author: Torsten Schenk * Created: Jan 01, 2011 - * Version: 0.3.0 * Copyright: (C) Torsten Schenk * * This program is free software; you can redistribute it and/or modify diff --git a/sound/usb/6fire/midi.h b/sound/usb/6fire/midi.h index 97a7bf669135..5114eccc1d8e 100644 --- a/sound/usb/6fire/midi.h +++ b/sound/usb/6fire/midi.h @@ -3,7 +3,6 @@ * * Author: Torsten Schenk * Created: Jan 01, 2011 - * Version: 0.3.0 * Copyright: (C) Torsten Schenk * * This program is free software; you can redistribute it and/or modify diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c index d144cdb2f159..c97d05f0e966 100644 --- a/sound/usb/6fire/pcm.c +++ b/sound/usb/6fire/pcm.c @@ -5,7 +5,6 @@ * * Author: Torsten Schenk * Created: Jan 01, 2011 - * Version: 0.3.0 * Copyright: (C) Torsten Schenk * * This program is free software; you can redistribute it and/or modify diff --git a/sound/usb/6fire/pcm.h b/sound/usb/6fire/pcm.h index 2bee81374002..3104301b257d 100644 --- a/sound/usb/6fire/pcm.h +++ b/sound/usb/6fire/pcm.h @@ -3,7 +3,6 @@ * * Author: Torsten Schenk * Created: Jan 01, 2011 - * Version: 0.3.0 * Copyright: (C) Torsten Schenk * * This program is free software; you can redistribute it and/or modify -- cgit v1.2.1 From 8e247a9c90e65b25b5b064e2159d9c4c2c173a5e Mon Sep 17 00:00:00 2001 From: Torsten Schenk Date: Wed, 22 Feb 2012 15:20:54 +0100 Subject: ALSA: snd-usb-6fire: add tlv to controls Remove the soft log-conversion and add a dB scale according to the DAC documentation instead. Signed-off-by: Torsten Schenk Signed-off-by: Takashi Iwai --- sound/usb/6fire/control.c | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) (limited to 'sound/usb') diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c index 8111844c4b16..b00b8bb88c63 100644 --- a/sound/usb/6fire/control.c +++ b/sound/usb/6fire/control.c @@ -15,6 +15,7 @@ #include #include +#include #include "control.h" #include "comm.h" @@ -23,26 +24,6 @@ static char *opt_coax_texts[2] = { "Optical", "Coax" }; static char *line_phono_texts[2] = { "Line", "Phono" }; -/* - * calculated with $value\[i\] = 128 \cdot sqrt[3]{\frac{i}{128}}$ - * this is done because the linear values cause rapid degredation - * of volume in the uppermost region. - */ -static const u8 log_volume_table[128] = { - 0x00, 0x19, 0x20, 0x24, 0x28, 0x2b, 0x2e, 0x30, 0x32, 0x34, - 0x36, 0x38, 0x3a, 0x3b, 0x3d, 0x3e, 0x40, 0x41, 0x42, 0x43, - 0x44, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, - 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x53, 0x54, 0x55, 0x56, - 0x56, 0x57, 0x58, 0x58, 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, - 0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, - 0x63, 0x63, 0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68, - 0x68, 0x69, 0x69, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c, 0x6c, - 0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71, - 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75, - 0x75, 0x76, 0x76, 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, - 0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, - 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f }; - /* * data that needs to be sent to device. sets up card internal stuff. * values dumped from windows driver and filtered by trial'n'error. @@ -69,6 +50,8 @@ static const int rates_altsetting[] = { 1, 1, 2, 2, 3, 3 }; static const u16 rates_6fire_vl[] = {0x00, 0x01, 0x00, 0x01, 0x00, 0x01}; static const u16 rates_6fire_vh[] = {0x11, 0x11, 0x10, 0x10, 0x00, 0x00}; +static DECLARE_TLV_DB_MINMAX(tlv_output, -9000, 0); + enum { DIGITAL_THRU_ONLY_SAMPLERATE = 3 }; @@ -78,8 +61,7 @@ static void usb6fire_control_master_vol_update(struct control_runtime *rt) struct comm_runtime *comm_rt = rt->chip->comm; if (comm_rt) { /* set volume */ - comm_rt->write8(comm_rt, 0x12, 0x0f, 0x7f - - log_volume_table[rt->master_vol]); + comm_rt->write8(comm_rt, 0x12, 0x0f, 180 - rt->master_vol); /* unmute */ comm_rt->write8(comm_rt, 0x12, 0x0e, 0x00); } @@ -170,7 +152,7 @@ static int usb6fire_control_master_vol_info(struct snd_kcontrol *kcontrol, uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 1; uinfo->value.integer.min = 0; - uinfo->value.integer.max = 127; + uinfo->value.integer.max = 180; return 0; } @@ -291,10 +273,12 @@ static struct __devinitdata snd_kcontrol_new elements[] = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Master Playback Volume", .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, .info = usb6fire_control_master_vol_info, .get = usb6fire_control_master_vol_get, - .put = usb6fire_control_master_vol_put + .put = usb6fire_control_master_vol_put, + .tlv = { .p = tlv_output } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -- cgit v1.2.1 From f90ffbf3c68a69714b4273b203d4deb5ae81d8d6 Mon Sep 17 00:00:00 2001 From: Torsten Schenk Date: Wed, 22 Feb 2012 15:21:12 +0100 Subject: ALSA: snd-usb-6fire: add individual volume control for analog channels Add a stereo volume control for every analog output pair 1/2, 3/4, 5/6. Signed-off-by: Torsten Schenk Signed-off-by: Takashi Iwai --- sound/usb/6fire/control.c | 146 +++++++++++++++++++++++++++++++++++++++------- sound/usb/6fire/control.h | 3 +- 2 files changed, 126 insertions(+), 23 deletions(-) (limited to 'sound/usb') diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c index b00b8bb88c63..c22cc29e33d7 100644 --- a/sound/usb/6fire/control.c +++ b/sound/usb/6fire/control.c @@ -7,6 +7,10 @@ * Created: Jan 01, 2011 * Copyright: (C) Torsten Schenk * + * Thanks to: + * - Holger Ruckdeschel: he found out how to control individual channel + * volumes and introduced mute switch + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -39,7 +43,7 @@ init_data[] = { { 0x22, 0x03, 0x00 }, { 0x20, 0x03, 0x08 }, { 0x22, 0x04, 0x00 }, { 0x20, 0x04, 0x08 }, { 0x22, 0x05, 0x01 }, { 0x20, 0x05, 0x08 }, { 0x22, 0x04, 0x01 }, { 0x12, 0x04, 0x00 }, { 0x12, 0x05, 0x00 }, - { 0x12, 0x0d, 0x78 }, { 0x12, 0x21, 0x82 }, { 0x12, 0x22, 0x80 }, + { 0x12, 0x0d, 0x38 }, { 0x12, 0x21, 0x82 }, { 0x12, 0x22, 0x80 }, { 0x12, 0x23, 0x00 }, { 0x12, 0x06, 0x02 }, { 0x12, 0x03, 0x00 }, { 0x12, 0x02, 0x00 }, { 0x22, 0x03, 0x01 }, { 0 } /* TERMINATING ENTRY */ @@ -56,15 +60,18 @@ enum { DIGITAL_THRU_ONLY_SAMPLERATE = 3 }; -static void usb6fire_control_master_vol_update(struct control_runtime *rt) +static void usb6fire_control_output_vol_update(struct control_runtime *rt) { struct comm_runtime *comm_rt = rt->chip->comm; - if (comm_rt) { - /* set volume */ - comm_rt->write8(comm_rt, 0x12, 0x0f, 180 - rt->master_vol); - /* unmute */ - comm_rt->write8(comm_rt, 0x12, 0x0e, 0x00); - } + int i; + + if (comm_rt) + for (i = 0; i < 6; i++) + if (!(rt->ovol_updated & (1 << i))) { + comm_rt->write8(comm_rt, 0x12, 0x0f + i, + 180 - rt->output_vol[i]); + rt->ovol_updated |= 1 << i; + } } static void usb6fire_control_line_phono_update(struct control_runtime *rt) @@ -146,34 +153,58 @@ static int usb6fire_control_streaming_update(struct control_runtime *rt) return -EINVAL; } -static int usb6fire_control_master_vol_info(struct snd_kcontrol *kcontrol, +static int usb6fire_control_output_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; + uinfo->count = 2; uinfo->value.integer.min = 0; uinfo->value.integer.max = 180; return 0; } -static int usb6fire_control_master_vol_put(struct snd_kcontrol *kcontrol, +static int usb6fire_control_output_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct control_runtime *rt = snd_kcontrol_chip(kcontrol); + unsigned int ch = kcontrol->private_value; int changed = 0; - if (rt->master_vol != ucontrol->value.integer.value[0]) { - rt->master_vol = ucontrol->value.integer.value[0]; - usb6fire_control_master_vol_update(rt); + + if (ch > 4) { + snd_printk(KERN_ERR PREFIX "Invalid channel in volume control."); + return -EINVAL; + } + + if (rt->output_vol[ch] != ucontrol->value.integer.value[0]) { + rt->output_vol[ch] = ucontrol->value.integer.value[0]; + rt->ovol_updated &= ~(1 << ch); changed = 1; } + if (rt->output_vol[ch + 1] != ucontrol->value.integer.value[1]) { + rt->output_vol[ch + 1] = ucontrol->value.integer.value[1]; + rt->ovol_updated &= ~(2 << ch); + changed = 1; + } + + if (changed) + usb6fire_control_output_vol_update(rt); + return changed; } -static int usb6fire_control_master_vol_get(struct snd_kcontrol *kcontrol, +static int usb6fire_control_output_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct control_runtime *rt = snd_kcontrol_chip(kcontrol); - ucontrol->value.integer.value[0] = rt->master_vol; + unsigned int ch = kcontrol->private_value; + + if (ch > 4) { + snd_printk(KERN_ERR PREFIX "Invalid channel in volume control."); + return -EINVAL; + } + + ucontrol->value.integer.value[0] = rt->output_vol[ch]; + ucontrol->value.integer.value[1] = rt->output_vol[ch + 1]; return 0; } @@ -268,18 +299,47 @@ static int usb6fire_control_digital_thru_get(struct snd_kcontrol *kcontrol, return 0; } -static struct __devinitdata snd_kcontrol_new elements[] = { +static struct __devinitdata snd_kcontrol_new vol_elements[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Volume", + .name = "Analog Playback Volume", .index = 0, + .private_value = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .info = usb6fire_control_output_vol_info, + .get = usb6fire_control_output_vol_get, + .put = usb6fire_control_output_vol_put, + .tlv = { .p = tlv_output } + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Analog Playback Volume", + .index = 1, + .private_value = 2, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .info = usb6fire_control_output_vol_info, + .get = usb6fire_control_output_vol_get, + .put = usb6fire_control_output_vol_put, + .tlv = { .p = tlv_output } + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Analog Playback Volume", + .index = 2, + .private_value = 4, .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, - .info = usb6fire_control_master_vol_info, - .get = usb6fire_control_master_vol_get, - .put = usb6fire_control_master_vol_put, + .info = usb6fire_control_output_vol_info, + .get = usb6fire_control_output_vol_get, + .put = usb6fire_control_output_vol_put, .tlv = { .p = tlv_output } }, + {} +}; + +static struct __devinitdata snd_kcontrol_new elements[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Line/Phono Capture Route", @@ -310,6 +370,40 @@ static struct __devinitdata snd_kcontrol_new elements[] = { {} }; +static int usb6fire_control_add_virtual( + struct control_runtime *rt, + struct snd_card *card, + char *name, + struct snd_kcontrol_new *elems) +{ + int ret; + int i; + struct snd_kcontrol *vmaster = + snd_ctl_make_virtual_master(name, tlv_output); + struct snd_kcontrol *control; + + if (!vmaster) + return -ENOMEM; + ret = snd_ctl_add(card, vmaster); + if (ret < 0) + return ret; + + i = 0; + while (elems[i].name) { + control = snd_ctl_new1(&elems[i], rt); + if (!control) + return -ENOMEM; + ret = snd_ctl_add(card, control); + if (ret < 0) + return ret; + ret = snd_ctl_add_slave(vmaster, control); + if (ret < 0) + return ret; + i++; + } + return 0; +} + int __devinit usb6fire_control_init(struct sfire_chip *chip) { int i; @@ -335,9 +429,17 @@ int __devinit usb6fire_control_init(struct sfire_chip *chip) usb6fire_control_opt_coax_update(rt); usb6fire_control_line_phono_update(rt); - usb6fire_control_master_vol_update(rt); + usb6fire_control_output_vol_update(rt); usb6fire_control_streaming_update(rt); + ret = usb6fire_control_add_virtual(rt, chip->card, + "Master Playback Volume", vol_elements); + if (ret) { + kfree(rt); + snd_printk(KERN_ERR PREFIX "cannot add control.\n"); + return ret; + } + i = 0; while (elements[i].name) { ret = snd_ctl_add(chip->card, snd_ctl_new1(&elements[i], rt)); diff --git a/sound/usb/6fire/control.h b/sound/usb/6fire/control.h index 0dcb1d2f522c..ce024113c98f 100644 --- a/sound/usb/6fire/control.h +++ b/sound/usb/6fire/control.h @@ -43,7 +43,8 @@ struct control_runtime { bool line_phono_switch; bool digital_thru_switch; bool usb_streaming; - u8 master_vol; + u8 output_vol[6]; + u8 ovol_updated; }; int __devinit usb6fire_control_init(struct sfire_chip *chip); -- cgit v1.2.1 From d97c735a1047fa06165e55da32154cf0e6b9419c Mon Sep 17 00:00:00 2001 From: Torsten Schenk Date: Wed, 22 Feb 2012 15:21:23 +0100 Subject: ALSA: snd-usb-6fire: add mute control for analog outputs Add a mute control for every analog output channel. Signed-off-by: Torsten Schenk Signed-off-by: Takashi Iwai --- sound/usb/6fire/control.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++ sound/usb/6fire/control.h | 1 + 2 files changed, 96 insertions(+) (limited to 'sound/usb') 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) } } +static void usb6fire_control_output_mute_update(struct control_runtime *rt) +{ + struct comm_runtime *comm_rt = rt->chip->comm; + + if (comm_rt) + comm_rt->write8(comm_rt, 0x12, 0x0e, ~rt->output_mute); +} + static void usb6fire_control_line_phono_update(struct control_runtime *rt) { struct comm_runtime *comm_rt = rt->chip->comm; @@ -208,6 +216,51 @@ static int usb6fire_control_output_vol_get(struct snd_kcontrol *kcontrol, return 0; } +static int usb6fire_control_output_mute_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct control_runtime *rt = snd_kcontrol_chip(kcontrol); + unsigned int ch = kcontrol->private_value; + u8 old = rt->output_mute; + u8 value = 0; + + if (ch > 4) { + snd_printk(KERN_ERR PREFIX "Invalid channel in volume control."); + return -EINVAL; + } + + rt->output_mute &= ~(3 << ch); + if (ucontrol->value.integer.value[0]) + value |= 1; + if (ucontrol->value.integer.value[1]) + value |= 2; + rt->output_mute |= value << ch; + + if (rt->output_mute != old) + usb6fire_control_output_mute_update(rt); + + return rt->output_mute != old; +} + +static int usb6fire_control_output_mute_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct control_runtime *rt = snd_kcontrol_chip(kcontrol); + unsigned int ch = kcontrol->private_value; + u8 value = rt->output_mute >> ch; + + if (ch > 4) { + snd_printk(KERN_ERR PREFIX "Invalid channel in volume control."); + return -EINVAL; + } + + ucontrol->value.integer.value[0] = 1 & value; + value >>= 1; + ucontrol->value.integer.value[1] = 1 & value; + + return 0; +} + static int usb6fire_control_line_phono_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -339,6 +392,40 @@ static struct __devinitdata snd_kcontrol_new vol_elements[] = { {} }; +static struct __devinitdata snd_kcontrol_new mute_elements[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Analog Playback Switch", + .index = 0, + .private_value = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = snd_ctl_boolean_stereo_info, + .get = usb6fire_control_output_mute_get, + .put = usb6fire_control_output_mute_put, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Analog Playback Switch", + .index = 1, + .private_value = 2, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = snd_ctl_boolean_stereo_info, + .get = usb6fire_control_output_mute_get, + .put = usb6fire_control_output_mute_put, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Analog Playback Switch", + .index = 2, + .private_value = 4, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = snd_ctl_boolean_stereo_info, + .get = usb6fire_control_output_mute_get, + .put = usb6fire_control_output_mute_put, + }, + {} +}; + static struct __devinitdata snd_kcontrol_new elements[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -430,13 +517,21 @@ int __devinit usb6fire_control_init(struct sfire_chip *chip) usb6fire_control_opt_coax_update(rt); usb6fire_control_line_phono_update(rt); usb6fire_control_output_vol_update(rt); + usb6fire_control_output_mute_update(rt); usb6fire_control_streaming_update(rt); ret = usb6fire_control_add_virtual(rt, chip->card, "Master Playback Volume", vol_elements); if (ret) { + snd_printk(KERN_ERR PREFIX "cannot add control.\n"); kfree(rt); + return ret; + } + ret = usb6fire_control_add_virtual(rt, chip->card, + "Master Playback Switch", mute_elements); + if (ret) { snd_printk(KERN_ERR PREFIX "cannot add control.\n"); + kfree(rt); return ret; } 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 { bool usb_streaming; u8 output_vol[6]; u8 ovol_updated; + u8 output_mute; }; int __devinit usb6fire_control_init(struct sfire_chip *chip); -- cgit v1.2.1 From 06bb4e7435019ff9b6dbc9b1d02d8babb36d8177 Mon Sep 17 00:00:00 2001 From: Torsten Schenk Date: Wed, 22 Feb 2012 15:21:30 +0100 Subject: ALSA: snd-usb-6fire: add analog input volume control Add a stereo volume control for analog input channel pair 1/2. Signed-off-by: Torsten Schenk Signed-off-by: Takashi Iwai --- sound/usb/6fire/control.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++ sound/usb/6fire/control.h | 2 ++ 2 files changed, 73 insertions(+) (limited to 'sound/usb') diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c index a2bbf48c6413..07ed914d5e71 100644 --- a/sound/usb/6fire/control.c +++ b/sound/usb/6fire/control.c @@ -55,6 +55,7 @@ static const u16 rates_6fire_vl[] = {0x00, 0x01, 0x00, 0x01, 0x00, 0x01}; static const u16 rates_6fire_vh[] = {0x11, 0x11, 0x10, 0x10, 0x00, 0x00}; static DECLARE_TLV_DB_MINMAX(tlv_output, -9000, 0); +static DECLARE_TLV_DB_MINMAX(tlv_input, -1500, 1500); enum { DIGITAL_THRU_ONLY_SAMPLERATE = 3 @@ -82,6 +83,20 @@ static void usb6fire_control_output_mute_update(struct control_runtime *rt) comm_rt->write8(comm_rt, 0x12, 0x0e, ~rt->output_mute); } +static void usb6fire_control_input_vol_update(struct control_runtime *rt) +{ + struct comm_runtime *comm_rt = rt->chip->comm; + int i; + + if (comm_rt) + for (i = 0; i < 2; i++) + if (!(rt->ivol_updated & (1 << i))) { + comm_rt->write8(comm_rt, 0x12, 0x1c + i, + rt->input_vol[i] & 0x3f); + rt->ivol_updated |= 1 << i; + } +} + static void usb6fire_control_line_phono_update(struct control_runtime *rt) { struct comm_runtime *comm_rt = rt->chip->comm; @@ -261,6 +276,50 @@ static int usb6fire_control_output_mute_get(struct snd_kcontrol *kcontrol, return 0; } +static int usb6fire_control_input_vol_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 30; + return 0; +} + +static int usb6fire_control_input_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct control_runtime *rt = snd_kcontrol_chip(kcontrol); + int changed = 0; + + if (rt->input_vol[0] != ucontrol->value.integer.value[0]) { + rt->input_vol[0] = ucontrol->value.integer.value[0] - 15; + rt->ivol_updated &= ~(1 << 0); + changed = 1; + } + if (rt->input_vol[1] != ucontrol->value.integer.value[1]) { + rt->input_vol[1] = ucontrol->value.integer.value[1] - 15; + rt->ivol_updated &= ~(1 << 1); + changed = 1; + } + + if (changed) + usb6fire_control_input_vol_update(rt); + + return changed; +} + +static int usb6fire_control_input_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct control_runtime *rt = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = rt->input_vol[0] + 15; + ucontrol->value.integer.value[1] = rt->input_vol[1] + 15; + + return 0; +} + static int usb6fire_control_line_phono_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -454,6 +513,17 @@ static struct __devinitdata snd_kcontrol_new elements[] = { .get = usb6fire_control_digital_thru_get, .put = usb6fire_control_digital_thru_put }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Analog Capture Volume", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | + SNDRV_CTL_ELEM_ACCESS_TLV_READ, + .info = usb6fire_control_input_vol_info, + .get = usb6fire_control_input_vol_get, + .put = usb6fire_control_input_vol_put, + .tlv = { .p = tlv_input } + }, {} }; @@ -518,6 +588,7 @@ int __devinit usb6fire_control_init(struct sfire_chip *chip) usb6fire_control_line_phono_update(rt); usb6fire_control_output_vol_update(rt); usb6fire_control_output_mute_update(rt); + usb6fire_control_input_vol_update(rt); usb6fire_control_streaming_update(rt); ret = usb6fire_control_add_virtual(rt, chip->card, diff --git a/sound/usb/6fire/control.h b/sound/usb/6fire/control.h index 9f9eb647bc6b..9a596d95474a 100644 --- a/sound/usb/6fire/control.h +++ b/sound/usb/6fire/control.h @@ -46,6 +46,8 @@ struct control_runtime { u8 output_vol[6]; u8 ovol_updated; u8 output_mute; + s8 input_vol[2]; + u8 ivol_updated; }; int __devinit usb6fire_control_init(struct sfire_chip *chip); -- cgit v1.2.1 From adef39c0ea2e5deae5c4f2917b23694b68535e45 Mon Sep 17 00:00:00 2001 From: Torsten Schenk Date: Fri, 24 Feb 2012 21:34:22 +0100 Subject: ALSA: snd-usb-6fire: Select missing SND_VMASTER option in Kconfig Signed-off-by: Torsten Schenk Signed-off-by: Takashi Iwai --- sound/usb/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'sound/usb') diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index 3efc21c3d67c..ff77b28f3da1 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig @@ -106,6 +106,7 @@ config SND_USB_6FIRE select BITREVERSE select SND_RAWMIDI select SND_PCM + select SND_VMASTER help Say Y here to include support for TerraTec 6fire DMX USB interface. -- cgit v1.2.1 From 0717d0f5d2737a63650a8d928360769e0d411bd5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 15 Mar 2012 16:14:38 +0100 Subject: ALSA: usb-audio - Fix build error by consitification of rate list Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'sound/usb') diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 0220b0f335b9..0eed6115c2d4 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -695,6 +695,7 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime, struct snd_usb_substream *subs) { struct audioformat *fp; + int *rate_list; int count = 0, needs_knot = 0; int err; @@ -708,7 +709,8 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime, if (!needs_knot) return 0; - subs->rate_list.list = kmalloc(sizeof(int) * count, GFP_KERNEL); + subs->rate_list.list = rate_list = + kmalloc(sizeof(int) * count, GFP_KERNEL); if (!subs->rate_list.list) return -ENOMEM; subs->rate_list.count = count; @@ -717,7 +719,7 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime, list_for_each_entry(fp, &subs->fmt_list, list) { int i; for (i = 0; i < fp->nr_rates; i++) - subs->rate_list.list[count++] = fp->rate_table[i]; + rate_list[count++] = fp->rate_table[i]; } err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &subs->rate_list); -- cgit v1.2.1