From 73373271a79872de96f24bcab99ee5ff5c00dbba Mon Sep 17 00:00:00 2001 From: Samantha Tran Date: Mon, 8 Feb 2021 21:33:40 -0800 Subject: [PATCH] disp: msm: sde: add multirect error status for ubwc and meta This change adds support for error checking ubwc and meta error status based off whether REC0 or RECT1 is used. Change-Id: I7c39755da99a9d6c0d02b4ef16fa93b8ec7458a9 Signed-off-by: Samantha Tran --- msm/sde/sde_crtc.c | 15 ++++---- msm/sde/sde_hw_catalog.c | 4 ++ msm/sde/sde_hw_catalog.h | 4 ++ msm/sde/sde_hw_sspp.c | 79 +++++++++++++++++++++++++++++++++++++--- msm/sde/sde_hw_sspp.h | 22 +++++++++-- msm/sde/sde_plane.c | 45 ++++++++++++++++++++++- msm/sde/sde_plane.h | 12 ++++++ 7 files changed, 163 insertions(+), 18 deletions(-) diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index 8166f8d296..1482a3bbff 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -2279,7 +2279,7 @@ static void sde_crtc_frame_event_cb(void *data, u32 event) struct sde_crtc_frame_event *fevent; struct sde_kms_frame_event_cb_data *cb_data; struct drm_plane *plane; - u32 ubwc_error; + u32 ubwc_error, meta_error; unsigned long flags; u32 crtc_id; @@ -2322,13 +2322,14 @@ static void sde_crtc_frame_event_cb(void *data, u32 event) drm_for_each_plane_mask(plane, crtc->dev, sde_crtc->plane_mask_old) { ubwc_error = sde_plane_get_ubwc_error(plane); - if (ubwc_error) { - SDE_EVT32(DRMID(crtc), DRMID(plane), - ubwc_error, SDE_EVTLOG_ERROR); - SDE_DEBUG("crtc%d plane %d ubwc_error %d\n", - DRMID(crtc), DRMID(plane), - ubwc_error); + meta_error = sde_plane_get_meta_error(plane); + if (ubwc_error | meta_error) { + SDE_EVT32(DRMID(crtc), DRMID(plane), ubwc_error, + meta_error, SDE_EVTLOG_ERROR); + SDE_DEBUG("crtc%d plane %d ubwc_error %d meta_error %d\n", + DRMID(crtc), DRMID(plane), ubwc_error, meta_error); sde_plane_clear_ubwc_error(plane); + sde_plane_clear_meta_error(plane); } } } diff --git a/msm/sde/sde_hw_catalog.c b/msm/sde/sde_hw_catalog.c index 9e8ed9ff62..51f666e1dd 100644 --- a/msm/sde/sde_hw_catalog.c +++ b/msm/sde/sde_hw_catalog.c @@ -1744,6 +1744,9 @@ static void sde_sspp_set_features(struct sde_mdss_cfg *sde_cfg, if (sde_cfg->sc_cfg[SDE_SYS_CACHE_DISP].has_sys_cache) set_bit(SDE_PERF_SSPP_SYS_CACHE, &sspp->perf_features); + if (sde_cfg->sspp_multirect_error) + set_bit(SDE_SSPP_MULTIRECT_ERROR, &sspp->features); + if (sde_cfg->has_decimation) { sblk->maxhdeciexp = MAX_HORZ_DECIMATION; sblk->maxvdeciexp = MAX_VERT_DECIMATION; @@ -4827,6 +4830,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev) sde_cfg->dither_luma_mode_support = true; sde_cfg->mdss_hw_block_size = 0x158; sde_cfg->syscache_supported = true; + sde_cfg->sspp_multirect_error = true; } else { SDE_ERROR("unsupported chipset id:%X\n", hw_rev); sde_cfg->perf.min_prefill_lines = 0xffff; diff --git a/msm/sde/sde_hw_catalog.h b/msm/sde/sde_hw_catalog.h index a22cb048f9..14c9bcfbac 100644 --- a/msm/sde/sde_hw_catalog.h +++ b/msm/sde/sde_hw_catalog.h @@ -252,6 +252,7 @@ enum { * @SDE_SSPP_BLOCK_SEC_UI Blocks secure-ui layers * @SDE_SSPP_SCALER_QSEED3LITE Qseed3lite algorithm support * @SDE_SSPP_TRUE_INLINE_ROT Support of SSPP true inline rotation v1 + * @SDE_SSPP_MULTIRECT_ERROR SSPP has error based on RECT0 or RECT1 * @SDE_SSPP_PREDOWNSCALE Support pre-downscale X-direction by 2 for inline * @SDE_SSPP_PREDOWNSCALE_Y Support pre-downscale Y-direction for inline * @SDE_SSPP_INLINE_CONST_CLR Inline rotation requires const clr disabled @@ -283,6 +284,7 @@ enum { SDE_SSPP_BLOCK_SEC_UI, SDE_SSPP_SCALER_QSEED3LITE, SDE_SSPP_TRUE_INLINE_ROT, + SDE_SSPP_MULTIRECT_ERROR, SDE_SSPP_PREDOWNSCALE, SDE_SSPP_PREDOWNSCALE_Y, SDE_SSPP_INLINE_CONST_CLR, @@ -1416,6 +1418,7 @@ struct sde_perf_cfg { * @true_inline_rot_rev inline rotator feature revision * @macrotile_mode UBWC parameter for macro tile channel distribution * @pipe_order_type indicate if it is required to specify pipe order + * @sspp_multirect_error flag to indicate whether ubwc and meta error by rect is supported * @delay_prg_fetch_start indicates if throttling the fetch start is required * @has_qsync Supports qsync feature * @has_3d_merge_reset Supports 3D merge reset @@ -1489,6 +1492,7 @@ struct sde_mdss_cfg { u32 true_inline_rot_rev; u32 macrotile_mode; u32 pipe_order_type; + bool sspp_multirect_error; bool delay_prg_fetch_start; bool has_qsync; bool has_3d_merge_reset; diff --git a/msm/sde/sde_hw_sspp.c b/msm/sde/sde_hw_sspp.c index f9fcc71780..979f4bd9cb 100644 --- a/msm/sde/sde_hw_sspp.c +++ b/msm/sde/sde_hw_sspp.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #include "sde_hwio.h" @@ -86,6 +86,7 @@ #define SSPP_SW_PIX_EXT_C3_LR 0x120 #define SSPP_SW_PIX_EXT_C3_TB 0x124 #define SSPP_SW_PIX_EXT_C3_REQ_PIXELS 0x128 +#define SSPP_META_ERROR_STATUS 0X12C #define SSPP_TRAFFIC_SHAPER 0x130 #define SSPP_CDP_CNTL 0x134 #define SSPP_UBWC_ERROR_STATUS 0x138 @@ -95,6 +96,8 @@ #define SSPP_TRAFFIC_SHAPER_REC1 0x158 #define SSPP_EXCL_REC_SIZE 0x1B4 #define SSPP_EXCL_REC_XY 0x1B8 +#define SSPP_META_ERROR_STATUS_REC1 0x1C4 +#define SSPP_UBWC_ERROR_STATUS_REC1 0x1C8 #define SSPP_VIG_OP_MODE 0x0 #define SSPP_VIG_CSC_10_OP_MODE 0x0 #define SSPP_TRAFFIC_SHAPER_BPC_MAX 0xFF @@ -417,25 +420,81 @@ static void sde_hw_sspp_setup_format(struct sde_hw_pipe *ctx, SDE_REG_WRITE(c, SSPP_UBWC_ERROR_STATUS + idx, BIT(31)); } -static void sde_hw_sspp_clear_ubwc_error(struct sde_hw_pipe *ctx) +static void sde_hw_sspp_clear_ubwc_error(struct sde_hw_pipe *ctx, uint32_t multirect_index) { struct sde_hw_blk_reg_map *c; c = &ctx->hw; + SDE_REG_WRITE(c, SSPP_UBWC_ERROR_STATUS, BIT(31)); } -static u32 sde_hw_sspp_get_ubwc_error(struct sde_hw_pipe *ctx) +static u32 sde_hw_sspp_get_ubwc_error(struct sde_hw_pipe *ctx, uint32_t multirect_index) { struct sde_hw_blk_reg_map *c; u32 reg_code; c = &ctx->hw; + reg_code = SDE_REG_READ(c, SSPP_UBWC_ERROR_STATUS); return reg_code; } +static void sde_hw_sspp_clear_ubwc_error_v1(struct sde_hw_pipe *ctx, uint32_t multirect_index) +{ + struct sde_hw_blk_reg_map *c; + + c = &ctx->hw; + + if (multirect_index == SDE_SSPP_RECT_1) + SDE_REG_WRITE(c, SSPP_UBWC_ERROR_STATUS_REC1, BIT(31)); + else + SDE_REG_WRITE(c, SSPP_UBWC_ERROR_STATUS, BIT(31)); +} + +static u32 sde_hw_sspp_get_ubwc_error_v1(struct sde_hw_pipe *ctx, uint32_t multirect_index) +{ + struct sde_hw_blk_reg_map *c; + u32 reg_code; + + c = &ctx->hw; + + if (multirect_index == SDE_SSPP_RECT_1) + reg_code = SDE_REG_READ(c, SSPP_UBWC_ERROR_STATUS_REC1); + else + reg_code = SDE_REG_READ(c, SSPP_UBWC_ERROR_STATUS); + + return reg_code; +} + +static void sde_hw_sspp_clear_meta_error(struct sde_hw_pipe *ctx, uint32_t multirect_index) +{ + struct sde_hw_blk_reg_map *c; + + c = &ctx->hw; + + if (multirect_index == SDE_SSPP_RECT_1) + SDE_REG_WRITE(c, SSPP_META_ERROR_STATUS_REC1, BIT(31)); + else + SDE_REG_WRITE(c, SSPP_META_ERROR_STATUS, BIT(31)); +} + +static u32 sde_hw_sspp_get_meta_error(struct sde_hw_pipe *ctx, uint32_t multirect_index) +{ + struct sde_hw_blk_reg_map *c; + u32 reg_code; + + c = &ctx->hw; + + if (multirect_index == SDE_SSPP_RECT_1) + reg_code = SDE_REG_READ(c, SSPP_META_ERROR_STATUS_REC1); + else + reg_code = SDE_REG_READ(c, SSPP_META_ERROR_STATUS); + + return reg_code; +} + static void sde_hw_sspp_setup_secure(struct sde_hw_pipe *ctx, enum sde_sspp_multirect_index rect_mode, bool enable) @@ -1253,6 +1312,17 @@ static void _setup_layer_ops(struct sde_hw_pipe *c, c->ops.setup_scaler = reg_dmav1_setup_vig_qseed3; } + if (test_bit(SDE_SSPP_MULTIRECT_ERROR, &features)) { + c->ops.get_meta_error = sde_hw_sspp_get_meta_error; + c->ops.clear_meta_error = sde_hw_sspp_clear_meta_error; + + c->ops.get_ubwc_error = sde_hw_sspp_get_ubwc_error_v1; + c->ops.clear_ubwc_error = sde_hw_sspp_clear_ubwc_error_v1; + } else { + c->ops.get_ubwc_error = sde_hw_sspp_get_ubwc_error; + c->ops.clear_ubwc_error = sde_hw_sspp_clear_ubwc_error; + } + if (test_bit(SDE_SSPP_PREDOWNSCALE, &features)) c->ops.setup_pre_downscale = sde_hw_sspp_setup_pre_downscale; @@ -1271,9 +1341,6 @@ static void _setup_layer_ops(struct sde_hw_pipe *c, c->ops.setup_inverse_pma = sde_hw_sspp_setup_dgm_inverse_pma; else if (test_bit(SDE_SSPP_INVERSE_PMA, &features)) c->ops.setup_inverse_pma = sde_hw_sspp_setup_inverse_pma; - - c->ops.get_ubwc_error = sde_hw_sspp_get_ubwc_error; - c->ops.clear_ubwc_error = sde_hw_sspp_clear_ubwc_error; } static struct sde_sspp_cfg *_sspp_offset(enum sde_sspp sspp, diff --git a/msm/sde/sde_hw_sspp.h b/msm/sde/sde_hw_sspp.h index f562ceb0ab..57209c5d8b 100644 --- a/msm/sde/sde_hw_sspp.h +++ b/msm/sde/sde_hw_sspp.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #ifndef _SDE_HW_SSPP_H @@ -591,17 +591,33 @@ struct sde_hw_sspp_ops { void (*setup_dgm_csc)(struct sde_hw_pipe *ctx, enum sde_sspp_multirect_index index, struct sde_csc_cfg *data); + /** + * clear_meta_error - clear the meta error-code registers + * @ctx: Pointer to pipe context + * @multirect_index: rec in use + */ + void (*clear_meta_error)(struct sde_hw_pipe *ctx, uint32_t multirect_index); + + /** + * get_meta_error - get the meta error-code + * @ctx: Pointer to pipe context + * @multirect_index: rec in use + */ + u32 (*get_meta_error)(struct sde_hw_pipe *ctx, uint32_t multirect_index); + /** * clear_ubwc_error - clear the ubwc error-code registers * @ctx: Pointer to pipe context + * @multirect_index: rec in use */ - void (*clear_ubwc_error)(struct sde_hw_pipe *ctx); + void (*clear_ubwc_error)(struct sde_hw_pipe *ctx, uint32_t multirect_index); /** * get_ubwc_error - get the ubwc error-code * @ctx: Pointer to pipe context + * @multirect_index: rec in use */ - u32 (*get_ubwc_error)(struct sde_hw_pipe *ctx); + u32 (*get_ubwc_error)(struct sde_hw_pipe *ctx, uint32_t multirect_index); }; /** diff --git a/msm/sde/sde_plane.c b/msm/sde/sde_plane.c index 7d4d7fa229..8ae38440b3 100644 --- a/msm/sde/sde_plane.c +++ b/msm/sde/sde_plane.c @@ -4276,15 +4276,18 @@ u32 sde_plane_get_ubwc_error(struct drm_plane *plane) { u32 ubwc_error = 0; struct sde_plane *psde; + struct sde_plane_state *pstate; if (!plane) { SDE_ERROR("invalid plane\n"); return 0; } psde = to_sde_plane(plane); + pstate = to_sde_plane_state(plane->state); if (!psde->is_virtual && psde->pipe_hw->ops.get_ubwc_error) - ubwc_error = psde->pipe_hw->ops.get_ubwc_error(psde->pipe_hw); + ubwc_error = psde->pipe_hw->ops.get_ubwc_error(psde->pipe_hw, + pstate->multirect_index); return ubwc_error; } @@ -4292,15 +4295,53 @@ u32 sde_plane_get_ubwc_error(struct drm_plane *plane) void sde_plane_clear_ubwc_error(struct drm_plane *plane) { struct sde_plane *psde; + struct sde_plane_state *pstate; if (!plane) { SDE_ERROR("invalid plane\n"); return; } psde = to_sde_plane(plane); + pstate = to_sde_plane_state(plane->state); if (psde->pipe_hw->ops.clear_ubwc_error) - psde->pipe_hw->ops.clear_ubwc_error(psde->pipe_hw); + psde->pipe_hw->ops.clear_ubwc_error(psde->pipe_hw, pstate->multirect_index); +} + +u32 sde_plane_get_meta_error(struct drm_plane *plane) +{ + u32 meta_error = 0; + struct sde_plane *psde; + struct sde_plane_state *pstate; + + if (!plane) { + SDE_ERROR("invalid plane\n"); + return 0; + } + psde = to_sde_plane(plane); + pstate = to_sde_plane_state(plane->state); + + if (psde->pipe_hw->ops.get_meta_error) + meta_error = psde->pipe_hw->ops.get_meta_error(psde->pipe_hw, + pstate->multirect_index); + + return meta_error; +} + +void sde_plane_clear_meta_error(struct drm_plane *plane) +{ + struct sde_plane *psde; + struct sde_plane_state *pstate; + + if (!plane) { + SDE_ERROR("invalid plane\n"); + return; + } + psde = to_sde_plane(plane); + pstate = to_sde_plane_state(plane->state); + + if (psde->pipe_hw->ops.clear_meta_error) + psde->pipe_hw->ops.clear_meta_error(psde->pipe_hw, pstate->multirect_index); } #ifdef CONFIG_DEBUG_FS diff --git a/msm/sde/sde_plane.h b/msm/sde/sde_plane.h index 16b72cd72d..105756af83 100644 --- a/msm/sde/sde_plane.h +++ b/msm/sde/sde_plane.h @@ -317,6 +317,18 @@ u32 sde_plane_get_ubwc_error(struct drm_plane *plane); */ void sde_plane_clear_ubwc_error(struct drm_plane *plane); +/* + * sde_plane_get_meta_error - gets the meta error code + * @plane: Pointer to DRM plane object + */ +u32 sde_plane_get_meta_error(struct drm_plane *plane); + +/* + * sde_plane_clear_meta_error - clears the meta error code + * @plane: Pointer to DRM plane object + */ +void sde_plane_clear_meta_error(struct drm_plane *plane); + /* * sde_plane_setup_src_split_order - enable/disable pipe's src_split_order * @plane: Pointer to DRM plane object