@@ -4717,6 +4717,10 @@ static const struct dbuf_slice_conf_entry dg2_allowed_dbufs[] = {
4717
4717
};
4718
4718
4719
4719
static const struct dbuf_slice_conf_entry adlp_allowed_dbufs [] = {
4720
+ /*
4721
+ * Keep the join_mbus cases first so check_mbus_joined()
4722
+ * will prefer them over the !join_mbus cases.
4723
+ */
4720
4724
{
4721
4725
.active_pipes = BIT (PIPE_A ),
4722
4726
.dbuf_mask = {
@@ -4731,6 +4735,20 @@ static const struct dbuf_slice_conf_entry adlp_allowed_dbufs[] = {
4731
4735
},
4732
4736
.join_mbus = true,
4733
4737
},
4738
+ {
4739
+ .active_pipes = BIT (PIPE_A ),
4740
+ .dbuf_mask = {
4741
+ [PIPE_A ] = BIT (DBUF_S1 ) | BIT (DBUF_S2 ),
4742
+ },
4743
+ .join_mbus = false,
4744
+ },
4745
+ {
4746
+ .active_pipes = BIT (PIPE_B ),
4747
+ .dbuf_mask = {
4748
+ [PIPE_B ] = BIT (DBUF_S3 ) | BIT (DBUF_S4 ),
4749
+ },
4750
+ .join_mbus = false,
4751
+ },
4734
4752
{
4735
4753
.active_pipes = BIT (PIPE_A ) | BIT (PIPE_B ),
4736
4754
.dbuf_mask = {
@@ -4847,13 +4865,14 @@ static bool adlp_check_mbus_joined(u8 active_pipes)
4847
4865
return check_mbus_joined (active_pipes , adlp_allowed_dbufs );
4848
4866
}
4849
4867
4850
- static u8 compute_dbuf_slices (enum pipe pipe , u8 active_pipes ,
4868
+ static u8 compute_dbuf_slices (enum pipe pipe , u8 active_pipes , bool join_mbus ,
4851
4869
const struct dbuf_slice_conf_entry * dbuf_slices )
4852
4870
{
4853
4871
int i ;
4854
4872
4855
4873
for (i = 0 ; i < dbuf_slices [i ].active_pipes ; i ++ ) {
4856
- if (dbuf_slices [i ].active_pipes == active_pipes )
4874
+ if (dbuf_slices [i ].active_pipes == active_pipes &&
4875
+ dbuf_slices [i ].join_mbus == join_mbus )
4857
4876
return dbuf_slices [i ].dbuf_mask [pipe ];
4858
4877
}
4859
4878
return 0 ;
@@ -4864,7 +4883,7 @@ static u8 compute_dbuf_slices(enum pipe pipe, u8 active_pipes,
4864
4883
* returns correspondent DBuf slice mask as stated in BSpec for particular
4865
4884
* platform.
4866
4885
*/
4867
- static u8 icl_compute_dbuf_slices (enum pipe pipe , u8 active_pipes )
4886
+ static u8 icl_compute_dbuf_slices (enum pipe pipe , u8 active_pipes , bool join_mbus )
4868
4887
{
4869
4888
/*
4870
4889
* FIXME: For ICL this is still a bit unclear as prev BSpec revision
@@ -4878,37 +4897,41 @@ static u8 icl_compute_dbuf_slices(enum pipe pipe, u8 active_pipes)
4878
4897
* still here - we will need it once those additional constraints
4879
4898
* pop up.
4880
4899
*/
4881
- return compute_dbuf_slices (pipe , active_pipes , icl_allowed_dbufs );
4900
+ return compute_dbuf_slices (pipe , active_pipes , join_mbus ,
4901
+ icl_allowed_dbufs );
4882
4902
}
4883
4903
4884
- static u8 tgl_compute_dbuf_slices (enum pipe pipe , u8 active_pipes )
4904
+ static u8 tgl_compute_dbuf_slices (enum pipe pipe , u8 active_pipes , bool join_mbus )
4885
4905
{
4886
- return compute_dbuf_slices (pipe , active_pipes , tgl_allowed_dbufs );
4906
+ return compute_dbuf_slices (pipe , active_pipes , join_mbus ,
4907
+ tgl_allowed_dbufs );
4887
4908
}
4888
4909
4889
- static u32 adlp_compute_dbuf_slices (enum pipe pipe , u32 active_pipes )
4910
+ static u8 adlp_compute_dbuf_slices (enum pipe pipe , u8 active_pipes , bool join_mbus )
4890
4911
{
4891
- return compute_dbuf_slices (pipe , active_pipes , adlp_allowed_dbufs );
4912
+ return compute_dbuf_slices (pipe , active_pipes , join_mbus ,
4913
+ adlp_allowed_dbufs );
4892
4914
}
4893
4915
4894
- static u32 dg2_compute_dbuf_slices (enum pipe pipe , u32 active_pipes )
4916
+ static u8 dg2_compute_dbuf_slices (enum pipe pipe , u8 active_pipes , bool join_mbus )
4895
4917
{
4896
- return compute_dbuf_slices (pipe , active_pipes , dg2_allowed_dbufs );
4918
+ return compute_dbuf_slices (pipe , active_pipes , join_mbus ,
4919
+ dg2_allowed_dbufs );
4897
4920
}
4898
4921
4899
- static u8 skl_compute_dbuf_slices (struct intel_crtc * crtc , u8 active_pipes )
4922
+ static u8 skl_compute_dbuf_slices (struct intel_crtc * crtc , u8 active_pipes , bool join_mbus )
4900
4923
{
4901
4924
struct drm_i915_private * dev_priv = to_i915 (crtc -> base .dev );
4902
4925
enum pipe pipe = crtc -> pipe ;
4903
4926
4904
4927
if (IS_DG2 (dev_priv ))
4905
- return dg2_compute_dbuf_slices (pipe , active_pipes );
4928
+ return dg2_compute_dbuf_slices (pipe , active_pipes , join_mbus );
4906
4929
else if (IS_ALDERLAKE_P (dev_priv ))
4907
- return adlp_compute_dbuf_slices (pipe , active_pipes );
4930
+ return adlp_compute_dbuf_slices (pipe , active_pipes , join_mbus );
4908
4931
else if (DISPLAY_VER (dev_priv ) == 12 )
4909
- return tgl_compute_dbuf_slices (pipe , active_pipes );
4932
+ return tgl_compute_dbuf_slices (pipe , active_pipes , join_mbus );
4910
4933
else if (DISPLAY_VER (dev_priv ) == 11 )
4911
- return icl_compute_dbuf_slices (pipe , active_pipes );
4934
+ return icl_compute_dbuf_slices (pipe , active_pipes , join_mbus );
4912
4935
/*
4913
4936
* For anything else just return one slice yet.
4914
4937
* Should be extended for other platforms.
@@ -6127,11 +6150,16 @@ skl_compute_ddb(struct intel_atomic_state *state)
6127
6150
return ret ;
6128
6151
}
6129
6152
6153
+ if (IS_ALDERLAKE_P (dev_priv ))
6154
+ new_dbuf_state -> joined_mbus =
6155
+ adlp_check_mbus_joined (new_dbuf_state -> active_pipes );
6156
+
6130
6157
for_each_intel_crtc (& dev_priv -> drm , crtc ) {
6131
6158
enum pipe pipe = crtc -> pipe ;
6132
6159
6133
6160
new_dbuf_state -> slices [pipe ] =
6134
- skl_compute_dbuf_slices (crtc , new_dbuf_state -> active_pipes );
6161
+ skl_compute_dbuf_slices (crtc , new_dbuf_state -> active_pipes ,
6162
+ new_dbuf_state -> joined_mbus );
6135
6163
6136
6164
if (old_dbuf_state -> slices [pipe ] == new_dbuf_state -> slices [pipe ])
6137
6165
continue ;
@@ -6143,9 +6171,6 @@ skl_compute_ddb(struct intel_atomic_state *state)
6143
6171
6144
6172
new_dbuf_state -> enabled_slices = intel_dbuf_enabled_slices (new_dbuf_state );
6145
6173
6146
- if (IS_ALDERLAKE_P (dev_priv ))
6147
- new_dbuf_state -> joined_mbus = adlp_check_mbus_joined (new_dbuf_state -> active_pipes );
6148
-
6149
6174
if (old_dbuf_state -> enabled_slices != new_dbuf_state -> enabled_slices ||
6150
6175
old_dbuf_state -> joined_mbus != new_dbuf_state -> joined_mbus ) {
6151
6176
ret = intel_atomic_serialize_global_state (& new_dbuf_state -> base );
@@ -6626,6 +6651,7 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
6626
6651
enum pipe pipe = crtc -> pipe ;
6627
6652
unsigned int mbus_offset ;
6628
6653
enum plane_id plane_id ;
6654
+ u8 slices ;
6629
6655
6630
6656
skl_pipe_wm_get_hw_state (crtc , & crtc_state -> wm .skl .optimal );
6631
6657
crtc_state -> wm .skl .raw = crtc_state -> wm .skl .optimal ;
@@ -6645,19 +6671,22 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
6645
6671
skl_ddb_entry_union (& dbuf_state -> ddb [pipe ], ddb_uv );
6646
6672
}
6647
6673
6648
- dbuf_state -> slices [pipe ] =
6649
- skl_compute_dbuf_slices (crtc , dbuf_state -> active_pipes );
6650
-
6651
6674
dbuf_state -> weight [pipe ] = intel_crtc_ddb_weight (crtc_state );
6652
6675
6653
6676
/*
6654
6677
* Used for checking overlaps, so we need absolute
6655
6678
* offsets instead of MBUS relative offsets.
6656
6679
*/
6657
- mbus_offset = mbus_ddb_offset (dev_priv , dbuf_state -> slices [pipe ]);
6680
+ slices = skl_compute_dbuf_slices (crtc , dbuf_state -> active_pipes ,
6681
+ dbuf_state -> joined_mbus );
6682
+ mbus_offset = mbus_ddb_offset (dev_priv , slices );
6658
6683
crtc_state -> wm .skl .ddb .start = mbus_offset + dbuf_state -> ddb [pipe ].start ;
6659
6684
crtc_state -> wm .skl .ddb .end = mbus_offset + dbuf_state -> ddb [pipe ].end ;
6660
6685
6686
+ /* The slices actually used by the planes on the pipe */
6687
+ dbuf_state -> slices [pipe ] =
6688
+ skl_ddb_dbuf_slice_mask (dev_priv , & crtc_state -> wm .skl .ddb );
6689
+
6661
6690
drm_dbg_kms (& dev_priv -> drm ,
6662
6691
"[CRTC:%d:%s] dbuf slices 0x%x, ddb (%d - %d), active pipes 0x%x, mbus joined: %s\n" ,
6663
6692
crtc -> base .base .id , crtc -> base .name ,
@@ -6669,6 +6698,74 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv)
6669
6698
dbuf_state -> enabled_slices = dev_priv -> dbuf .enabled_slices ;
6670
6699
}
6671
6700
6701
+ static bool skl_dbuf_is_misconfigured (struct drm_i915_private * i915 )
6702
+ {
6703
+ const struct intel_dbuf_state * dbuf_state =
6704
+ to_intel_dbuf_state (i915 -> dbuf .obj .state );
6705
+ struct skl_ddb_entry entries [I915_MAX_PIPES ] = {};
6706
+ struct intel_crtc * crtc ;
6707
+
6708
+ for_each_intel_crtc (& i915 -> drm , crtc ) {
6709
+ const struct intel_crtc_state * crtc_state =
6710
+ to_intel_crtc_state (crtc -> base .state );
6711
+
6712
+ entries [crtc -> pipe ] = crtc_state -> wm .skl .ddb ;
6713
+ }
6714
+
6715
+ for_each_intel_crtc (& i915 -> drm , crtc ) {
6716
+ const struct intel_crtc_state * crtc_state =
6717
+ to_intel_crtc_state (crtc -> base .state );
6718
+ u8 slices ;
6719
+
6720
+ slices = skl_compute_dbuf_slices (crtc , dbuf_state -> active_pipes ,
6721
+ dbuf_state -> joined_mbus );
6722
+ if (dbuf_state -> slices [crtc -> pipe ] & ~slices )
6723
+ return true;
6724
+
6725
+ if (skl_ddb_allocation_overlaps (& crtc_state -> wm .skl .ddb , entries ,
6726
+ I915_MAX_PIPES , crtc -> pipe ))
6727
+ return true;
6728
+ }
6729
+
6730
+ return false;
6731
+ }
6732
+
6733
+ void skl_wm_sanitize (struct drm_i915_private * i915 )
6734
+ {
6735
+ struct intel_crtc * crtc ;
6736
+
6737
+ /*
6738
+ * On TGL/RKL (at least) the BIOS likes to assign the planes
6739
+ * to the wrong DBUF slices. This will cause an infinite loop
6740
+ * in skl_commit_modeset_enables() as it can't find a way to
6741
+ * transition between the old bogus DBUF layout to the new
6742
+ * proper DBUF layout without DBUF allocation overlaps between
6743
+ * the planes (which cannot be allowed or else the hardware
6744
+ * may hang). If we detect a bogus DBUF layout just turn off
6745
+ * all the planes so that skl_commit_modeset_enables() can
6746
+ * simply ignore them.
6747
+ */
6748
+ if (!skl_dbuf_is_misconfigured (i915 ))
6749
+ return ;
6750
+
6751
+ drm_dbg_kms (& i915 -> drm , "BIOS has misprogrammed the DBUF, disabling all planes\n" );
6752
+
6753
+ for_each_intel_crtc (& i915 -> drm , crtc ) {
6754
+ struct intel_plane * plane = to_intel_plane (crtc -> base .primary );
6755
+ const struct intel_plane_state * plane_state =
6756
+ to_intel_plane_state (plane -> base .state );
6757
+ struct intel_crtc_state * crtc_state =
6758
+ to_intel_crtc_state (crtc -> base .state );
6759
+
6760
+ if (plane_state -> uapi .visible )
6761
+ intel_plane_disable_noatomic (crtc , plane );
6762
+
6763
+ drm_WARN_ON (& i915 -> drm , crtc_state -> active_planes != 0 );
6764
+
6765
+ memset (& crtc_state -> wm .skl .ddb , 0 , sizeof (crtc_state -> wm .skl .ddb ));
6766
+ }
6767
+ }
6768
+
6672
6769
static void ilk_pipe_wm_get_hw_state (struct intel_crtc * crtc )
6673
6770
{
6674
6771
struct drm_device * dev = crtc -> base .dev ;
0 commit comments