aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_hdmi.c
diff options
context:
space:
mode:
authorWang Xingchao <xingchao.wang@linux.intel.com>2013-06-18 09:42:14 -0400
committerTakashi Iwai <tiwai@suse.de>2013-06-18 10:17:48 -0400
commit7ef166b831237e67b2ea83ce0c933c46ddd6eb26 (patch)
treeb5b34ae376f464d24c5ce7dea18e8c846ce4773e /sound/pci/hda/patch_hdmi.c
parentbddee96b5d0db869f47b195fe48c614ca824203c (diff)
ALSA: hda - Avoid choose same converter for unused pins
For Intel Haswell HDMI codecs, the pins choose converter 0 by default. This would cause conflict when playing audio on unused pins,the pin with physical device connected would get audio data too. i.e. Pin 0/1/2 default choose converter 0, pin 1 has HDMI monitor connected. when play audio on Pin 0 or pin 2, pin 1 could get audio data too. This patch configure unused pins to choose different converter. Signed-off-by: Wang Xingchao <xingchao.wang@linux.intel.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_hdmi.c')
-rw-r--r--sound/pci/hda/patch_hdmi.c89
1 files changed, 75 insertions, 14 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 844cf55a62b1..0687d536b563 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -1110,26 +1110,15 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
1110 return 0; 1110 return 0;
1111} 1111}
1112 1112
1113/* 1113static int hdmi_choose_cvt(struct hda_codec *codec,
1114 * HDA PCM callbacks 1114 int pin_idx, int *cvt_id, int *mux_id)
1115 */
1116static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
1117 struct hda_codec *codec,
1118 struct snd_pcm_substream *substream)
1119{ 1115{
1120 struct hdmi_spec *spec = codec->spec; 1116 struct hdmi_spec *spec = codec->spec;
1121 struct snd_pcm_runtime *runtime = substream->runtime;
1122 int pin_idx, cvt_idx, mux_idx = 0;
1123 struct hdmi_spec_per_pin *per_pin; 1117 struct hdmi_spec_per_pin *per_pin;
1124 struct hdmi_eld *eld;
1125 struct hdmi_spec_per_cvt *per_cvt = NULL; 1118 struct hdmi_spec_per_cvt *per_cvt = NULL;
1119 int cvt_idx, mux_idx = 0;
1126 1120
1127 /* Validate hinfo */
1128 pin_idx = hinfo_to_pin_index(spec, hinfo);
1129 if (snd_BUG_ON(pin_idx < 0))
1130 return -EINVAL;
1131 per_pin = get_pin(spec, pin_idx); 1121 per_pin = get_pin(spec, pin_idx);
1132 eld = &per_pin->sink_eld;
1133 1122
1134 /* Dynamically assign converter to stream */ 1123 /* Dynamically assign converter to stream */
1135 for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) { 1124 for (cvt_idx = 0; cvt_idx < spec->num_cvts; cvt_idx++) {
@@ -1147,10 +1136,77 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
1147 continue; 1136 continue;
1148 break; 1137 break;
1149 } 1138 }
1139
1150 /* No free converters */ 1140 /* No free converters */
1151 if (cvt_idx == spec->num_cvts) 1141 if (cvt_idx == spec->num_cvts)
1152 return -ENODEV; 1142 return -ENODEV;
1153 1143
1144 if (cvt_id)
1145 *cvt_id = cvt_idx;
1146 if (mux_id)
1147 *mux_id = mux_idx;
1148
1149 return 0;
1150}
1151
1152static void haswell_config_cvts(struct hda_codec *codec,
1153 int pin_id, int mux_id)
1154{
1155 struct hdmi_spec *spec = codec->spec;
1156 struct hdmi_spec_per_pin *per_pin;
1157 int pin_idx, mux_idx;
1158 int curr;
1159 int err;
1160
1161 for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
1162 per_pin = get_pin(spec, pin_idx);
1163
1164 if (pin_idx == pin_id)
1165 continue;
1166
1167 curr = snd_hda_codec_read(codec, per_pin->pin_nid, 0,
1168 AC_VERB_GET_CONNECT_SEL, 0);
1169
1170 /* Choose another unused converter */
1171 if (curr == mux_id) {
1172 err = hdmi_choose_cvt(codec, pin_idx, NULL, &mux_idx);
1173 if (err < 0)
1174 return;
1175 snd_printdd("HDMI: choose converter %d for pin %d\n", mux_idx, pin_idx);
1176 snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,
1177 AC_VERB_SET_CONNECT_SEL,
1178 mux_idx);
1179 }
1180 }
1181}
1182
1183/*
1184 * HDA PCM callbacks
1185 */
1186static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
1187 struct hda_codec *codec,
1188 struct snd_pcm_substream *substream)
1189{
1190 struct hdmi_spec *spec = codec->spec;
1191 struct snd_pcm_runtime *runtime = substream->runtime;
1192 int pin_idx, cvt_idx, mux_idx = 0;
1193 struct hdmi_spec_per_pin *per_pin;
1194 struct hdmi_eld *eld;
1195 struct hdmi_spec_per_cvt *per_cvt = NULL;
1196 int err;
1197
1198 /* Validate hinfo */
1199 pin_idx = hinfo_to_pin_index(spec, hinfo);
1200 if (snd_BUG_ON(pin_idx < 0))
1201 return -EINVAL;
1202 per_pin = get_pin(spec, pin_idx);
1203 eld = &per_pin->sink_eld;
1204
1205 err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, &mux_idx);
1206 if (err < 0)
1207 return err;
1208
1209 per_cvt = get_cvt(spec, cvt_idx);
1154 /* Claim converter */ 1210 /* Claim converter */
1155 per_cvt->assigned = 1; 1211 per_cvt->assigned = 1;
1156 hinfo->nid = per_cvt->cvt_nid; 1212 hinfo->nid = per_cvt->cvt_nid;
@@ -1158,6 +1214,11 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
1158 snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0, 1214 snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0,
1159 AC_VERB_SET_CONNECT_SEL, 1215 AC_VERB_SET_CONNECT_SEL,
1160 mux_idx); 1216 mux_idx);
1217
1218 /* configure unused pins to choose other converters */
1219 if (codec->vendor_id == 0x80862807)
1220 haswell_config_cvts(codec, pin_idx, mux_idx);
1221
1161 snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid); 1222 snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid);
1162 1223
1163 /* Initially set the converter's capabilities */ 1224 /* Initially set the converter's capabilities */