[alsa-devel] [PATCH] ALSA: hda - Fix the workaround for conflicting IEC958 controls

Takashi Iwai tiwai at suse.de
Sun Feb 10 11:38:02 CET 2013


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.

Could you add alsa-info.sh output of this board (at best before and
after your patch)?


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
> 


More information about the Alsa-devel mailing list