#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>
static struct snd_usb_audio *usb_chip[SNDRV_CARDS];
static struct usb_driver usb_audio_driver;
#ifdef CONFIG_SND_RK_SOC
-#define USB_AUDIO_CARD_NUM 2
+#define USB_AUDIO_CARD_NUM 3
struct switch_dev *usb_audio_sdev;
#endif
+#ifdef CONFIG_SWITCH
+//usb audio card will begin from RBASE_USB_AUDIO_IDX.
+#define RBASE_USB_AUDIO_IDX (3)
+#define NO_USBAUDIO_PLAYBACK (-1)
+#define NO_USBAUDIO_CAPTURE (-1)
+
+struct usb_audio_switch {
+ int playback_switch_cur_state;
+ int capture_switch_cur_state;
+ struct switch_dev sUsbaudio_Playback;
+ struct switch_dev sUsbaudio_Capture;
+};
+
+// state: card*10 + device
+static struct usb_audio_switch sUsbaudio_Switch = {
+ .playback_switch_cur_state = NO_USBAUDIO_PLAYBACK,
+ .capture_switch_cur_state = NO_USBAUDIO_CAPTURE,
+ .sUsbaudio_Playback = {
+ .name = "usb_audio_playback",
+ .state = NO_USBAUDIO_PLAYBACK, //this means no usb audio playback available
+ },
+
+ .sUsbaudio_Capture = {
+ .name = "usb_audio_capture",
+ .state = NO_USBAUDIO_CAPTURE, //this means no usb audio capture available
+ },
+};
+#endif
+
/*
* disconnect streams
* called from snd_usb_audio_disconnect()
return 0;
}
+#ifdef CONFIG_SWITCH
+static int usb_audio_card_switch_state_update(struct snd_card *card, bool force){
+ struct snd_device *dev;
+ struct snd_pcm *pcm;
+ struct snd_pcm_str *pstr;
+
+ if (snd_BUG_ON(!card))
+ return -EINVAL;
+ //we use the latest devices
+ list_for_each_entry(dev, &card->devices, list) {
+ if (dev->type == SNDRV_DEV_PCM && dev->state == SNDRV_DEV_REGISTERED) {
+ pcm = (struct snd_pcm*)dev->device_data;
+ if (NULL != pcm) {
+ //playback available?
+ pstr = &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK];
+ snd_printdd(KERN_INFO "playback substream_count: 0x%x\n", pstr->substream_count);
+ if (pstr->substream_count > 0) {
+ sUsbaudio_Switch.playback_switch_cur_state = card->number * 10;
+ }
+ //capture available?
+ pstr = &pcm->streams[SNDRV_PCM_STREAM_CAPTURE];
+ snd_printdd(KERN_INFO "capture substream_count: 0x%x\n", pstr->substream_count);
+ if (pstr->substream_count > 0) {
+ sUsbaudio_Switch.capture_switch_cur_state = card->number * 10;
+ }
+ }
+ }
+ }
+ if (force) {
+ switch_set_state(&sUsbaudio_Switch.sUsbaudio_Playback, sUsbaudio_Switch.playback_switch_cur_state);
+ switch_set_state(&sUsbaudio_Switch.sUsbaudio_Capture, sUsbaudio_Switch.capture_switch_cur_state);
+ }
+ return 0;
+
+}
+
+static void usb_audio_switch_state_update_all(void)
+{
+ int index = 0;
+ struct snd_card *card;
+
+ sUsbaudio_Switch.playback_switch_cur_state = NO_USBAUDIO_PLAYBACK;
+ sUsbaudio_Switch.capture_switch_cur_state = NO_USBAUDIO_CAPTURE;
+
+ for (index = 0; index < SNDRV_CARDS; ++index) {
+ if (NULL != usb_chip[index]) {
+ card = usb_chip[index]->card;
+ usb_audio_card_switch_state_update(card, false);
+ }
+ }
+
+ switch_set_state(&sUsbaudio_Switch.sUsbaudio_Playback,
+ sUsbaudio_Switch.playback_switch_cur_state);
+ switch_set_state(&sUsbaudio_Switch.sUsbaudio_Capture,
+ sUsbaudio_Switch.capture_switch_cur_state);
+}
+#endif
+
+
/*
* probe the active usb device
*
/* it's a fresh one.
* now look for an empty slot and create a new card instance
*/
+ // use RBASE_USB_AUDIO_IDX instead of zero, modify by zxg.
for (i = 0; i < SNDRV_CARDS; i++)
if (enable[i] && ! usb_chip[i] &&
(vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) &&
if (snd_card_register(chip->card) < 0) {
goto __error;
}
-
+#ifdef CONFIG_SWITCH
+ if (usb_audio_card_switch_state_update(chip->card, true) < 0) {
+ printk(KERN_ERR "usb_audio_card_switch_state_update failed!!!\n");
+ goto __error;
+ }
+#endif
usb_chip[chip->index] = chip;
chip->num_interfaces++;
chip->probing = 0;
} else {
mutex_unlock(®ister_mutex);
}
+#ifdef CONFIG_SWITCH
+ usb_audio_switch_state_update_all();
+#endif
}
/*
static int __init snd_usb_audio_init(void)
{
+ int ret;
+#ifdef CONFIG_SWITCH
+ int i;
+ ret = switch_dev_register(&sUsbaudio_Switch.sUsbaudio_Playback);
+ if (ret)
+ goto err;
+ ret = switch_dev_register(&sUsbaudio_Switch.sUsbaudio_Capture);
+ if (ret)
+ goto err_drv;
+
+ switch_set_state(&sUsbaudio_Switch.sUsbaudio_Playback, NO_USBAUDIO_PLAYBACK);
+ switch_set_state(&sUsbaudio_Switch.sUsbaudio_Capture, NO_USBAUDIO_CAPTURE);
+#endif
+
if (nrpacks < 1 || nrpacks > MAX_PACKS) {
printk(KERN_WARNING "invalid nrpacks value.\n");
return -EINVAL;
}
-
#ifdef CONFIG_SND_RK_SOC
usb_audio_sdev = kzalloc(sizeof(usb_audio_sdev), GFP_KERNEL);
usb_audio_sdev->name = "usb_audio";
}
#endif
+ //re initial array index for rebasing usb audio cards create, modify by zxg.
+ for(i=0; i<SNDRV_CARDS; ++i){
+ index[i] = i;
+ }
+
return usb_register(&usb_audio_driver);
+
+err_drv:
+#ifdef CONFIG_SWITCH
+ switch_dev_unregister(&sUsbaudio_Switch.sUsbaudio_Playback);
+#endif
+err:
+ return ret;
+
}
static void __exit snd_usb_audio_cleanup(void)
#ifdef CONFIG_SND_RK_SOC
kfree(usb_audio_sdev);
#endif
+ switch_dev_unregister(&sUsbaudio_Switch.sUsbaudio_Capture);
+ switch_dev_unregister(&sUsbaudio_Switch.sUsbaudio_Playback);
}
module_init(snd_usb_audio_init);
+/* use late initcall_sync instead of module_init,
+ * make sure that usbaudio probe after board codec.
+ * added by zxg@rock-chips.com
+ */
+late_initcall_sync(snd_usb_audio_init);
module_exit(snd_usb_audio_cleanup);