audio : fix usb audio no sound problem.

This commit is contained in:
smj
2014-10-28 14:46:03 +08:00
parent bcc506fddc
commit 028772b4ef

View File

@@ -45,7 +45,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>
@@ -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(&register_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<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)
@@ -794,7 +919,14 @@ 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);