diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-09-06 11:42:08 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-09-06 11:59:19 -0400 |
commit | 1a6003b525b9815ccd9d23ae3b70372a17d0bce2 (patch) | |
tree | c3d6babd6561a814f0e2caed8f896eba3082e0b6 | |
parent | 298efee7f5a20a32c9ebfa0f7469d87d84998ba1 (diff) |
ALSA: hda - Move non-PCM check to per_pin in patch_hdmi.c
Recently the check for non-PCM stream state was added to the generic
HDMI driver code. But this check should be done rather to each pin
instead of each converter. Otherwise when a different converter is
assigned at the next open, the audio infoframe can be inconsistent
with the setup using the previous converter.
For fixing this issue, this patch moves the state of the current
non-PCM status from per_cvt to per_pin. (In addition an unused
argument cvt_nid is stripped from hdmi_setup_channel_mapping())
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 46 |
1 files changed, 25 insertions, 21 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 5361298be4d0..333d5338c15c 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -61,7 +61,6 @@ struct hdmi_spec_per_cvt { | |||
61 | u32 rates; | 61 | u32 rates; |
62 | u64 formats; | 62 | u64 formats; |
63 | unsigned int maxbps; | 63 | unsigned int maxbps; |
64 | bool non_pcm; | ||
65 | }; | 64 | }; |
66 | 65 | ||
67 | struct hdmi_spec_per_pin { | 66 | struct hdmi_spec_per_pin { |
@@ -73,6 +72,7 @@ struct hdmi_spec_per_pin { | |||
73 | struct hdmi_eld sink_eld; | 72 | struct hdmi_eld sink_eld; |
74 | struct delayed_work work; | 73 | struct delayed_work work; |
75 | int repoll_count; | 74 | int repoll_count; |
75 | bool non_pcm; | ||
76 | }; | 76 | }; |
77 | 77 | ||
78 | struct hdmi_spec { | 78 | struct hdmi_spec { |
@@ -550,7 +550,6 @@ static void hdmi_debug_channel_mapping(struct hda_codec *codec, | |||
550 | 550 | ||
551 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, | 551 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, |
552 | hda_nid_t pin_nid, | 552 | hda_nid_t pin_nid, |
553 | hda_nid_t cvt_nid, | ||
554 | bool non_pcm, | 553 | bool non_pcm, |
555 | int ca) | 554 | int ca) |
556 | { | 555 | { |
@@ -712,27 +711,16 @@ static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, | |||
712 | } | 711 | } |
713 | 712 | ||
714 | static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, | 713 | static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, |
715 | hda_nid_t cvt_nid, struct snd_pcm_substream *substream) | 714 | bool non_pcm, |
715 | struct snd_pcm_substream *substream) | ||
716 | { | 716 | { |
717 | struct hdmi_spec *spec = codec->spec; | 717 | struct hdmi_spec *spec = codec->spec; |
718 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 718 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; |
719 | struct hdmi_spec_per_cvt *per_cvt; | ||
720 | struct hda_spdif_out *spdif; | ||
721 | hda_nid_t pin_nid = per_pin->pin_nid; | 719 | hda_nid_t pin_nid = per_pin->pin_nid; |
722 | int channels = substream->runtime->channels; | 720 | int channels = substream->runtime->channels; |
723 | struct hdmi_eld *eld; | 721 | struct hdmi_eld *eld; |
724 | int ca; | 722 | int ca; |
725 | int cvt_idx; | ||
726 | union audio_infoframe ai; | 723 | union audio_infoframe ai; |
727 | bool non_pcm = false; | ||
728 | |||
729 | cvt_idx = cvt_nid_to_cvt_index(spec, cvt_nid); | ||
730 | per_cvt = &spec->cvts[cvt_idx]; | ||
731 | |||
732 | mutex_lock(&codec->spdif_mutex); | ||
733 | spdif = snd_hda_spdif_out_of_nid(codec, cvt_nid); | ||
734 | non_pcm = !!(spdif->status & IEC958_AES0_NONAUDIO); | ||
735 | mutex_unlock(&codec->spdif_mutex); | ||
736 | 724 | ||
737 | eld = &spec->pins[pin_idx].sink_eld; | 725 | eld = &spec->pins[pin_idx].sink_eld; |
738 | if (!eld->monitor_present) | 726 | if (!eld->monitor_present) |
@@ -775,7 +763,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, | |||
775 | "pin=%d channels=%d\n", | 763 | "pin=%d channels=%d\n", |
776 | pin_nid, | 764 | pin_nid, |
777 | channels); | 765 | channels); |
778 | hdmi_setup_channel_mapping(codec, pin_nid, cvt_nid, non_pcm, ca); | 766 | hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca); |
779 | hdmi_stop_infoframe_trans(codec, pin_nid); | 767 | hdmi_stop_infoframe_trans(codec, pin_nid); |
780 | hdmi_fill_audio_infoframe(codec, pin_nid, | 768 | hdmi_fill_audio_infoframe(codec, pin_nid, |
781 | ai.bytes, sizeof(ai)); | 769 | ai.bytes, sizeof(ai)); |
@@ -783,11 +771,11 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, | |||
783 | } else { | 771 | } else { |
784 | /* For non-pcm audio switch, setup new channel mapping | 772 | /* For non-pcm audio switch, setup new channel mapping |
785 | * accordingly */ | 773 | * accordingly */ |
786 | if (per_cvt->non_pcm != non_pcm) | 774 | if (per_pin->non_pcm != non_pcm) |
787 | hdmi_setup_channel_mapping(codec, pin_nid, cvt_nid, non_pcm, ca); | 775 | hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca); |
788 | } | 776 | } |
789 | 777 | ||
790 | per_cvt->non_pcm = non_pcm; | 778 | per_pin->non_pcm = non_pcm; |
791 | } | 779 | } |
792 | 780 | ||
793 | 781 | ||
@@ -1080,6 +1068,7 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) | |||
1080 | per_pin = &spec->pins[pin_idx]; | 1068 | per_pin = &spec->pins[pin_idx]; |
1081 | 1069 | ||
1082 | per_pin->pin_nid = pin_nid; | 1070 | per_pin->pin_nid = pin_nid; |
1071 | per_pin->non_pcm = false; | ||
1083 | 1072 | ||
1084 | err = hdmi_read_pin_conn(codec, pin_idx); | 1073 | err = hdmi_read_pin_conn(codec, pin_idx); |
1085 | if (err < 0) | 1074 | if (err < 0) |
@@ -1109,7 +1098,6 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) | |||
1109 | 1098 | ||
1110 | per_cvt->cvt_nid = cvt_nid; | 1099 | per_cvt->cvt_nid = cvt_nid; |
1111 | per_cvt->channels_min = 2; | 1100 | per_cvt->channels_min = 2; |
1112 | per_cvt->non_pcm = false; | ||
1113 | if (chans <= 16) | 1101 | if (chans <= 16) |
1114 | per_cvt->channels_max = chans; | 1102 | per_cvt->channels_max = chans; |
1115 | 1103 | ||
@@ -1179,6 +1167,19 @@ static char *get_hdmi_pcm_name(int idx) | |||
1179 | return &names[idx][0]; | 1167 | return &names[idx][0]; |
1180 | } | 1168 | } |
1181 | 1169 | ||
1170 | static bool check_non_pcm_per_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) | ||
1171 | { | ||
1172 | struct hda_spdif_out *spdif; | ||
1173 | bool non_pcm; | ||
1174 | |||
1175 | mutex_lock(&codec->spdif_mutex); | ||
1176 | spdif = snd_hda_spdif_out_of_nid(codec, cvt_nid); | ||
1177 | non_pcm = !!(spdif->status & IEC958_AES0_NONAUDIO); | ||
1178 | mutex_unlock(&codec->spdif_mutex); | ||
1179 | return non_pcm; | ||
1180 | } | ||
1181 | |||
1182 | |||
1182 | /* | 1183 | /* |
1183 | * HDMI callbacks | 1184 | * HDMI callbacks |
1184 | */ | 1185 | */ |
@@ -1194,10 +1195,13 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
1194 | int pin_idx = hinfo_to_pin_index(spec, hinfo); | 1195 | int pin_idx = hinfo_to_pin_index(spec, hinfo); |
1195 | hda_nid_t pin_nid = spec->pins[pin_idx].pin_nid; | 1196 | hda_nid_t pin_nid = spec->pins[pin_idx].pin_nid; |
1196 | int pinctl; | 1197 | int pinctl; |
1198 | bool non_pcm; | ||
1199 | |||
1200 | non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); | ||
1197 | 1201 | ||
1198 | hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels); | 1202 | hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels); |
1199 | 1203 | ||
1200 | hdmi_setup_audio_infoframe(codec, pin_idx, cvt_nid, substream); | 1204 | hdmi_setup_audio_infoframe(codec, pin_idx, non_pcm, substream); |
1201 | 1205 | ||
1202 | pinctl = snd_hda_codec_read(codec, pin_nid, 0, | 1206 | pinctl = snd_hda_codec_read(codec, pin_nid, 0, |
1203 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 1207 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |