mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 04:10:18 +09:00
audio : fix usb audio no sound problem.
This commit is contained in:
138
sound/usb/card.c
138
sound/usb/card.c
@@ -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(®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<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);
|
||||
|
||||
Reference in New Issue
Block a user