Refactor the initial plane configuration and atomic commit path to
ensure a seamless transition from the bootloader to the driver,
specifically targeting Panther Lake (PTL) platforms.

Key changes include:

1.  **Robust Initial Plane Readout**: Rewrote
    `skl_get_initial_plane_config` to correctly identify tiling
    modifiers (including CCS/MC variants) instead of relying on
    fallbacks. This ensures the framebuffer is created with the
    correct format layout and rotation.

2.  **Hardened Atomic Handover**: Added checks for
    `old_crtc_state->inherited` in `intel_pre_plane_update`,
    `intel_pre_update_crtc`, and `intel_old_crtc_state_disables`.
    This prevents the driver from prematurely disabling the pipe,
    updating watermarks, or touching FBC during the initial takeover,
    preserving the boot image.

3.  **Removal of Hardcoded Hacks**: Removed temporary workarounds,
    including hardcoded MSO stride (0x8d), link rate overrides
    (216000), and forced sync flags. The driver now relies on correct
    hardware readout and state persistence.

4.  **Splash Screen Preservation**: Disabled the framebuffer clear loop
    in `xe_plane_initial.c` to prevent overwriting the BIOS splash
    screen during initialization.

Signed-off-by: Juasheem Sultan <[email protected]>
---
 drivers/gpu/drm/i915/display/intel_display.c       | 195 +++++++++------------
 .../gpu/drm/i915/display/intel_display_driver.c    |  35 +---
 drivers/gpu/drm/i915/display/intel_dp.c            |  15 --
 drivers/gpu/drm/i915/display/skl_universal_plane.c | 147 +++++++++-------
 drivers/gpu/drm/xe/display/xe_plane_initial.c      |   4 +-
 5 files changed, 167 insertions(+), 229 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 
e0020f6e21bc95f57348d5733bac8542a00f672d..5ba82abb7e33b2f62d595bd425a1f7a9c9c23270
 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -1301,7 +1301,7 @@ static void intel_pre_plane_update(struct 
intel_atomic_state *state,
                 * us to.
                 */
                if (!intel_initial_watermarks(state, crtc))
-                       if (new_crtc_state->update_wm_pre)
+                       if (new_crtc_state->update_wm_pre && 
!old_crtc_state->inherited)
                                intel_update_watermarks(display);
        }
 
@@ -2967,7 +2967,7 @@ static void intel_get_pipe_src_size(struct intel_crtc 
*crtc,
                      REG_FIELD_GET(PIPESRC_WIDTH_MASK, tmp) + 1,
                      REG_FIELD_GET(PIPESRC_HEIGHT_MASK, tmp) + 1);
 
