diff options
author | Takashi Iwai <tiwai@suse.de> | 2016-03-21 07:56:46 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2016-03-28 03:38:40 -0400 |
commit | 4846a67eb5a1d7cac76e1b22f66e88a8cbbdff3f (patch) | |
tree | f3bf49c5505ad27b375f13595dfc46271e0f0e66 /sound/pci/hda/patch_hdmi.c | |
parent | 2c1c9b86c6b22dc0cbac3f4ca2c8272c472dc463 (diff) |
ALSA: hda - Introduce pin_cvt_fixup() ops to hdmi parser
For reducing the splat of is_haswell_plus() or such macros, this patch
introduces pin_cvt_fixup() ops to hdmi_spec. For HSW+ and VLV+
codecs, set this ops so that the driver can call the Intel-specific
workarounds appropriately.
A gratis bonus that we can remove the mux_id argument from
hdmi_choose_cvt(), too, since the fixup function always refers the
mux_idx from the given per_pin object.
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.c | 82 |
1 files changed, 50 insertions, 32 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 985518891b99..3481b43476dc 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -114,6 +114,9 @@ struct hdmi_ops { | |||
114 | int (*setup_stream)(struct hda_codec *codec, hda_nid_t cvt_nid, | 114 | int (*setup_stream)(struct hda_codec *codec, hda_nid_t cvt_nid, |
115 | hda_nid_t pin_nid, u32 stream_tag, int format); | 115 | hda_nid_t pin_nid, u32 stream_tag, int format); |
116 | 116 | ||
117 | void (*pin_cvt_fixup)(struct hda_codec *codec, | ||
118 | struct hdmi_spec_per_pin *per_pin, | ||
119 | hda_nid_t cvt_nid); | ||
117 | }; | 120 | }; |
118 | 121 | ||
119 | struct hdmi_pcm { | 122 | struct hdmi_pcm { |
@@ -881,7 +884,7 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, | |||
881 | * of the pin. | 884 | * of the pin. |
882 | */ | 885 | */ |
883 | static int hdmi_choose_cvt(struct hda_codec *codec, | 886 | static int hdmi_choose_cvt(struct hda_codec *codec, |
884 | int pin_idx, int *cvt_id, int *mux_id) | 887 | int pin_idx, int *cvt_id) |
885 | { | 888 | { |
886 | struct hdmi_spec *spec = codec->spec; | 889 | struct hdmi_spec *spec = codec->spec; |
887 | struct hdmi_spec_per_pin *per_pin; | 890 | struct hdmi_spec_per_pin *per_pin; |
@@ -922,8 +925,6 @@ static int hdmi_choose_cvt(struct hda_codec *codec, | |||
922 | 925 | ||
923 | if (cvt_id) | 926 | if (cvt_id) |
924 | *cvt_id = cvt_idx; | 927 | *cvt_id = cvt_idx; |
925 | if (mux_id) | ||
926 | *mux_id = mux_idx; | ||
927 | 928 | ||
928 | return 0; | 929 | return 0; |
929 | } | 930 | } |
@@ -1016,9 +1017,6 @@ static void intel_not_share_assigned_cvt_nid(struct hda_codec *codec, | |||
1016 | int mux_idx; | 1017 | int mux_idx; |
1017 | struct hdmi_spec *spec = codec->spec; | 1018 | struct hdmi_spec *spec = codec->spec; |
1018 | 1019 | ||
1019 | if (!is_haswell_plus(codec) && !is_valleyview_plus(codec)) | ||
1020 | return; | ||
1021 | |||
1022 | /* On Intel platform, the mapping of converter nid to | 1020 | /* On Intel platform, the mapping of converter nid to |
1023 | * mux index of the pins are always the same. | 1021 | * mux index of the pins are always the same. |
1024 | * The pin nid may be 0, this means all pins will not | 1022 | * The pin nid may be 0, this means all pins will not |
@@ -1029,6 +1027,17 @@ static void intel_not_share_assigned_cvt_nid(struct hda_codec *codec, | |||
1029 | intel_not_share_assigned_cvt(codec, pin_nid, mux_idx); | 1027 | intel_not_share_assigned_cvt(codec, pin_nid, mux_idx); |
1030 | } | 1028 | } |
1031 | 1029 | ||
1030 | /* skeleton caller of pin_cvt_fixup ops */ | ||
1031 | static void pin_cvt_fixup(struct hda_codec *codec, | ||
1032 | struct hdmi_spec_per_pin *per_pin, | ||
1033 | hda_nid_t cvt_nid) | ||
1034 | { | ||
1035 | struct hdmi_spec *spec = codec->spec; | ||
1036 | |||
1037 | if (spec->ops.pin_cvt_fixup) | ||
1038 | spec->ops.pin_cvt_fixup(codec, per_pin, cvt_nid); | ||
1039 | } | ||
1040 | |||
1032 | /* called in hdmi_pcm_open when no pin is assigned to the PCM | 1041 | /* called in hdmi_pcm_open when no pin is assigned to the PCM |
1033 | * in dyn_pcm_assign mode. | 1042 | * in dyn_pcm_assign mode. |
1034 | */ | 1043 | */ |
@@ -1046,7 +1055,7 @@ static int hdmi_pcm_open_no_pin(struct hda_pcm_stream *hinfo, | |||
1046 | if (pcm_idx < 0) | 1055 | if (pcm_idx < 0) |
1047 | return -EINVAL; | 1056 | return -EINVAL; |
1048 | 1057 | ||
1049 | err = hdmi_choose_cvt(codec, -1, &cvt_idx, NULL); | 1058 | err = hdmi_choose_cvt(codec, -1, &cvt_idx); |
1050 | if (err) | 1059 | if (err) |
1051 | return err; | 1060 | return err; |
1052 | 1061 | ||
@@ -1054,7 +1063,7 @@ static int hdmi_pcm_open_no_pin(struct hda_pcm_stream *hinfo, | |||
1054 | per_cvt->assigned = 1; | 1063 | per_cvt->assigned = 1; |
1055 | hinfo->nid = per_cvt->cvt_nid; | 1064 | hinfo->nid = per_cvt->cvt_nid; |
1056 | 1065 | ||
1057 | intel_not_share_assigned_cvt_nid(codec, 0, per_cvt->cvt_nid); | 1066 | pin_cvt_fixup(codec, NULL, per_cvt->cvt_nid); |
1058 | 1067 | ||
1059 | set_bit(pcm_idx, &spec->pcm_in_use); | 1068 | set_bit(pcm_idx, &spec->pcm_in_use); |
1060 | /* todo: setup spdif ctls assign */ | 1069 | /* todo: setup spdif ctls assign */ |
@@ -1086,7 +1095,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, | |||
1086 | { | 1095 | { |
1087 | struct hdmi_spec *spec = codec->spec; | 1096 | struct hdmi_spec *spec = codec->spec; |
1088 | struct snd_pcm_runtime *runtime = substream->runtime; | 1097 | struct snd_pcm_runtime *runtime = substream->runtime; |
1089 | int pin_idx, cvt_idx, pcm_idx, mux_idx = 0; | 1098 | int pin_idx, cvt_idx, pcm_idx; |
1090 | struct hdmi_spec_per_pin *per_pin; | 1099 | struct hdmi_spec_per_pin *per_pin; |
1091 | struct hdmi_eld *eld; | 1100 | struct hdmi_eld *eld; |
1092 | struct hdmi_spec_per_cvt *per_cvt = NULL; | 1101 | struct hdmi_spec_per_cvt *per_cvt = NULL; |
@@ -1115,7 +1124,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, | |||
1115 | } | 1124 | } |
1116 | } | 1125 | } |
1117 | 1126 | ||
1118 | err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, &mux_idx); | 1127 | err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx); |
1119 | if (err < 0) { | 1128 | if (err < 0) { |
1120 | mutex_unlock(&spec->pcm_lock); | 1129 | mutex_unlock(&spec->pcm_lock); |
1121 | return err; | 1130 | return err; |
@@ -1132,11 +1141,10 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, | |||
1132 | 1141 | ||
1133 | snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0, | 1142 | snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0, |
1134 | AC_VERB_SET_CONNECT_SEL, | 1143 | AC_VERB_SET_CONNECT_SEL, |
1135 | mux_idx); | 1144 | per_pin->mux_idx); |
1136 | 1145 | ||
1137 | /* configure unused pins to choose other converters */ | 1146 | /* configure unused pins to choose other converters */ |
1138 | if (is_haswell_plus(codec) || is_valleyview_plus(codec)) | 1147 | pin_cvt_fixup(codec, per_pin, 0); |
1139 | intel_not_share_assigned_cvt(codec, per_pin->pin_nid, mux_idx); | ||
1140 | 1148 | ||
1141 | snd_hda_spdif_ctls_assign(codec, pcm_idx, per_cvt->cvt_nid); | 1149 | snd_hda_spdif_ctls_assign(codec, pcm_idx, per_cvt->cvt_nid); |
1142 | 1150 | ||
@@ -1369,12 +1377,7 @@ static void update_eld(struct hda_codec *codec, | |||
1369 | * and this can make HW reset converter selection on a pin. | 1377 | * and this can make HW reset converter selection on a pin. |
1370 | */ | 1378 | */ |
1371 | if (eld->eld_valid && !old_eld_valid && per_pin->setup) { | 1379 | if (eld->eld_valid && !old_eld_valid && per_pin->setup) { |
1372 | if (is_haswell_plus(codec) || is_valleyview_plus(codec)) { | 1380 | pin_cvt_fixup(codec, per_pin, 0); |
1373 | intel_verify_pin_cvt_connect(codec, per_pin); | ||
1374 | intel_not_share_assigned_cvt(codec, per_pin->pin_nid, | ||
1375 | per_pin->mux_idx); | ||
1376 | } | ||
1377 | |||
1378 | hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm); | 1381 | hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm); |
1379 | } | 1382 | } |
1380 | 1383 | ||
@@ -1709,7 +1712,7 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
1709 | * skip pin setup and return 0 to make audio playback | 1712 | * skip pin setup and return 0 to make audio playback |
1710 | * be ongoing | 1713 | * be ongoing |
1711 | */ | 1714 | */ |
1712 | intel_not_share_assigned_cvt_nid(codec, 0, cvt_nid); | 1715 | pin_cvt_fixup(codec, NULL, cvt_nid); |
1713 | snd_hda_codec_setup_stream(codec, cvt_nid, | 1716 | snd_hda_codec_setup_stream(codec, cvt_nid, |
1714 | stream_tag, 0, format); | 1717 | stream_tag, 0, format); |
1715 | mutex_unlock(&spec->pcm_lock); | 1718 | mutex_unlock(&spec->pcm_lock); |
@@ -1722,18 +1725,16 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
1722 | } | 1725 | } |
1723 | per_pin = get_pin(spec, pin_idx); | 1726 | per_pin = get_pin(spec, pin_idx); |
1724 | pin_nid = per_pin->pin_nid; | 1727 | pin_nid = per_pin->pin_nid; |
1725 | if (is_haswell_plus(codec) || is_valleyview_plus(codec)) { | 1728 | |
1726 | /* Verify pin:cvt selections to avoid silent audio after S3. | 1729 | /* Verify pin:cvt selections to avoid silent audio after S3. |
1727 | * After S3, the audio driver restores pin:cvt selections | 1730 | * After S3, the audio driver restores pin:cvt selections |
1728 | * but this can happen before gfx is ready and such selection | 1731 | * but this can happen before gfx is ready and such selection |
1729 | * is overlooked by HW. Thus multiple pins can share a same | 1732 | * is overlooked by HW. Thus multiple pins can share a same |
1730 | * default convertor and mute control will affect each other, | 1733 | * default convertor and mute control will affect each other, |
1731 | * which can cause a resumed audio playback become silent | 1734 | * which can cause a resumed audio playback become silent |
1732 | * after S3. | 1735 | * after S3. |
1733 | */ | 1736 | */ |
1734 | intel_verify_pin_cvt_connect(codec, per_pin); | 1737 | pin_cvt_fixup(codec, per_pin, 0); |
1735 | intel_not_share_assigned_cvt(codec, pin_nid, per_pin->mux_idx); | ||
1736 | } | ||
1737 | 1738 | ||
1738 | /* Call sync_audio_rate to set the N/CTS/M manually if necessary */ | 1739 | /* Call sync_audio_rate to set the N/CTS/M manually if necessary */ |
1739 | /* Todo: add DP1.2 MST audio support later */ | 1740 | /* Todo: add DP1.2 MST audio support later */ |
@@ -2312,6 +2313,20 @@ static int i915_hsw_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, | |||
2312 | return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); | 2313 | return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); |
2313 | } | 2314 | } |
2314 | 2315 | ||
2316 | /* pin_cvt_fixup ops override for HSW+ and VLV+ */ | ||
2317 | static void i915_pin_cvt_fixup(struct hda_codec *codec, | ||
2318 | struct hdmi_spec_per_pin *per_pin, | ||
2319 | hda_nid_t cvt_nid) | ||
2320 | { | ||
2321 | if (per_pin) { | ||
2322 | intel_verify_pin_cvt_connect(codec, per_pin); | ||
2323 | intel_not_share_assigned_cvt(codec, per_pin->pin_nid, | ||
2324 | per_pin->mux_idx); | ||
2325 | } else { | ||
2326 | intel_not_share_assigned_cvt_nid(codec, 0, cvt_nid); | ||
2327 | } | ||
2328 | } | ||
2329 | |||
2315 | /* Intel Haswell and onwards; audio component with eld notifier */ | 2330 | /* Intel Haswell and onwards; audio component with eld notifier */ |
2316 | static int patch_i915_hsw_hdmi(struct hda_codec *codec) | 2331 | static int patch_i915_hsw_hdmi(struct hda_codec *codec) |
2317 | { | 2332 | { |
@@ -2344,6 +2359,7 @@ static int patch_i915_hsw_hdmi(struct hda_codec *codec) | |||
2344 | codec->auto_runtime_pm = 1; | 2359 | codec->auto_runtime_pm = 1; |
2345 | 2360 | ||
2346 | spec->ops.setup_stream = i915_hsw_setup_stream; | 2361 | spec->ops.setup_stream = i915_hsw_setup_stream; |
2362 | spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup; | ||
2347 | 2363 | ||
2348 | err = hdmi_parse_codec(codec); | 2364 | err = hdmi_parse_codec(codec); |
2349 | if (err < 0) { | 2365 | if (err < 0) { |
@@ -2381,6 +2397,8 @@ static int patch_i915_byt_hdmi(struct hda_codec *codec) | |||
2381 | codec->depop_delay = 0; | 2397 | codec->depop_delay = 0; |
2382 | codec->auto_runtime_pm = 1; | 2398 | codec->auto_runtime_pm = 1; |
2383 | 2399 | ||
2400 | spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup; | ||
2401 | |||
2384 | err = hdmi_parse_codec(codec); | 2402 | err = hdmi_parse_codec(codec); |
2385 | if (err < 0) { | 2403 | if (err < 0) { |
2386 | generic_spec_free(codec); | 2404 | generic_spec_free(codec); |