diff options
author | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2024-06-25 16:58:52 +0300 |
---|---|---|
committer | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2024-08-29 14:53:48 +0300 |
commit | 81a1c37c8b52eff636e77a794d0f0620c3a40af0 (patch) | |
tree | 3b8580a4a9205c43dce8a21f12a000af9dc4b7f0 /drivers/gpu/drm/i915/display/intel_dsb.c | |
parent | 33eca84db6e31091cef63584158ab64704f78462 (diff) | |
download | linux-81a1c37c8b52eff636e77a794d0f0620c3a40af0.tar.xz |
drm/i915/dsb: Hook up DSB error interrupts
Enable all DSB error/fault interrupts so that we can see if
anything goes terribly wrong.
v2: Pass intel_display to DISPLAY_VER() (Jani)
Drop extra '/' from drm_err() for consistency
v3: Reorder the irq handler a bit
Cc: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240625135852.13431-1-ville.syrjala@linux.intel.com
Reviewed-by: Animesh Manna <animesh.manna@intel.com>
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_dsb.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_dsb.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c index 2ab3765f6c06..3453989728aa 100644 --- a/drivers/gpu/drm/i915/display/intel_dsb.c +++ b/drivers/gpu/drm/i915/display/intel_dsb.c @@ -339,6 +339,40 @@ static u32 dsb_chicken(struct intel_crtc *crtc) return DSB_SKIP_WAITS_EN; } +static u32 dsb_error_int_status(struct intel_display *display) +{ + u32 errors; + + errors = DSB_GTT_FAULT_INT_STATUS | + DSB_RSPTIMEOUT_INT_STATUS | + DSB_POLL_ERR_INT_STATUS; + + /* + * All the non-existing status bits operate as + * normal r/w bits, so any attempt to clear them + * will just end up setting them. Never do that so + * we won't mistake them for actual error interrupts. + */ + if (DISPLAY_VER(display) >= 14) + errors |= DSB_ATS_FAULT_INT_STATUS; + + return errors; +} + +static u32 dsb_error_int_en(struct intel_display *display) +{ + u32 errors; + + errors = DSB_GTT_FAULT_INT_EN | + DSB_RSPTIMEOUT_INT_EN | + DSB_POLL_ERR_INT_EN; + + if (DISPLAY_VER(display) >= 14) + errors |= DSB_ATS_FAULT_INT_EN; + + return errors; +} + static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl, int dewake_scanline) { @@ -363,6 +397,10 @@ static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl, intel_de_write_fw(display, DSB_CHICKEN(pipe, dsb->id), dsb_chicken(crtc)); + intel_de_write_fw(display, DSB_INTERRUPT(pipe, dsb->id), + dsb_error_int_status(display) | DSB_PROG_INT_STATUS | + dsb_error_int_en(display)); + intel_de_write_fw(display, DSB_HEAD(pipe, dsb->id), intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf)); @@ -430,6 +468,9 @@ void intel_dsb_wait(struct intel_dsb *dsb) dsb->free_pos = 0; dsb->ins_start_offset = 0; intel_de_write_fw(display, DSB_CTRL(pipe, dsb->id), 0); + + intel_de_write_fw(display, DSB_INTERRUPT(pipe, dsb->id), + dsb_error_int_status(display) | DSB_PROG_INT_STATUS); } /** @@ -513,3 +554,18 @@ void intel_dsb_cleanup(struct intel_dsb *dsb) intel_dsb_buffer_cleanup(&dsb->dsb_buf); kfree(dsb); } + +void intel_dsb_irq_handler(struct intel_display *display, + enum pipe pipe, enum intel_dsb_id dsb_id) +{ + struct intel_crtc *crtc = intel_crtc_for_pipe(to_i915(display->drm), pipe); + u32 tmp, errors; + + tmp = intel_de_read_fw(display, DSB_INTERRUPT(pipe, dsb_id)); + intel_de_write_fw(display, DSB_INTERRUPT(pipe, dsb_id), tmp); + + errors = tmp & dsb_error_int_status(display); + if (errors) + drm_err(display->drm, "[CRTC:%d:%s] DSB %d error interrupt: 0x%x\n", + crtc->base.base.id, crtc->base.name, dsb_id, errors); +} |