Commit ef18beded8ddbaafdf4914bab209f77e60ae3a18
Committed by
Takashi Iwai
1 parent
6b7b284958
Exists in
master
and in
39 other branches
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>
Showing 1 changed file with 15 additions and 6 deletions Side-by-side Diff
sound/pci/hda/hda_intel.c
... | ... | @@ -356,6 +356,7 @@ |
356 | 356 | */ |
357 | 357 | unsigned char stream_tag; /* assigned stream */ |
358 | 358 | unsigned char index; /* stream index */ |
359 | + int device; /* last device number assigned to */ | |
359 | 360 | |
360 | 361 | unsigned int opened :1; |
361 | 362 | unsigned int running :1; |
362 | 363 | |
... | ... | @@ -1441,10 +1442,13 @@ |
1441 | 1442 | */ |
1442 | 1443 | |
1443 | 1444 | /* assign a stream for the PCM */ |
1444 | -static inline struct azx_dev *azx_assign_device(struct azx *chip, int stream) | |
1445 | +static inline struct azx_dev * | |
1446 | +azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream) | |
1445 | 1447 | { |
1446 | 1448 | int dev, i, nums; |
1447 | - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | |
1449 | + struct azx_dev *res = NULL; | |
1450 | + | |
1451 | + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | |
1448 | 1452 | dev = chip->playback_index_offset; |
1449 | 1453 | nums = chip->playback_streams; |
1450 | 1454 | } else { |
1451 | 1455 | |
... | ... | @@ -1453,10 +1457,15 @@ |
1453 | 1457 | } |
1454 | 1458 | for (i = 0; i < nums; i++, dev++) |
1455 | 1459 | if (!chip->azx_dev[dev].opened) { |
1456 | - chip->azx_dev[dev].opened = 1; | |
1457 | - return &chip->azx_dev[dev]; | |
1460 | + res = &chip->azx_dev[dev]; | |
1461 | + if (res->device == substream->pcm->device) | |
1462 | + break; | |
1458 | 1463 | } |
1459 | - return NULL; | |
1464 | + if (res) { | |
1465 | + res->opened = 1; | |
1466 | + res->device = substream->pcm->device; | |
1467 | + } | |
1468 | + return res; | |
1460 | 1469 | } |
1461 | 1470 | |
1462 | 1471 | /* release the assigned stream */ |
... | ... | @@ -1505,7 +1514,7 @@ |
1505 | 1514 | int err; |
1506 | 1515 | |
1507 | 1516 | mutex_lock(&chip->open_mutex); |
1508 | - azx_dev = azx_assign_device(chip, substream->stream); | |
1517 | + azx_dev = azx_assign_device(chip, substream); | |
1509 | 1518 | if (azx_dev == NULL) { |
1510 | 1519 | mutex_unlock(&chip->open_mutex); |
1511 | 1520 | return -EBUSY; |