summaryrefslogtreecommitdiff
path: root/sound/usb
diff options
context:
space:
mode:
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/card.c57
-rw-r--r--sound/usb/stream.c98
2 files changed, 153 insertions, 2 deletions
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 64952e2d3ed1..e0c0e25b7293 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -32,7 +32,6 @@
* indeed an AC3 stream packed in SPDIF frames (i.e. no real AC3 stream).
*/
-
#include <linux/bitops.h>
#include <linux/init.h>
#include <linux/list.h>
@@ -45,6 +44,9 @@
#include <linux/usb/audio.h>
#include <linux/usb/audio-v2.h>
#include <linux/module.h>
+#ifdef CONFIG_SWITCH
+#include <linux/switch.h>
+#endif
#include <sound/control.h>
#include <sound/core.h>
@@ -113,6 +115,18 @@ static DEFINE_MUTEX(register_mutex);
static struct snd_usb_audio *usb_chip[SNDRV_CARDS];
static struct usb_driver usb_audio_driver;
+#ifdef CONFIG_SWITCH
+enum switch_state {
+ STATE_CONNECTED_UNKNOWN = -1,
+ STATE_DISCONNECTED = 0,
+ STATE_CONNECTED = 1
+};
+
+static struct switch_dev usb_switch_dev = {
+ .name = "usb_audio",
+};
+#endif
+
/*
* disconnect streams
* called from snd_usb_audio_disconnect()
@@ -558,10 +572,15 @@ snd_usb_audio_probe(struct usb_device *dev,
goto __error;
}
+#ifdef CONFIG_SWITCH
+ switch_set_state(&usb_switch_dev, STATE_CONNECTED);
+#endif
+
usb_chip[chip->index] = chip;
chip->num_interfaces++;
chip->probing = 0;
mutex_unlock(&register_mutex);
+
return chip;
__error:
@@ -572,6 +591,7 @@ snd_usb_audio_probe(struct usb_device *dev,
}
mutex_unlock(&register_mutex);
__err_val:
+
return NULL;
}
@@ -584,6 +604,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
{
struct snd_card *card;
struct list_head *p, *n;
+ int i;
if (chip == (void *)-1L)
return;
@@ -595,6 +616,16 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
mutex_lock(&register_mutex);
chip->num_interfaces--;
+
+#ifdef CONFIG_SWITCH
+ for (i = 0; i < chip->index; i++) {
+ if (usb_chip[i])
+ break;
+ }
+ if (i == chip->index)
+ switch_set_state(&usb_switch_dev, STATE_DISCONNECTED);
+#endif
+
if (chip->num_interfaces <= 0) {
snd_card_disconnect(card);
/* release the pcm resources */
@@ -756,15 +787,37 @@ static struct usb_driver usb_audio_driver = {
static int __init snd_usb_audio_init(void)
{
+ int err = 0;
+
if (nrpacks < 1 || nrpacks > MAX_PACKS) {
printk(KERN_WARNING "invalid nrpacks value.\n");
return -EINVAL;
}
- return usb_register(&usb_audio_driver);
+
+#ifdef CONFIG_SWITCH
+ /* Add usb_audio swith class support */
+ err = switch_dev_register(&usb_switch_dev);
+ if (err < 0){
+ printk(KERN_ERR "failed to register switch device");
+ return -EINVAL;
+ }
+#endif
+
+ err = usb_register(&usb_audio_driver);
+ if (err) {
+#ifdef CONFIG_SWITCH
+ switch_dev_unregister(&usb_switch_dev);
+#endif
+ }
+
+ return err;
}
static void __exit snd_usb_audio_cleanup(void)
{
+#ifdef CONFIG_SWITCH
+ switch_dev_unregister(&usb_switch_dev);
+#endif
usb_deregister(&usb_audio_driver);
}
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 7db2f8958e79..70a07761f270 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -461,6 +461,89 @@ static struct uac2_output_terminal_descriptor *
return NULL;
}
+static int usb_device_sample_rate_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 = 192000;
+ return 0;
+}
+
+static int usb_device_sample_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct audioformat *fp = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] = fp->rate_min;
+ ucontrol->value.integer.value[1] = fp->rate_max;
+
+ return 0;
+}
+
+static int usb_device_pb_channels_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 1;
+ uinfo->value.integer.max = 2;
+ return 0;
+}
+
+static int usb_device_pb_channels_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct audioformat *fp = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] = fp->channels;
+ return 0;
+}
+
+static int usb_device_cap_channels_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 1;
+ uinfo->value.integer.max = 2;
+ return 0;
+}
+
+static int usb_device_cap_channels_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct audioformat *fp = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] = fp->channels;
+ return 0;
+}
+
+struct snd_kcontrol_new usb_device_sample_rate_control = {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "USB Device Sample Rate",
+ .info = usb_device_sample_rate_info,
+ .get = usb_device_sample_rate_get,
+};
+
+struct snd_kcontrol_new usb_device_pb_channels_control = {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "USB Device Playback Channels",
+ .info = usb_device_pb_channels_info,
+ .get = usb_device_pb_channels_get,
+};
+
+struct snd_kcontrol_new usb_device_cap_channels_control = {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "USB Device Capture Channels",
+ .info = usb_device_cap_channels_info,
+ .get = usb_device_cap_channels_get,
+};
+
int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
{
struct usb_device *dev;
@@ -697,6 +780,21 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
snd_usb_init_pitch(chip, iface_no, alts, fp);
snd_usb_init_sample_rate(chip, iface_no, alts, fp, fp->rate_max);
}
+
+ /* Add usb device sample rate control */
+ snd_ctl_add(chip->card,
+ snd_ctl_new1(&usb_device_sample_rate_control, fp));
+
+ /* Add usb device playback channels control */
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ snd_ctl_add(chip->card,
+ snd_ctl_new1(&usb_device_pb_channels_control, fp));
+
+ /* Add usb device capture channels control */
+ if (stream == SNDRV_PCM_STREAM_CAPTURE)
+ snd_ctl_add(chip->card,
+ snd_ctl_new1(&usb_device_cap_channels_control, fp));
+
return 0;
}