-       /* [FB-FIX] Force pipe source size from boot state if HW readout is 
invalid (seamless handoff) */
+       /* Force pipe source size from boot state if HW readout is invalid 
(seamless handoff) */
        if (boot_state_captured && crtc->pipe == boot_pipe &&
            (drm_rect_width(&pipe_config->pipe_src) <= 1 || 
drm_rect_height(&pipe_config->pipe_src) <= 1)) {
                drm_rect_init(&pipe_config->pipe_src, 0, 0, boot_hdisplay, 
boot_vdisplay);
@@ -7149,7 +7149,8 @@ static void intel_pre_update_crtc(struct 
intel_atomic_state *state,
                    intel_crtc_needs_color_update(new_crtc_state))
                        intel_color_load_luts(new_crtc_state);
 
-               intel_pre_plane_update(state, crtc);
+               if (!old_crtc_state->inherited)
+                       intel_pre_plane_update(state, crtc);
 
                if (intel_crtc_needs_fastset(new_crtc_state))
                        intel_encoders_update_pipe(state, crtc);
@@ -7163,7 +7164,8 @@ static void intel_pre_update_crtc(struct 
intel_atomic_state *state,
                        intel_vrr_set_transcoder_timings(new_crtc_state);
        }
 
-       intel_fbc_update(state, crtc);
+       if (!old_crtc_state->inherited)
+               intel_fbc_update(state, crtc);
 
        drm_WARN_ON(display->drm, !intel_display_power_is_enabled(display, 
POWER_DOMAIN_DC_OFF));
 
@@ -7275,24 +7277,17 @@ static void intel_update_crtc(struct intel_atomic_state 
*state,
 }
 
 static void intel_old_crtc_state_disables(struct intel_atomic_state *state,
-                                         struct intel_crtc *crtc)
-{
-       struct intel_display *display = to_intel_display(state);
-       const struct intel_crtc_state *old_crtc_state =
-               intel_atomic_get_old_crtc_state(state, crtc);
-       const struct intel_crtc_state *new_crtc_state =
-               intel_atomic_get_new_crtc_state(state, crtc);
-       struct intel_crtc *pipe_crtc;
-
-       if (old_crtc_state->inherited && new_crtc_state->uapi.active) {
-               return;
-       }
-
-       /*
-        * We need to disable pipe CRC before disabling the pipe,
-        * or we race against vblank off.
-        */
-       for_each_intel_crtc_in_pipe_mask(display->drm, pipe_crtc,
+                                                               struct 
intel_crtc *crtc)
+                                         {
+                                               struct intel_display *display = 
to_intel_display(state);
+                                               const struct intel_crtc_state 
*old_crtc_state =
+                                                       
intel_atomic_get_old_crtc_state(state, crtc);
+                                               struct intel_crtc *pipe_crtc;
+                                         
+                                               /*
+                                                * We need to disable pipe CRC 
before disabling the pipe,
+                                                * or we race against vblank 
off.
+                                                */     
for_each_intel_crtc_in_pipe_mask(display->drm, pipe_crtc,
                                         
intel_crtc_joined_pipe_mask(old_crtc_state))
                intel_crtc_disable_pipe_crc(pipe_crtc);
 
@@ -8649,8 +8644,8 @@ void intel_crtc_steal_state(struct intel_crtc_state 
*crtc_state)
 
        /* FIX: Also populate pipe_src so pfit doesn't complain */
        drm_rect_init(&live_crtc_state->pipe_src, 0, 0,
-                     crtc_state->hw.adjusted_mode.crtc_hdisplay,
-                     crtc_state->hw.adjusted_mode.crtc_vdisplay);
+                       crtc_state->hw.adjusted_mode.crtc_hdisplay,
+                       crtc_state->hw.adjusted_mode.crtc_vdisplay);
 
        /* Capture boot state for persistence */
        if (!boot_state_captured && (crtc_state->hw.active || 
crtc_state->hw.adjusted_mode.crtc_clock > 0)) {
@@ -8673,7 +8668,7 @@ void intel_crtc_steal_state(struct intel_crtc_state 
*crtc_state)
                boot_csc_mode = crtc_state->csc_mode;
                boot_linetime = crtc_state->linetime;
 
-               /* [FB-FIX] Capture Watermark and DDB state */
+               /* Capture Watermark and DDB state */
                if (DISPLAY_VER(display) >= 9) {
                        memcpy(&boot_wm, &crtc_state->wm.skl.optimal, 
sizeof(boot_wm));
                        memcpy(&boot_ddb, &crtc_state->wm.skl.plane_ddb, 
sizeof(boot_ddb));
@@ -8700,53 +8695,45 @@ void intel_crtc_steal_state(struct intel_crtc_state 
*crtc_state)
                boot_state_captured = true;
        }
 
-               if (live_crtc_state->hw.active) {
-                       /*
-                        * This is filling in the uapi.mode and creating the 
blob for it.
-                        * The blob is required for the initial commit to 
succeed.
-                        */
-                       memset(&live_crtc_state->uapi.mode, 0, 
sizeof(live_crtc_state->uapi.mode));
-
-                       struct drm_mode_modeinfo umode;
-                       struct drm_property_blob *blob;
-
-                       /* Manually create the mode blob to avoid triggering a 
modeset */
-                       memset(&umode, 0, sizeof(umode));
-                       umode.clock = crtc_state->hw.adjusted_mode.clock;
-                       umode.hdisplay = crtc_state->hw.adjusted_mode.hdisplay;
-                       umode.hsync_start = 
crtc_state->hw.adjusted_mode.hsync_start;
-                       umode.hsync_end = 
crtc_state->hw.adjusted_mode.hsync_end;
-                       umode.htotal = crtc_state->hw.adjusted_mode.htotal;
-                       umode.hskew = crtc_state->hw.adjusted_mode.hskew;
-                       umode.vdisplay = crtc_state->hw.adjusted_mode.vdisplay;
-                       umode.vsync_start = 
crtc_state->hw.adjusted_mode.vsync_start;
-                       umode.vsync_end = 
crtc_state->hw.adjusted_mode.vsync_end;
-                       umode.vtotal = crtc_state->hw.adjusted_mode.vtotal;
-
-                       /* [FB-FIX] Ensure vtotal is populated to prevent 
scanline divide-by-zero */
-                       if (umode.vtotal == 0) {
-                               umode.vtotal = 
crtc_state->hw.adjusted_mode.crtc_vtotal;
-                       }
-                       if (umode.vtotal == 0) {
-                               umode.vtotal = 1504; /* Fallback for MSO panel 
*/
-                       }
-
-                       umode.vscan = crtc_state->hw.adjusted_mode.vscan;
-                       umode.vrefresh = 
drm_mode_vrefresh(&crtc_state->hw.adjusted_mode);
-                       umode.flags = crtc_state->hw.adjusted_mode.flags;
-                       umode.type = crtc_state->hw.adjusted_mode.type;
-                       strncpy(umode.name, crtc_state->hw.adjusted_mode.name, 
DRM_DISPLAY_MODE_LEN);
-
-                       blob = drm_property_create_blob(display->drm, 
sizeof(umode), &umode);
-                       if (IS_ERR(blob)) {
-                       } else {
-                               /* This is the key: replace the blob without 
marking mode_changed */
-                               
drm_property_replace_blob(&live_crtc_state->uapi.mode_blob, blob);
-                               drm_property_blob_put(blob);
-                               drm_mode_copy(&live_crtc_state->uapi.mode, 
&crtc_state->hw.adjusted_mode);
-                               live_crtc_state->uapi.enable = true;
-                       }
-               }               /* Mark the primary plane as visible in the 
live state */
+       if (live_crtc_state->hw.active) {
+               /*
+                * This is filling in the uapi.mode and creating the blob for 
it.
+                * The blob is required for the initial commit to succeed.
+                */
+               memset(&live_crtc_state->uapi.mode, 0, 
sizeof(live_crtc_state->uapi.mode));
+
+               struct drm_mode_modeinfo umode;
+               struct drm_property_blob *blob;
+
+               /* Manually create the mode blob to avoid triggering a modeset 
*/
+               memset(&umode, 0, sizeof(umode));
+               umode.clock = crtc_state->hw.adjusted_mode.clock;
+               umode.hdisplay = crtc_state->hw.adjusted_mode.hdisplay;
+               umode.hsync_start = crtc_state->hw.adjusted_mode.hsync_start;
+               umode.hsync_end = crtc_state->hw.adjusted_mode.hsync_end;
+               umode.htotal = crtc_state->hw.adjusted_mode.htotal;
+               umode.hskew = crtc_state->hw.adjusted_mode.hskew;
+               umode.vdisplay = crtc_state->hw.adjusted_mode.vdisplay;
+               umode.vsync_start = crtc_state->hw.adjusted_mode.vsync_start;
+               umode.vsync_end = crtc_state->hw.adjusted_mode.vsync_end;
+               umode.vtotal = crtc_state->hw.adjusted_mode.vtotal;
+
+               umode.vscan = crtc_state->hw.adjusted_mode.vscan;
+               umode.vrefresh = 
drm_mode_vrefresh(&crtc_state->hw.adjusted_mode);
+               umode.flags = crtc_state->hw.adjusted_mode.flags;
+               umode.type = crtc_state->hw.adjusted_mode.type;
+               strncpy(umode.name, crtc_state->hw.adjusted_mode.name, 
DRM_DISPLAY_MODE_LEN);
+
+               blob = drm_property_create_blob(display->drm, sizeof(umode), 
&umode);
+               if (IS_ERR(blob)) {
+               } else {
+                       /* This is the key: replace the blob without marking 
mode_changed */
+                       
drm_property_replace_blob(&live_crtc_state->uapi.mode_blob, blob);
+                       drm_property_blob_put(blob);
+                       drm_mode_copy(&live_crtc_state->uapi.mode, 
&crtc_state->hw.adjusted_mode);
+                       live_crtc_state->uapi.enable = true;
+               }
+               /* Mark the primary plane as visible in the live state */
                live_plane_state->uapi.visible = true;
                live_crtc_state->uapi.plane_mask |= 
drm_plane_mask(&primary->base);
 
@@ -8789,10 +8776,12 @@ void intel_crtc_steal_state(struct intel_crtc_state 
*crtc_state)
                                drm_encoder_mask(&encoder->base);
 
                        connector->base.status = connector_status_connected;
-                       } else {
-                           drm_warn(display->drm, "[XE-STEAL] No active 
connector found for pipe %c!\n",
-                                pipe_name(crtc->pipe));
-                       }}
+               } else {
+                       drm_warn(display->drm, "[XE-STEAL] No active connector 
found for pipe %c!\n",
+                                       pipe_name(crtc->pipe));
+               }
+       }
+}
 #ifdef CONFIG_DRM_I915
 EXPORT_SYMBOL_GPL(intel_crtc_steal_state);
 #endif
