[alsa-devel] [PATCH] ALSA: hda - Fix the workaround for conflicting IEC958 controls
Anssi Hannula
anssi.hannula at iki.fi
Sun Feb 10 12:05:14 CET 2013
10.02.2013 12:38, Takashi Iwai kirjoitti:
> At Sat, 9 Feb 2013 00:44:39 +0200,
> Anssi Hannula wrote:
>>
>> Commit dcda5806165c155d90b9aa466a1602cf4726012b ("ALSA: hda - Add
>> workaround for conflicting IEC958 controls") added a workaround for
>> cards that have both an S/PDIF and an HDMI device, so that S/PDIF IEC958
>> controls will be moved to device=1 on such cards.
>>
>> However, the workaround did not take it into account that the S/PDIF and
>> HDMI devices may be on different codecs of the same card. Currently this
>> is always the case, and the workaround therefore fails to work.
>>
>> Fix the workaround to handle card-wide IEC958 conflicts.
>>
>> Reported-by: Stephan Raue <stephan at openelec.tv>
>> Signed-off-by: Anssi Hannula <anssi.hannula at iki.fi>
>> ---
>>
>> Unfortunately this seems to cause a nasty issue with alsa-lib 1.0.26:
>> $ amixer scontrols -c 0
>> ALSA lib simple_none.c:1551:(simple_add1) helem (MIXER,'IEC958 Playback Switch',0,1,0) appears twice or more
>> amixer: Mixer hw:0 load error: Invalid argument
>>
>> The non-simple-mode "amixer controls -c 0" works fine, though.
>>
>> Not really sure what to do now then, do we revert the workaround
>> completely and devise a different workaround/fix for this, or do you
>> have some other good ideas?
>
> If the element isn't really dup'ed, it must be a bug in alsa-lib mixer
> abstraction, so it should be fixed there.
This is because the simple mixer interface only identifies controls by
name+index:
http://www.alsa-project.org/alsa-doc/alsa-lib/group___simple_mixer.html
So controls that only differ by device (or subdevice?) are considered
duplicated. I did look at the code but saw no straight-forward way to
fix it, other than to introduce devices (and subdevices) to the simple
mixer API (which is used by outside applications).
Anyway, wouldn't breaking "old" alsa-lib make this way of fixing it a
no-go (the error is fatal and mixer creation fails completely)?
> Could you add alsa-info.sh output of this board (at best before and
> after your patch)?
Here's one after patch (can't get one before patch right now, but I
guess it isn't needed since the cause is very clear):
http://www.alsa-project.org/db/?f=bb3fc8680b372c0475719d42d7fc8b2bb7bfb4eb
(this one has alsa-lib hack applied which ignores the failure to add the
control so that the mixer error is non-fatal)
>
> thanks,
>
> Takashi
>
>
>>
>>
>> sound/pci/hda/hda_codec.c | 27 +++++++++++++++------------
>> sound/pci/hda/hda_codec.h | 4 +++-
>> 2 files changed, 18 insertions(+), 13 deletions(-)
>>
>> diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
>> index 822df97..fe5d6fc 100644
>> --- a/sound/pci/hda/hda_codec.c
>> +++ b/sound/pci/hda/hda_codec.c
>> @@ -3135,25 +3135,28 @@ int snd_hda_create_dig_out_ctls(struct hda_codec *codec,
>> int idx, dev = 0;
>> const int spdif_pcm_dev = 1;
>> struct hda_spdif_out *spdif;
>> + struct hda_codec *c;
>>
>> - if (codec->primary_dig_out_type == HDA_PCM_TYPE_HDMI &&
>> + if (codec->bus->primary_dig_out_type == HDA_PCM_TYPE_HDMI &&
>> type == HDA_PCM_TYPE_SPDIF) {
>> dev = spdif_pcm_dev;
>> - } else if (codec->primary_dig_out_type == HDA_PCM_TYPE_SPDIF &&
>> + } else if (codec->bus->primary_dig_out_type == HDA_PCM_TYPE_SPDIF &&
>> type == HDA_PCM_TYPE_HDMI) {
>> - for (idx = 0; idx < codec->spdif_out.used; idx++) {
>> - spdif = snd_array_elem(&codec->spdif_out, idx);
>> - for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
>> - kctl = find_mixer_ctl(codec, dig_mix->name, 0, idx);
>> - if (!kctl)
>> - break;
>> - kctl->id.device = spdif_pcm_dev;
>> + list_for_each_entry(c, &codec->bus->codec_list, list) {
>> + for (idx = 0; idx < c->spdif_out.used; idx++) {
>> + spdif = snd_array_elem(&c->spdif_out, idx);
>> + for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
>> + kctl = find_mixer_ctl(c, dig_mix->name, 0, idx);
>> + if (!kctl)
>> + break;
>> + kctl->id.device = spdif_pcm_dev;
>> + }
>> }
>> }
>> - codec->primary_dig_out_type = HDA_PCM_TYPE_HDMI;
>> + codec->bus->primary_dig_out_type = HDA_PCM_TYPE_HDMI;
>> }
>> - if (!codec->primary_dig_out_type)
>> - codec->primary_dig_out_type = type;
>> + if (!codec->bus->primary_dig_out_type)
>> + codec->bus->primary_dig_out_type = type;
>>
>> idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch", dev);
>> if (idx < 0) {
>> diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
>> index 8665540..ab807f7 100644
>> --- a/sound/pci/hda/hda_codec.h
>> +++ b/sound/pci/hda/hda_codec.h
>> @@ -671,6 +671,9 @@ struct hda_bus {
>> unsigned int response_reset:1; /* controller was reset */
>> unsigned int in_reset:1; /* during reset operation */
>> unsigned int power_keep_link_on:1; /* don't power off HDA link */
>> +
>> + /* primary digital out PCM type */
>> + int primary_dig_out_type;
>> };
>>
>> /*
>> @@ -837,7 +840,6 @@ struct hda_codec {
>> struct mutex hash_mutex;
>> struct snd_array spdif_out;
>> unsigned int spdif_in_enable; /* SPDIF input enable? */
>> - int primary_dig_out_type; /* primary digital out PCM type */
>> const hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
>> struct snd_array init_pins; /* initial (BIOS) pin configurations */
>> struct snd_array driver_pins; /* pin configs set by codec parser */
>> --
>> 1.7.10
>>
>
--
Anssi Hannula
More information about the Alsa-devel
mailing list