From 028772b4ef125a90cb04fbebba047f0c354d71bf Mon Sep 17 00:00:00 2001 From: smj Date: Tue, 28 Oct 2014 14:46:03 +0800 Subject: [PATCH] audio : fix usb audio no sound problem. --- sound/usb/card.c | 138 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 135 insertions(+), 3 deletions(-) diff --git a/sound/usb/card.c b/sound/usb/card.c index f00b15a7301f..bfac3568ae2c 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -45,7 +45,9 @@ #include #include #include +#ifdef CONFIG_SWITCH #include +#endif #include #include @@ -114,10 +116,39 @@ static DEFINE_MUTEX(register_mutex); 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() @@ -466,6 +497,65 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, 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 * @@ -520,6 +610,7 @@ snd_usb_audio_probe(struct usb_device *dev, /* 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)) && @@ -565,7 +656,12 @@ snd_usb_audio_probe(struct usb_device *dev, 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; @@ -627,6 +723,9 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, } else { mutex_unlock(®ister_mutex); } +#ifdef CONFIG_SWITCH + usb_audio_switch_state_update_all(); +#endif } /* @@ -770,11 +869,24 @@ static struct usb_driver usb_audio_driver = { 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"; @@ -785,7 +897,20 @@ static int __init snd_usb_audio_init(void) } #endif + //re initial array index for rebasing usb audio cards create, modify by zxg. + for(i=0; i