@@ -114,6 +114,9 @@ struct hdmi_ops {
114
114
int (* setup_stream )(struct hda_codec * codec , hda_nid_t cvt_nid ,
115
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
122
struct hdmi_pcm {
@@ -881,7 +884,7 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid,
881
884
* of the pin.
882
885
*/
883
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
889
struct hdmi_spec * spec = codec -> spec ;
887
890
struct hdmi_spec_per_pin * per_pin ;
@@ -922,8 +925,6 @@ static int hdmi_choose_cvt(struct hda_codec *codec,
922
925
923
926
if (cvt_id )
924
927
* cvt_id = cvt_idx ;
925
- if (mux_id )
926
- * mux_id = mux_idx ;
927
928
928
929
return 0 ;
929
930
}
@@ -1016,9 +1017,6 @@ static void intel_not_share_assigned_cvt_nid(struct hda_codec *codec,
1016
1017
int mux_idx ;
1017
1018
struct hdmi_spec * spec = codec -> spec ;
1018
1019
1019
- if (!is_haswell_plus (codec ) && !is_valleyview_plus (codec ))
1020
- return ;
1021
-
1022
1020
/* On Intel platform, the mapping of converter nid to
1023
1021
* mux index of the pins are always the same.
1024
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
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
1041
/* called in hdmi_pcm_open when no pin is assigned to the PCM
1033
1042
* in dyn_pcm_assign mode.
1034
1043
*/
@@ -1046,15 +1055,15 @@ static int hdmi_pcm_open_no_pin(struct hda_pcm_stream *hinfo,
1046
1055
if (pcm_idx < 0 )
1047
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
1059
if (err )
1051
1060
return err ;
1052
1061
1053
1062
per_cvt = get_cvt (spec , cvt_idx );
1054
1063
per_cvt -> assigned = 1 ;
1055
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
1068
set_bit (pcm_idx , & spec -> pcm_in_use );
1060
1069
/* todo: setup spdif ctls assign */
@@ -1086,7 +1095,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
1086
1095
{
1087
1096
struct hdmi_spec * spec = codec -> spec ;
1088
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
1099
struct hdmi_spec_per_pin * per_pin ;
1091
1100
struct hdmi_eld * eld ;
1092
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
1128
if (err < 0 ) {
1120
1129
mutex_unlock (& spec -> pcm_lock );
1121
1130
return err ;
@@ -1132,11 +1141,10 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
1132
1141
1133
1142
snd_hda_codec_write_cache (codec , per_pin -> pin_nid , 0 ,
1134
1143
AC_VERB_SET_CONNECT_SEL ,
1135
- mux_idx );
1144
+ per_pin -> mux_idx );
1136
1145
1137
1146
/* configure unused pins to choose other converters */
1138
- if (is_haswell_plus (codec ) || is_valleyview_plus (codec ))
1139
- intel_not_share_assigned_cvt (codec , per_pin -> pin_nid , mux_idx );
1147
+ pin_cvt_fixup (codec , per_pin , 0 );
1140
1148
1141
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
1377
* and this can make HW reset converter selection on a pin.
1370
1378
*/
1371
1379
if (eld -> eld_valid && !old_eld_valid && per_pin -> setup ) {
1372
- if (is_haswell_plus (codec ) || is_valleyview_plus (codec )) {
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
-
1380
+ pin_cvt_fixup (codec , per_pin , 0 );
1378
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
1712
* skip pin setup and return 0 to make audio playback
1710
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
1716
snd_hda_codec_setup_stream (codec , cvt_nid ,
1714
1717
stream_tag , 0 , format );
1715
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
1726
per_pin = get_pin (spec , pin_idx );
1724
1727
pin_nid = per_pin -> pin_nid ;
1725
- if (is_haswell_plus (codec ) || is_valleyview_plus (codec )) {
1726
- /* Verify pin:cvt selections to avoid silent audio after S3.
1727
- * After S3, the audio driver restores pin:cvt selections
1728
- * but this can happen before gfx is ready and such selection
1729
- * is overlooked by HW. Thus multiple pins can share a same
1730
- * default convertor and mute control will affect each other,
1731
- * which can cause a resumed audio playback become silent
1732
- * after S3.
1733
- */
1734
- intel_verify_pin_cvt_connect (codec , per_pin );
1735
- intel_not_share_assigned_cvt (codec , pin_nid , per_pin -> mux_idx );
1736
- }
1728
+
1729
+ /* Verify pin:cvt selections to avoid silent audio after S3.
1730
+ * After S3, the audio driver restores pin:cvt selections
1731
+ * but this can happen before gfx is ready and such selection
1732
+ * is overlooked by HW. Thus multiple pins can share a same
1733
+ * default convertor and mute control will affect each other,
1734
+ * which can cause a resumed audio playback become silent
1735
+ * after S3.
1736
+ */
1737
+ pin_cvt_fixup (codec , per_pin , 0 );
1737
1738
1738
1739
/* Call sync_audio_rate to set the N/CTS/M manually if necessary */
1739
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
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
2330
/* Intel Haswell and onwards; audio component with eld notifier */
2316
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
2359
codec -> auto_runtime_pm = 1 ;
2345
2360
2346
2361
spec -> ops .setup_stream = i915_hsw_setup_stream ;
2362
+ spec -> ops .pin_cvt_fixup = i915_pin_cvt_fixup ;
2347
2363
2348
2364
err = hdmi_parse_codec (codec );
2349
2365
if (err < 0 ) {
@@ -2381,6 +2397,8 @@ static int patch_i915_byt_hdmi(struct hda_codec *codec)
2381
2397
codec -> depop_delay = 0 ;
2382
2398
codec -> auto_runtime_pm = 1 ;
2383
2399
2400
+ spec -> ops .pin_cvt_fixup = i915_pin_cvt_fixup ;
2401
+
2384
2402
err = hdmi_parse_codec (codec );
2385
2403
if (err < 0 ) {
2386
2404
generic_spec_free (codec );
0 commit comments