From: Ville Syrjälä Date: Thu, 12 Jun 2025 14:50:17 +0000 (+0300) Subject: drm/i915/dsb: Move the DSB_PMCTRL* reset out of intel_dsb_finish() X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7c50c6a8173137519c84574bd348abe6703989be;p=thirdparty%2Fkernel%2Flinux.git drm/i915/dsb: Move the DSB_PMCTRL* reset out of intel_dsb_finish() When using the flip queue, due to the DMC vs. DSB register corruption problem, we must not issue any register writes from the DSB after unhalting the DMC. Currently we are doing just that by trying to restore DSB_PMCTRL* back to a sane state from intel_dsb_finish(). Since the only place left that pokes at DSB_PMCTRL* is intel_dsb_chain() we can just do DSB_PMCTRL_2/DSB_FORCE_DEWAKE reset in the same place. The DSB_PMCTRL reset is trickier since we'd have to do it from the chained DSB itself. But based on my earlier testing DSB_PMCTRL/DSB_ENABLE_DEWAKE doesn't actually do anything if the DSB isn't actually enabled, so we can omit the reset to keep things a bit simpler. We do need to reset DSB_PMCTRL/DSB_ENABLE_DEWAKE before tarting the DSB however, in case it was left enabled from a previous use. Reviewed-by: Uma Shankar Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20250612145018.8735-6-ville.syrjala@linux.intel.com --- diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 2f7bd8da1bf17..aaa2a4a52edcf 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -628,18 +628,6 @@ void intel_dsb_gosub_finish(struct intel_dsb *dsb) void intel_dsb_finish(struct intel_dsb *dsb) { - struct intel_crtc *crtc = dsb->crtc; - - /* - * DSB_FORCE_DEWAKE remains active even after DSB is - * disabled, so make sure to clear it (if set during - * intel_dsb_commit()). And clear DSB_ENABLE_DEWAKE as - * well for good measure. - */ - intel_dsb_reg_write(dsb, DSB_PMCTRL(crtc->pipe, dsb->id), 0); - intel_dsb_reg_write_masked(dsb, DSB_PMCTRL_2(crtc->pipe, dsb->id), - DSB_FORCE_DEWAKE, 0); - intel_dsb_align_tail(dsb); intel_dsb_buffer_flush_map(&dsb->dsb_buf); @@ -780,6 +768,8 @@ static void _intel_dsb_chain(struct intel_atomic_state *state, intel_dsb_reg_write(dsb, DSB_PMCTRL(pipe, chained_dsb->id), DSB_ENABLE_DEWAKE | DSB_SCANLINE_FOR_DEWAKE(hw_dewake_scanline)); + } else { + intel_dsb_reg_write(dsb, DSB_PMCTRL(pipe, chained_dsb->id), 0); } intel_dsb_reg_write(dsb, DSB_HEAD(pipe, chained_dsb->id), @@ -801,6 +791,13 @@ static void _intel_dsb_chain(struct intel_atomic_state *state, intel_dsb_wait_scanline_out(state, dsb, dsb_dewake_scanline_start(state, crtc), dsb_dewake_scanline_end(state, crtc)); + + /* + * DSB_FORCE_DEWAKE remains active even after DSB is + * disabled, so make sure to clear it. + */ + intel_dsb_reg_write_masked(dsb, DSB_PMCTRL_2(crtc->pipe, dsb->id), + DSB_FORCE_DEWAKE, 0); } } @@ -856,6 +853,8 @@ void intel_dsb_commit(struct intel_dsb *dsb) dsb_error_int_status(display) | DSB_PROG_INT_STATUS | dsb_error_int_en(display) | DSB_PROG_INT_EN); + intel_de_write_fw(display, DSB_PMCTRL(pipe, dsb->id), 0); + intel_de_write_fw(display, DSB_HEAD(pipe, dsb->id), intel_dsb_head(dsb));