aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/pci/hda/patch_hdmi.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index b83b14fa1d29..22b50899b151 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -67,6 +67,8 @@ struct hdmi_spec_per_pin {
67 struct delayed_work work; 67 struct delayed_work work;
68 struct snd_kcontrol *eld_ctl; 68 struct snd_kcontrol *eld_ctl;
69 int repoll_count; 69 int repoll_count;
70 bool setup; /* the stream has been set up by prepare callback */
71 int channels; /* current number of channels */
70 bool non_pcm; 72 bool non_pcm;
71 bool chmap_set; /* channel-map override by ALSA API? */ 73 bool chmap_set; /* channel-map override by ALSA API? */
72 unsigned char chmap[8]; /* ALSA API channel-map */ 74 unsigned char chmap[8]; /* ALSA API channel-map */
@@ -879,18 +881,19 @@ static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
879 return true; 881 return true;
880} 882}
881 883
882static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, 884static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
883 bool non_pcm, 885 struct hdmi_spec_per_pin *per_pin,
884 struct snd_pcm_substream *substream) 886 bool non_pcm)
885{ 887{
886 struct hdmi_spec *spec = codec->spec;
887 struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
888 hda_nid_t pin_nid = per_pin->pin_nid; 888 hda_nid_t pin_nid = per_pin->pin_nid;
889 int channels = substream->runtime->channels; 889 int channels = per_pin->channels;
890 struct hdmi_eld *eld; 890 struct hdmi_eld *eld;
891 int ca; 891 int ca;
892 union audio_infoframe ai; 892 union audio_infoframe ai;
893 893
894 if (!channels)
895 return;
896
894 eld = &per_pin->sink_eld; 897 eld = &per_pin->sink_eld;
895 if (!eld->monitor_present) 898 if (!eld->monitor_present)
896 return; 899 return;
@@ -1341,6 +1344,7 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
1341 eld_changed = true; 1344 eld_changed = true;
1342 } 1345 }
1343 if (update_eld) { 1346 if (update_eld) {
1347 bool old_eld_valid = pin_eld->eld_valid;
1344 pin_eld->eld_valid = eld->eld_valid; 1348 pin_eld->eld_valid = eld->eld_valid;
1345 eld_changed = pin_eld->eld_size != eld->eld_size || 1349 eld_changed = pin_eld->eld_size != eld->eld_size ||
1346 memcmp(pin_eld->eld_buffer, eld->eld_buffer, 1350 memcmp(pin_eld->eld_buffer, eld->eld_buffer,
@@ -1350,6 +1354,18 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
1350 eld->eld_size); 1354 eld->eld_size);
1351 pin_eld->eld_size = eld->eld_size; 1355 pin_eld->eld_size = eld->eld_size;
1352 pin_eld->info = eld->info; 1356 pin_eld->info = eld->info;
1357
1358 /* Haswell-specific workaround: re-setup when the transcoder is
1359 * changed during the stream playback
1360 */
1361 if (codec->vendor_id == 0x80862807 &&
1362 eld->eld_valid && !old_eld_valid && per_pin->setup) {
1363 snd_hda_codec_write(codec, pin_nid, 0,
1364 AC_VERB_SET_AMP_GAIN_MUTE,
1365 AMP_OUT_UNMUTE);
1366 hdmi_setup_audio_infoframe(codec, per_pin,
1367 per_pin->non_pcm);
1368 }
1353 } 1369 }
1354 mutex_unlock(&pin_eld->lock); 1370 mutex_unlock(&pin_eld->lock);
1355 1371
@@ -1522,14 +1538,17 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
1522 hda_nid_t cvt_nid = hinfo->nid; 1538 hda_nid_t cvt_nid = hinfo->nid;
1523 struct hdmi_spec *spec = codec->spec; 1539 struct hdmi_spec *spec = codec->spec;
1524 int pin_idx = hinfo_to_pin_index(spec, hinfo); 1540 int pin_idx = hinfo_to_pin_index(spec, hinfo);
1525 hda_nid_t pin_nid = get_pin(spec, pin_idx)->pin_nid; 1541 struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
1542 hda_nid_t pin_nid = per_pin->pin_nid;
1526 bool non_pcm; 1543 bool non_pcm;
1527 1544
1528 non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); 1545 non_pcm = check_non_pcm_per_cvt(codec, cvt_nid);
1546 per_pin->channels = substream->runtime->channels;
1547 per_pin->setup = true;
1529 1548
1530 hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels); 1549 hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels);
1531 1550
1532 hdmi_setup_audio_infoframe(codec, pin_idx, non_pcm, substream); 1551 hdmi_setup_audio_infoframe(codec, per_pin, non_pcm);
1533 1552
1534 return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); 1553 return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format);
1535} 1554}
@@ -1569,6 +1588,9 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
1569 snd_hda_spdif_ctls_unassign(codec, pin_idx); 1588 snd_hda_spdif_ctls_unassign(codec, pin_idx);
1570 per_pin->chmap_set = false; 1589 per_pin->chmap_set = false;
1571 memset(per_pin->chmap, 0, sizeof(per_pin->chmap)); 1590 memset(per_pin->chmap, 0, sizeof(per_pin->chmap));
1591
1592 per_pin->setup = false;
1593 per_pin->channels = 0;
1572 } 1594 }
1573 1595
1574 return 0; 1596 return 0;
@@ -1704,8 +1726,7 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol,
1704 per_pin->chmap_set = true; 1726 per_pin->chmap_set = true;
1705 memcpy(per_pin->chmap, chmap, sizeof(chmap)); 1727 memcpy(per_pin->chmap, chmap, sizeof(chmap));
1706 if (prepared) 1728 if (prepared)
1707 hdmi_setup_audio_infoframe(codec, pin_idx, per_pin->non_pcm, 1729 hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm);
1708 substream);
1709 1730
1710 return 0; 1731 return 0;
1711} 1732}