Browse Source

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 <[email protected]>
Samantha Tran 4 years ago
parent
commit
73373271a7

+ 8 - 7
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_crtc_frame_event *fevent;
 	struct sde_kms_frame_event_cb_data *cb_data;
 	struct sde_kms_frame_event_cb_data *cb_data;
 	struct drm_plane *plane;
 	struct drm_plane *plane;
-	u32 ubwc_error;
+	u32 ubwc_error, meta_error;
 	unsigned long flags;
 	unsigned long flags;
 	u32 crtc_id;
 	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,
 		drm_for_each_plane_mask(plane, crtc->dev,
 						sde_crtc->plane_mask_old) {
 						sde_crtc->plane_mask_old) {
 			ubwc_error = sde_plane_get_ubwc_error(plane);
 			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_ubwc_error(plane);
+				sde_plane_clear_meta_error(plane);
 			}
 			}
 		}
 		}
 	}
 	}

+ 4 - 0
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)
 		if (sde_cfg->sc_cfg[SDE_SYS_CACHE_DISP].has_sys_cache)
 			set_bit(SDE_PERF_SSPP_SYS_CACHE, &sspp->perf_features);
 			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) {
 		if (sde_cfg->has_decimation) {
 			sblk->maxhdeciexp = MAX_HORZ_DECIMATION;
 			sblk->maxhdeciexp = MAX_HORZ_DECIMATION;
 			sblk->maxvdeciexp = MAX_VERT_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->dither_luma_mode_support = true;
 		sde_cfg->mdss_hw_block_size = 0x158;
 		sde_cfg->mdss_hw_block_size = 0x158;
 		sde_cfg->syscache_supported = true;
 		sde_cfg->syscache_supported = true;
+		sde_cfg->sspp_multirect_error = true;
 	} else {
 	} else {
 		SDE_ERROR("unsupported chipset id:%X\n", hw_rev);
 		SDE_ERROR("unsupported chipset id:%X\n", hw_rev);
 		sde_cfg->perf.min_prefill_lines = 0xffff;
 		sde_cfg->perf.min_prefill_lines = 0xffff;

+ 4 - 0
msm/sde/sde_hw_catalog.h

@@ -252,6 +252,7 @@ enum {
  * @SDE_SSPP_BLOCK_SEC_UI    Blocks secure-ui layers
  * @SDE_SSPP_BLOCK_SEC_UI    Blocks secure-ui layers
  * @SDE_SSPP_SCALER_QSEED3LITE Qseed3lite algorithm support
  * @SDE_SSPP_SCALER_QSEED3LITE Qseed3lite algorithm support
  * @SDE_SSPP_TRUE_INLINE_ROT Support of SSPP true inline rotation v1
  * @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    Support pre-downscale X-direction by 2 for inline
  * @SDE_SSPP_PREDOWNSCALE_Y  Support pre-downscale Y-direction for inline
  * @SDE_SSPP_PREDOWNSCALE_Y  Support pre-downscale Y-direction for inline
  * @SDE_SSPP_INLINE_CONST_CLR Inline rotation requires const clr disabled
  * @SDE_SSPP_INLINE_CONST_CLR Inline rotation requires const clr disabled
@@ -283,6 +284,7 @@ enum {
 	SDE_SSPP_BLOCK_SEC_UI,
 	SDE_SSPP_BLOCK_SEC_UI,
 	SDE_SSPP_SCALER_QSEED3LITE,
 	SDE_SSPP_SCALER_QSEED3LITE,
 	SDE_SSPP_TRUE_INLINE_ROT,
 	SDE_SSPP_TRUE_INLINE_ROT,
+	SDE_SSPP_MULTIRECT_ERROR,
 	SDE_SSPP_PREDOWNSCALE,
 	SDE_SSPP_PREDOWNSCALE,
 	SDE_SSPP_PREDOWNSCALE_Y,
 	SDE_SSPP_PREDOWNSCALE_Y,
 	SDE_SSPP_INLINE_CONST_CLR,
 	SDE_SSPP_INLINE_CONST_CLR,
@@ -1416,6 +1418,7 @@ struct sde_perf_cfg {
  * @true_inline_rot_rev	inline rotator feature revision
  * @true_inline_rot_rev	inline rotator feature revision
  * @macrotile_mode     UBWC parameter for macro tile channel distribution
  * @macrotile_mode     UBWC parameter for macro tile channel distribution
  * @pipe_order_type    indicate if it is required to specify pipe order
  * @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
  * @delay_prg_fetch_start indicates if throttling the fetch start is required
  * @has_qsync	       Supports qsync feature
  * @has_qsync	       Supports qsync feature
  * @has_3d_merge_reset Supports 3D merge reset
  * @has_3d_merge_reset Supports 3D merge reset
@@ -1489,6 +1492,7 @@ struct sde_mdss_cfg {
 	u32 true_inline_rot_rev;
 	u32 true_inline_rot_rev;
 	u32 macrotile_mode;
 	u32 macrotile_mode;
 	u32 pipe_order_type;
 	u32 pipe_order_type;
+	bool sspp_multirect_error;
 	bool delay_prg_fetch_start;
 	bool delay_prg_fetch_start;
 	bool has_qsync;
 	bool has_qsync;
 	bool has_3d_merge_reset;
 	bool has_3d_merge_reset;

+ 73 - 6
msm/sde/sde_hw_sspp.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // 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"
 #include "sde_hwio.h"
@@ -86,6 +86,7 @@
 #define SSPP_SW_PIX_EXT_C3_LR              0x120
 #define SSPP_SW_PIX_EXT_C3_LR              0x120
 #define SSPP_SW_PIX_EXT_C3_TB              0x124
 #define SSPP_SW_PIX_EXT_C3_TB              0x124
 #define SSPP_SW_PIX_EXT_C3_REQ_PIXELS      0x128
 #define SSPP_SW_PIX_EXT_C3_REQ_PIXELS      0x128
+#define SSPP_META_ERROR_STATUS             0X12C
 #define SSPP_TRAFFIC_SHAPER                0x130
 #define SSPP_TRAFFIC_SHAPER                0x130
 #define SSPP_CDP_CNTL                      0x134
 #define SSPP_CDP_CNTL                      0x134
 #define SSPP_UBWC_ERROR_STATUS             0x138
 #define SSPP_UBWC_ERROR_STATUS             0x138
@@ -95,6 +96,8 @@
 #define SSPP_TRAFFIC_SHAPER_REC1           0x158
 #define SSPP_TRAFFIC_SHAPER_REC1           0x158
 #define SSPP_EXCL_REC_SIZE                 0x1B4
 #define SSPP_EXCL_REC_SIZE                 0x1B4
 #define SSPP_EXCL_REC_XY                   0x1B8
 #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_OP_MODE                   0x0
 #define SSPP_VIG_CSC_10_OP_MODE            0x0
 #define SSPP_VIG_CSC_10_OP_MODE            0x0
 #define SSPP_TRAFFIC_SHAPER_BPC_MAX        0xFF
 #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));
 	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;
 	struct sde_hw_blk_reg_map *c;
 
 
 	c = &ctx->hw;
 	c = &ctx->hw;
+
 	SDE_REG_WRITE(c, SSPP_UBWC_ERROR_STATUS, BIT(31));
 	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;
 	struct sde_hw_blk_reg_map *c;
 	u32 reg_code;
 	u32 reg_code;
 
 
 	c = &ctx->hw;
 	c = &ctx->hw;
+
 	reg_code = SDE_REG_READ(c, SSPP_UBWC_ERROR_STATUS);
 	reg_code = SDE_REG_READ(c, SSPP_UBWC_ERROR_STATUS);
 
 
 	return reg_code;
 	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,
 static void sde_hw_sspp_setup_secure(struct sde_hw_pipe *ctx,
 		enum sde_sspp_multirect_index rect_mode,
 		enum sde_sspp_multirect_index rect_mode,
 		bool enable)
 		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;
 			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))
 	if (test_bit(SDE_SSPP_PREDOWNSCALE, &features))
 		c->ops.setup_pre_downscale = sde_hw_sspp_setup_pre_downscale;
 		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;
 		c->ops.setup_inverse_pma = sde_hw_sspp_setup_dgm_inverse_pma;
 	else if (test_bit(SDE_SSPP_INVERSE_PMA, &features))
 	else if (test_bit(SDE_SSPP_INVERSE_PMA, &features))
 		c->ops.setup_inverse_pma = sde_hw_sspp_setup_inverse_pma;
 		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,
 static struct sde_sspp_cfg *_sspp_offset(enum sde_sspp sspp,

+ 19 - 3
msm/sde/sde_hw_sspp.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* 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
 #ifndef _SDE_HW_SSPP_H
@@ -591,17 +591,33 @@ struct sde_hw_sspp_ops {
 	void (*setup_dgm_csc)(struct sde_hw_pipe *ctx,
 	void (*setup_dgm_csc)(struct sde_hw_pipe *ctx,
 		enum sde_sspp_multirect_index index, struct sde_csc_cfg *data);
 		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
 	 * clear_ubwc_error - clear the ubwc error-code registers
 	 * @ctx: Pointer to pipe context
 	 * @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
 	 * get_ubwc_error - get the ubwc error-code
 	 * @ctx: Pointer to pipe context
 	 * @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);
 };
 };
 
 
 /**
 /**

+ 43 - 2
msm/sde/sde_plane.c

@@ -4276,15 +4276,18 @@ u32 sde_plane_get_ubwc_error(struct drm_plane *plane)
 {
 {
 	u32 ubwc_error = 0;
 	u32 ubwc_error = 0;
 	struct sde_plane *psde;
 	struct sde_plane *psde;
+	struct sde_plane_state *pstate;
 
 
 	if (!plane) {
 	if (!plane) {
 		SDE_ERROR("invalid plane\n");
 		SDE_ERROR("invalid plane\n");
 		return 0;
 		return 0;
 	}
 	}
 	psde = to_sde_plane(plane);
 	psde = to_sde_plane(plane);
+	pstate = to_sde_plane_state(plane->state);
 
 
 	if (!psde->is_virtual && psde->pipe_hw->ops.get_ubwc_error)
 	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;
 	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)
 void sde_plane_clear_ubwc_error(struct drm_plane *plane)
 {
 {
 	struct sde_plane *psde;
 	struct sde_plane *psde;
+	struct sde_plane_state *pstate;
 
 
 	if (!plane) {
 	if (!plane) {
 		SDE_ERROR("invalid plane\n");
 		SDE_ERROR("invalid plane\n");
 		return;
 		return;
 	}
 	}
 	psde = to_sde_plane(plane);
 	psde = to_sde_plane(plane);
+	pstate = to_sde_plane_state(plane->state);
 
 
 	if (psde->pipe_hw->ops.clear_ubwc_error)
 	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
 #ifdef CONFIG_DEBUG_FS

+ 12 - 0
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);
 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
  * sde_plane_setup_src_split_order - enable/disable pipe's src_split_order
  * @plane: Pointer to DRM plane object
  * @plane: Pointer to DRM plane object