@@ -8840,37 +8829,21 @@ int intel_initial_commit(struct intel_display *display)
                        crtc_state->hw.enable = true; /* Force hw.enable to 
match uapi.enable */
                        crtc_state->inherited = true;
 
-                                   crtc_state->pixel_rate =
-
-                                       
to_intel_crtc_state(crtc->base.state)->uapi.adjusted_mode.crtc_clock;
-
-
-
-                                   /* Find and link the connector for this 
CRTC */
-
-                                   for_each_intel_encoder(display->drm, 
encoder) {
-
-                                       if (crtc_state->uapi.encoder_mask & 
drm_encoder_mask(&encoder->base)) {
-
-                                                       break;
-
-                                       }
+                       crtc_state->pixel_rate =
+                               
to_intel_crtc_state(crtc->base.state)->uapi.adjusted_mode.crtc_clock;
 
-                                       }
-
-
-
-                                       if (encoder) {
-
-                                       
drm_connector_list_iter_begin(display->drm, &conn_iter);
-
-                                       drm_for_each_connector_iter(iter_conn, 
&conn_iter) {
-
-                                                       if 
(to_intel_connector(iter_conn)->encoder == encoder) {
+                       /* Find and link the connector for this CRTC */
+                       for_each_intel_encoder(display->drm, encoder) {
+                               if (crtc_state->uapi.encoder_mask & 
drm_encoder_mask(&encoder->base)) {
+                                       break;
+                               }
+                       }
 
+                       if (encoder) {
+                               drm_connector_list_iter_begin(display->drm, 
&conn_iter);
+                               drm_for_each_connector_iter(iter_conn, 
&conn_iter) {
+                                       if 
(to_intel_connector(iter_conn)->encoder == encoder) {
                                                connector = 
to_intel_connector(iter_conn);
-
-
                                                break;
                                        }
                                }
@@ -8881,7 +8854,7 @@ int intel_initial_commit(struct intel_display *display)
                                struct drm_connector_state *conn_state;
 
                                conn_state = 
drm_atomic_get_connector_state(state,
-                                                                       
&connector->base);
+                                               &connector->base);
                                if (IS_ERR(conn_state)) {
                                        ret = PTR_ERR(conn_state);
                                        goto out;
@@ -8900,7 +8873,7 @@ int intel_initial_commit(struct intel_display *display)
                                        crtc_state->uapi.encoder_mask |= 
drm_encoder_mask(&connector->encoder->base);
                        } else {
                                drm_warn(dev, "[FB-COMMIT] No connector found 
for CRTC %s\n",
-                                        crtc->base.name);
+                                               crtc->base.name);
                        }
 
                        ret = drm_atomic_add_affected_planes(state, 
&crtc->base);
@@ -8916,11 +8889,11 @@ int intel_initial_commit(struct intel_display *display)
                        crtc_state->uapi.color_mgmt_changed = true;
 
                        for_each_intel_encoder_mask(display->drm, encoder,
-                                                   
crtc_state->uapi.encoder_mask) {
+                                       crtc_state->uapi.encoder_mask) {
                                if (encoder->initial_fastset_check &&
-                                   !encoder->initial_fastset_check(encoder, 
crtc_state)) {
+                                               
!encoder->initial_fastset_check(encoder, crtc_state)) {
                                        ret = 
drm_atomic_add_affected_connectors(state,
-                                                                               
 &crtc->base);
+                                                       &crtc->base);
                                        if (ret)
                                                goto out;
                                }
@@ -8938,11 +8911,9 @@ int intel_initial_commit(struct intel_display *display)
                goto retry;
        }
 
+       initial_boot_handoff = false;
        if (ret) {
                drm_atomic_state_put(state);
-               initial_boot_handoff = false;
-       } else {
-               initial_boot_handoff = false;
        }
 out_no_state:
        drm_modeset_drop_locks(&ctx);
diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c 
b/drivers/gpu/drm/i915/display/intel_display_driver.c
index 
73de39f655d9bb4435c21ac67d19d1bb7ace759d..5f3ae482d24a57a9268c2739c745912e8edab2db
 100644
--- a/drivers/gpu/drm/i915/display/intel_display_driver.c
+++ b/drivers/gpu/drm/i915/display/intel_display_driver.c
@@ -542,40 +542,7 @@ int intel_display_driver_probe_nogem(struct intel_display 
*display)
                                 */
                                encoder->get_config(encoder, crtc_state);
 
-                               /*
-                                * HACK: MSO Fixup for readout (Fastboot path).
-                                * If we read out the split MSO mode (1128), 
scale it up to the
-                                * logical mode (2256) so it matches the 
VBT/User mode.
-                                */
-                               if (crtc_state->hw.pipe_mode.hdisplay == 1128) {
-
-                                       /* Scale ALL horizontal timings to 
prevent invalid mode (Sync < Active) */
-                                       crtc_state->hw.pipe_mode.hdisplay *= 2;
-                                       crtc_state->hw.pipe_mode.hsync_start *= 
2;
-                                       crtc_state->hw.pipe_mode.hsync_end *= 2;
-                                       crtc_state->hw.pipe_mode.htotal *= 2;
-
-                                       crtc_state->hw.pipe_mode.crtc_hdisplay 
*= 2;
-                                       
crtc_state->hw.pipe_mode.crtc_hsync_start *= 2;
-                                       crtc_state->hw.pipe_mode.crtc_hsync_end 
*= 2;
-                                       crtc_state->hw.pipe_mode.crtc_htotal *= 
2;
-                                       
crtc_state->hw.pipe_mode.crtc_hblank_start *= 2;
-                                       
crtc_state->hw.pipe_mode.crtc_hblank_end *= 2;
-
-                                       /* Fix name */
-                                       snprintf(crtc_state->hw.pipe_mode.name, 
DRM_DISPLAY_MODE_LEN, "%dx%d",
-                                                       
crtc_state->hw.pipe_mode.hdisplay, crtc_state->hw.pipe_mode.vdisplay);
-                               } else if (crtc_state->hw.pipe_mode.hdisplay == 
2256 &&
-                                               
crtc_state->hw.pipe_mode.crtc_hsync_start == 1152) {
-
-                                       /* Geometry is already scaled, but 
Sync/Blank are raw. Fix them. */
-                                       crtc_state->hw.pipe_mode.hsync_start *= 
2;
-                                       crtc_state->hw.pipe_mode.hsync_end *= 2;
-                                       
crtc_state->hw.pipe_mode.crtc_hsync_start *= 2;
-                                       crtc_state->hw.pipe_mode.crtc_hsync_end 
*= 2;
-                                       
crtc_state->hw.pipe_mode.crtc_hblank_start *= 2;
-                                       
crtc_state->hw.pipe_mode.crtc_hblank_end *= 2;
-                               }
+
                                /* Link the encoder to the CRTC */
                                encoder->base.crtc = &crtc->base;
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 
f73a7f9d2198b418cea06cc3c1636f09bb681dee..4d7a6f98efa2489ecbea24d8eda22f7fb4ff0ffb
 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -3276,12 +3276,6 @@ intel_dp_compute_config(struct intel_encoder *encoder,
        if (ret)
                return ret;
 
-       /* [FB-FIX] Force 216000 link rate for MSO. Found 216000 in HW. 
Override compute result. */
-       if (pipe_config->hw.pipe_mode.hdisplay == 2256) {
-               pipe_config->lane_count = 4;
-               pipe_config->port_clock = 216000;
-       }
-
        if ((intel_dp_is_edp(intel_dp) && fixed_mode) ||
            pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420) {
                ret = intel_pfit_compute_config(pipe_config, conn_state);
@@ -3314,15 +3308,6 @@ intel_dp_compute_config(struct intel_encoder *encoder,
                pipe_config->splitter.link_count = n;
                pipe_config->splitter.pixel_overlap = overlap;
 
-               /*
-                * [FB-FIX] Force Positive Sync for MSO panels.
-                * If we fell through here (skipped restore_boot), we must 
ensure flags are correct.
-                */
-               if ((adjusted_mode->flags & (DRM_MODE_FLAG_PHSYNC | 
DRM_MODE_FLAG_NHSYNC |
-                                            DRM_MODE_FLAG_PVSYNC | 
DRM_MODE_FLAG_NVSYNC)) == 0) {
-                       adjusted_mode->flags |= DRM_MODE_FLAG_PHSYNC | 
DRM_MODE_FLAG_PVSYNC;
-               }
-
                adjusted_mode->crtc_hdisplay = adjusted_mode->crtc_hdisplay / n 
+ overlap;
                adjusted_mode->crtc_hblank_start = 
adjusted_mode->crtc_hblank_start / n + overlap;
                adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_hblank_end 
/ n + overlap;
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c 
b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index 
3db998edf8fe15e4bc07318c15c009688bf1fbbc..dfe670d81aba64207d5ea348c346125e9ab49398
 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -1540,11 +1540,6 @@ icl_plane_update_noarm(struct intel_dsb *dsb,
        int src_h = drm_rect_height(&plane_state->uapi.src) >> 16;
        u32 plane_color_ctl;
 
-       /* [] Hack: Force stride 0x8d for MSO 2256px to fix display artifacts */
-       if (fb->width == 2256 && crtc_state->inherited) {
-               stride = 0x8d;
-       }
-
        plane_color_ctl = plane_state->color_ctl |
                glk_plane_color_ctl_crtc(crtc_state);
 
@@ -1651,18 +1646,18 @@ icl_plane_update_arm(struct intel_dsb *dsb,
        icl_plane_update_sel_fetch_arm(dsb, plane, crtc_state, plane_state);
 
        /*
-        * The control register self-arms if the plane was previously
+        * Enable the plane.
+        *
+        * The hardware will ignore the plane enable bit if the plane
+        * is not armed (FRAME_START_DELAY not elapsed yet).
+        *
+        * However, on Gen11+ the plane enable bit is double buffered.
+        * If we write the control register with the enable bit set
+        * before the surface register, the plane will be enabled
+        * immediately (on the next vblank) even if the plane was
         * disabled. Try to make the plane enable atomic by writing
         * the control register just before the surface register.
         */
-       u32 hw_ctl = intel_de_read(display, PLANE_CTL(pipe, plane_id));
-
-       if (crtc_state->inherited) {
-               if (hw_ctl & 0x8) {
-                       plane_ctl |= 0x8;
-               }
-       }
-
        intel_de_write_dsb(display, dsb, PLANE_CTL(pipe, plane_id),
                           plane_ctl);
        intel_de_write_dsb(display, dsb, PLANE_SURF(pipe, plane_id),
@@ -3027,13 +3022,14 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
        enum plane_id plane_id = plane->id;
        enum pipe pipe;
        u32 val, offset, stride_mult, tiling, alpha;
-       u32 plane_ctl, plane_size, plane_stride;
        int fourcc, pixel_format;
        unsigned int aligned_height;
        struct drm_framebuffer *fb;
        struct intel_framebuffer *intel_fb;
+       static_assert(PLANE_CTL_TILED_YF == PLANE_CTL_TILED_4);
 
-       pipe = plane->pipe;
+       if (!plane->get_hw_state(plane, &pipe))
+               return;
 
        drm_WARN_ON(display->drm, pipe != crtc->pipe);
 
@@ -3044,44 +3040,34 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
                return;
        }
 
-       plane_ctl = intel_de_read(display, PLANE_CTL(plane->i9xx_plane, pipe));
-
-       if (!(plane_ctl & PLANE_CTL_ENABLE)) {
-               to_intel_crtc_state(crtc->base.state)->uapi.active = false;
+       intel_fb = intel_framebuffer_alloc();
+       if (!intel_fb) {
+               drm_dbg_kms(display->drm, "failed to alloc fb\n");
                return;
        }
 
-       plane_size = intel_de_read(display, PLANE_SIZE(plane->i9xx_plane, 
pipe));
-       plane_stride = intel_de_read(display, PLANE_STRIDE(plane->i9xx_plane, 
pipe));
+       fb = &intel_fb->base;
+
+       fb->dev = display->drm;
 
-       val = plane_ctl;
+       val = intel_de_read(display, PLANE_CTL(pipe, plane_id));
 
        if (DISPLAY_VER(display) >= 11)
                pixel_format = val & PLANE_CTL_FORMAT_MASK_ICL;
        else
-               pixel_format = REG_FIELD_GET(PLANE_CTL_FORMAT_MASK_SKL, val);
+               pixel_format = val & PLANE_CTL_FORMAT_MASK_SKL;
 
        if (DISPLAY_VER(display) >= 10) {
-               u32 plane_color_ctl =
-                       intel_de_read(display, PLANE_COLOR_CTL(pipe, plane_id));
-               alpha = REG_FIELD_GET(PLANE_COLOR_ALPHA_MASK, plane_color_ctl);
+               u32 color_ctl;
+
+               color_ctl = intel_de_read(display, PLANE_COLOR_CTL(pipe, 
plane_id));
+               alpha = REG_FIELD_GET(PLANE_COLOR_ALPHA_MASK, color_ctl);
        } else {
                alpha = REG_FIELD_GET(PLANE_CTL_ALPHA_MASK, val);
        }
 
        fourcc = skl_format_to_fourcc(pixel_format,
-                                             val & PLANE_CTL_ORDER_RGBX,
-                                             alpha !=PLANE_CTL_ALPHA_DISABLE);
-
-       intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
-       if (!intel_fb) {
-               drm_dbg_kms(display->drm, "failed to alloc fb\n");
-               return;
-       }
-       fb = &intel_fb->base;
-
-       fb->dev = display->drm;
-
+                                     val & PLANE_CTL_ORDER_RGBX, alpha);
        fb->format = drm_format_info(fourcc);
 
        tiling = val & PLANE_CTL_TILED_MASK;
@@ -3095,14 +3081,39 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
                break;
        case PLANE_CTL_TILED_Y:
                plane_config->tiling = I915_TILING_Y;
-               fb->modifier = I915_FORMAT_MOD_Y_TILED;
+               if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
+                       if (DISPLAY_VER(display) >= 14)
+                               fb->modifier = 
I915_FORMAT_MOD_4_TILED_MTL_RC_CCS;
+                       else if (DISPLAY_VER(display) >= 12)
+                               fb->modifier = 
I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS;
+                       else
+                               fb->modifier = I915_FORMAT_MOD_Y_TILED_CCS;
+               else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
+                       if (DISPLAY_VER(display) >= 14)
+                               fb->modifier = 
I915_FORMAT_MOD_4_TILED_MTL_MC_CCS;
+                       else
+                               fb->modifier = 
I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS;
+               else
+                       fb->modifier = I915_FORMAT_MOD_Y_TILED;
                break;
-       case PLANE_CTL_TILED_YF:
+       case PLANE_CTL_TILED_YF: /* aka PLANE_CTL_TILED_4 on XE_LPD+ */
                if (HAS_4TILE(display)) {
-                       fb->modifier = I915_FORMAT_MOD_4_TILED;
+                       u32 rc_mask = PLANE_CTL_RENDER_DECOMPRESSION_ENABLE |
+                                     PLANE_CTL_CLEAR_COLOR_DISABLE;
+
+                       if ((val & rc_mask) == rc_mask)
+                               fb->modifier = 
I915_FORMAT_MOD_4_TILED_DG2_RC_CCS;
+                       else if (val & PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE)
+                               fb->modifier = 
I915_FORMAT_MOD_4_TILED_DG2_MC_CCS;
+                       else if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
+                               fb->modifier = 
I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC;
+                       else
+                               fb->modifier = I915_FORMAT_MOD_4_TILED;
                } else {
-                       plane_config->tiling = I915_TILING_Y;
-                       fb->modifier = I915_FORMAT_MOD_Yf_TILED;
+                       if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE)
+                               fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS;
+                       else
+                               fb->modifier = I915_FORMAT_MOD_Yf_TILED;
                }
                break;
        default:
@@ -3134,48 +3145,52 @@ skl_get_initial_plane_config(struct intel_crtc *crtc,
                plane_config->rotation = DRM_MODE_ROTATE_90;
                break;
        }
-       
-       struct drm_mode_fb_cmd2 mode_cmd = { 0 };
-
-       fb->width = (REG_FIELD_GET(PLANE_WIDTH_MASK, plane_size) + 1);
-       fb->height = (REG_FIELD_GET(PLANE_HEIGHT_MASK, plane_size) + 1);
-       
-       mode_cmd.width = fb->width;
-       mode_cmd.height = fb->height;
-       mode_cmd.pixel_format = fourcc;
 
-       drm_helper_mode_fill_fb_struct(display->drm, fb,
-                                      drm_format_info(fourcc),
-                                      &mode_cmd);
-
-       if (fb->modifier == DRM_FORMAT_MOD_LINEAR)
-               stride_mult = 64;
-       else
-               stride_mult = intel_tile_width_bytes(fb, 0);
-       
-       fb->pitches[0] = REG_FIELD_GET(PLANE_STRIDE__MASK, plane_stride) * 
stride_mult;
+       if (DISPLAY_VER(display) >= 11 && val & PLANE_CTL_FLIP_HORIZONTAL)
+               plane_config->rotation |= DRM_MODE_REFLECT_X;
 
-       aligned_height = intel_fb_align_height(fb, 0, fb->height);
+       /* 90/270 degree rotation would require extra work */
+       if (drm_rotation_90_or_270(plane_config->rotation))
+               goto error;
 
        /*
         * HACK: The PLANE_SURF register is unreliable at this stage. Based on
         * i915 and coreboot behavior, the correct GTT offset is 0.
         */
+       u32 surf = intel_de_read(display, PLANE_SURF(pipe, plane_id));
+       drm_info(display->drm, "[FB-FIX] PLANE_SURF read: 0x%08x, Forcing base 
to 0\n", surf);
        plane_config->base = 0;
 
        offset = intel_de_read(display, PLANE_OFFSET(pipe, plane_id));
        drm_WARN_ON(display->drm, offset != 0);
 
+       val = intel_de_read(display, PLANE_SIZE(pipe, plane_id));
+       fb->height = REG_FIELD_GET(PLANE_HEIGHT_MASK, val) + 1;
+       fb->width = REG_FIELD_GET(PLANE_WIDTH_MASK, val) + 1;
+
+       val = intel_de_read(display, PLANE_STRIDE(pipe, plane_id));
+       stride_mult = skl_plane_stride_mult(fb, 0, DRM_MODE_ROTATE_0);
+
+       fb->pitches[0] = REG_FIELD_GET(PLANE_STRIDE__MASK, val) * stride_mult;
+
+       aligned_height = intel_fb_align_height(fb, 0, fb->height);
+
        plane_config->size = fb->pitches[0] * aligned_height;
-       plane_config->fb = intel_fb;
 
+       drm_dbg_kms(display->drm,
+                   "[CRTC:%d:%s][PLANE:%d:%s] with fb: size=%dx%d@%d, 
offset=%x, pitch %d, size 0x%x\n",
+                   crtc->base.base.id, crtc->base.name,
+                   plane->base.base.id, plane->base.name,
+                   fb->width, fb->height, fb->format->cpp[0] * 8,
+                   plane_config->base, fb->pitches[0], plane_config->size);
+
+       plane_config->fb = intel_fb;
        return;
 
 error:
        kfree(intel_fb);
        plane_config->fb = NULL;
 }
-
 bool skl_fixup_initial_plane_config(struct intel_crtc *crtc,
                                    const struct intel_initial_plane_config 
*plane_config)
 {
diff --git a/drivers/gpu/drm/xe/display/xe_plane_initial.c 
b/drivers/gpu/drm/xe/display/xe_plane_initial.c
index 
6a987224e90dc5620194a277ec5f52820da5efce..c7b1371d823bbfa71785df61e7aa601bf76d725e
 100644
--- a/drivers/gpu/drm/xe/display/xe_plane_initial.c
+++ b/drivers/gpu/drm/xe/display/xe_plane_initial.c
@@ -192,7 +192,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
        }
        /* Reference handed over to fb */
        xe_bo_put(bo);
-       if (bo->vmap.vaddr && plane_config->fb) {
+       /*if (bo->vmap.vaddr && plane_config->fb) {
                int x, y;
                void *vaddr = bo->vmap.vaddr;
                u32 height = plane_config->fb->base.height;
@@ -209,7 +209,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
                                row[x] = color;
                        }
                }
-       }
+       }*/
 
        return true;
 

-- 
2.52.0.457.g6b5491de43-goog

Reply via email to