mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 06:31:49 +00:00
ALSA: hda - HDMI sticky stream tag support
When we run the following commands in turn (with CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0), speaker-test -Dhw:0,3 -c2 -twav # HDMI speaker-test -Dhw:0,0 -c2 -twav # Analog The second command will produce sound in the analog lineout _as well as_ HDMI sink. The root cause is, device 0 "reuses" the same stream tag that was used by device 3, and the "intelhdmi - sticky stream id" patch leaves the HDMI codec in a functional state. So the HDMI codec happily accepts the audio samples which reuse its stream tag. The proposed solution is to remember the last device each azx_dev was assigned to, and prefer to 1) reuse the azx_dev (and hence the stream tag) the HDMI codec last used 2) or assign a never-used azx_dev for HDMI With this patch and the above two speaker-test commands, HDMI codec will use stream tag 8 and Analog codec will use 5. The stream tag used by HDMI codec won't be reused by others, as long as we don't run out of the 4 playback azx_dev's. The legacy Analog codec will continue to use stream tag 5 because its device id is 0 (this is a bit tricky). Signed-off-by: Wu Fengguang <fengguang.wu@intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
6b7b284958
commit
ef18beded8
@ -356,6 +356,7 @@ struct azx_dev {
|
|||||||
*/
|
*/
|
||||||
unsigned char stream_tag; /* assigned stream */
|
unsigned char stream_tag; /* assigned stream */
|
||||||
unsigned char index; /* stream index */
|
unsigned char index; /* stream index */
|
||||||
|
int device; /* last device number assigned to */
|
||||||
|
|
||||||
unsigned int opened :1;
|
unsigned int opened :1;
|
||||||
unsigned int running :1;
|
unsigned int running :1;
|
||||||
@ -1441,10 +1442,13 @@ static int __devinit azx_codec_configure(struct azx *chip)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* assign a stream for the PCM */
|
/* assign a stream for the PCM */
|
||||||
static inline struct azx_dev *azx_assign_device(struct azx *chip, int stream)
|
static inline struct azx_dev *
|
||||||
|
azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
int dev, i, nums;
|
int dev, i, nums;
|
||||||
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
struct azx_dev *res = NULL;
|
||||||
|
|
||||||
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
dev = chip->playback_index_offset;
|
dev = chip->playback_index_offset;
|
||||||
nums = chip->playback_streams;
|
nums = chip->playback_streams;
|
||||||
} else {
|
} else {
|
||||||
@ -1453,10 +1457,15 @@ static inline struct azx_dev *azx_assign_device(struct azx *chip, int stream)
|
|||||||
}
|
}
|
||||||
for (i = 0; i < nums; i++, dev++)
|
for (i = 0; i < nums; i++, dev++)
|
||||||
if (!chip->azx_dev[dev].opened) {
|
if (!chip->azx_dev[dev].opened) {
|
||||||
chip->azx_dev[dev].opened = 1;
|
res = &chip->azx_dev[dev];
|
||||||
return &chip->azx_dev[dev];
|
if (res->device == substream->pcm->device)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return NULL;
|
if (res) {
|
||||||
|
res->opened = 1;
|
||||||
|
res->device = substream->pcm->device;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* release the assigned stream */
|
/* release the assigned stream */
|
||||||
@ -1505,7 +1514,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
mutex_lock(&chip->open_mutex);
|
mutex_lock(&chip->open_mutex);
|
||||||
azx_dev = azx_assign_device(chip, substream->stream);
|
azx_dev = azx_assign_device(chip, substream);
|
||||||
if (azx_dev == NULL) {
|
if (azx_dev == NULL) {
|
||||||
mutex_unlock(&chip->open_mutex);
|
mutex_unlock(&chip->open_mutex);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
Loading…
Reference in New Issue
Block a user