dri-devel.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/17] Add support for CDM over DP
@ 2024-01-25 19:38 Paloma Arellano
  2024-01-25 19:38 ` [PATCH 01/17] drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP Paloma Arellano
                   ` (16 more replies)
  0 siblings, 17 replies; 95+ messages in thread
From: Paloma Arellano @ 2024-01-25 19:38 UTC (permalink / raw)
  To: freedreno
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, quic_abhinavk,
	dri-devel, swboyd, seanpaul, quic_jesszhan, dmitry.baryshkov,
	Paloma Arellano, quic_khsieh

The Chroma Down Sampling (CDM) block is a hardware component in the DPU
pipeline that includes a CSC block capable of converting RGB input from
the DPU to YUV data.

This block can be used with either HDMI, DP, or writeback interfaces.
This series adds support for the CDM block to be used with DP in
YUV420 mode format.

This series allows selection of the YUV420 format for monitors which support
certain resolutions only in YUV420 thus unblocking the validation of many
other resolutions which were previously filtered out if the connector did
not support YUV420.

This was validated using a DP connected monitor requiring the use of
YUV420 format.

This series currently works as-is. But it was also validated to function on
top of in the case of future integration:

https://patchwork.freedesktop.org/series/118831/

Kuogee Hsieh (1):
  drm/msm/dpu: add support of new peripheral flush mechanism

Paloma Arellano (16):
  drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP
  drm/msm/dpu: move dpu_encoder_helper_phys_setup_cdm to dpu_encoder
  drm/msm/dp: rename wide_bus_en to wide_bus_supported
  drm/msm/dp: store mode YUV420 information to be used by rest of DP
  drm/msm/dp: add an API to indicate if sink supports VSC SDP
  drm/msm/dpu: move widebus logic to its own API
  drm/msm/dpu: disallow widebus en in INTF_CONFIG2 when DP is YUV420
  drm/msm/dp: change YUV420 related programming for DP
  drm/msm/dp: move parity calculation to dp_catalog
  drm/msm/dp: modify dp_catalog_hw_revision to show major and minor val
  drm/msm/dp: add VSC SDP support for YUV420 over DP
  drm/msm/dp: enable SDP and SDE periph flush update
  drm/msm/dpu: modify encoder programming for CDM over DP
  drm/msm/dpu: allow certain formats for CDM for DP
  drm/msm/dpu: reserve CDM blocks for DP if mode is YUV420
  drm/msm/dp: allow YUV420 mode for DP connector when VSC SDP supported

 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 143 ++++++++++++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |  12 ++
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  13 +-
 .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  |  36 +++-
 .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 101 +---------
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c    |   2 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c    |  17 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h    |  10 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c   |   4 +-
 drivers/gpu/drm/msm/dp/dp_audio.c             | 100 ++--------
 drivers/gpu/drm/msm/dp/dp_catalog.c           | 182 +++++++++++++++++-
 drivers/gpu/drm/msm/dp/dp_catalog.h           |  81 +++++++-
 drivers/gpu/drm/msm/dp/dp_ctrl.c              |  17 +-
 drivers/gpu/drm/msm/dp/dp_display.c           |  79 +++++---
 drivers/gpu/drm/msm/dp/dp_panel.c             |  82 +++++++-
 drivers/gpu/drm/msm/dp/dp_panel.h             |   2 +
 drivers/gpu/drm/msm/dp/dp_reg.h               |   5 +
 drivers/gpu/drm/msm/msm_drv.h                 |   9 +-
 drivers/gpu/drm/msm/msm_kms.h                 |   3 +
 19 files changed, 655 insertions(+), 243 deletions(-)

-- 
2.39.2


^ permalink raw reply	[flat|nested] 95+ messages in thread

* [PATCH 01/17] drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP
  2024-01-25 19:38 [PATCH 00/17] Add support for CDM over DP Paloma Arellano
@ 2024-01-25 19:38 ` Paloma Arellano
  2024-01-25 21:14   ` Dmitry Baryshkov
  2024-01-25 19:38 ` [PATCH 02/17] drm/msm/dpu: move dpu_encoder_helper_phys_setup_cdm to dpu_encoder Paloma Arellano
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-25 19:38 UTC (permalink / raw)
  To: freedreno
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, quic_abhinavk,
	dri-devel, swboyd, seanpaul, quic_jesszhan, dmitry.baryshkov,
	Paloma Arellano, quic_khsieh

Generalize dpu_encoder_helper_phys_setup_cdm to be compatible with DP.

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  4 +--
 .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 31 ++++++++++---------
 2 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index 993f263433314..37ac385727c3b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -153,6 +153,7 @@ enum dpu_intr_idx {
  * @hw_intf:		Hardware interface to the intf registers
  * @hw_wb:		Hardware interface to the wb registers
  * @hw_cdm:		Hardware interface to the CDM registers
+ * @cdm_cfg:	CDM block config needed to store WB/DP block's CDM configuration
  * @dpu_kms:		Pointer to the dpu_kms top level
  * @cached_mode:	DRM mode cached at mode_set time, acted on in enable
  * @vblank_ctl_lock:	Vblank ctl mutex lock to protect vblank_refcount
@@ -183,6 +184,7 @@ struct dpu_encoder_phys {
 	struct dpu_hw_intf *hw_intf;
 	struct dpu_hw_wb *hw_wb;
 	struct dpu_hw_cdm *hw_cdm;
+	struct dpu_hw_cdm_cfg cdm_cfg;
 	struct dpu_kms *dpu_kms;
 	struct drm_display_mode cached_mode;
 	struct mutex vblank_ctl_lock;
@@ -213,7 +215,6 @@ static inline int dpu_encoder_phys_inc_pending(struct dpu_encoder_phys *phys)
  * @wbirq_refcount:     Reference count of writeback interrupt
  * @wb_done_timeout_cnt: number of wb done irq timeout errors
  * @wb_cfg:  writeback block config to store fb related details
- * @cdm_cfg: cdm block config needed to store writeback block's CDM configuration
  * @wb_conn: backpointer to writeback connector
  * @wb_job: backpointer to current writeback job
  * @dest:   dpu buffer layout for current writeback output buffer
@@ -223,7 +224,6 @@ struct dpu_encoder_phys_wb {
 	atomic_t wbirq_refcount;
 	int wb_done_timeout_cnt;
 	struct dpu_hw_wb_cfg wb_cfg;
-	struct dpu_hw_cdm_cfg cdm_cfg;
 	struct drm_writeback_connector *wb_conn;
 	struct drm_writeback_job *wb_job;
 	struct dpu_hw_fmt_layout dest;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
index 4cd2d9e3131a4..072fc6950e496 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -269,28 +269,21 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
  *                                     This API does not handle DPU_CHROMA_H1V2.
  * @phys_enc:Pointer to physical encoder
  */
-static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
+static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc,
+					      const struct dpu_format *dpu_fmt,
+					      u32 output_type)
 {
 	struct dpu_hw_cdm *hw_cdm;
 	struct dpu_hw_cdm_cfg *cdm_cfg;
 	struct dpu_hw_pingpong *hw_pp;
-	struct dpu_encoder_phys_wb *wb_enc;
-	const struct msm_format *format;
-	const struct dpu_format *dpu_fmt;
-	struct drm_writeback_job *wb_job;
 	int ret;
 
 	if (!phys_enc)
 		return;
 
-	wb_enc = to_dpu_encoder_phys_wb(phys_enc);
-	cdm_cfg = &wb_enc->cdm_cfg;
+	cdm_cfg = &phys_enc->cdm_cfg;
 	hw_pp = phys_enc->hw_pp;
 	hw_cdm = phys_enc->hw_cdm;
-	wb_job = wb_enc->wb_job;
-
-	format = msm_framebuffer_format(wb_enc->wb_job->fb);
-	dpu_fmt = dpu_get_dpu_format_ext(format->pixel_format, wb_job->fb->modifier);
 
 	if (!hw_cdm)
 		return;
@@ -306,10 +299,10 @@ static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
 
 	memset(cdm_cfg, 0, sizeof(struct dpu_hw_cdm_cfg));
 
-	cdm_cfg->output_width = wb_job->fb->width;
-	cdm_cfg->output_height = wb_job->fb->height;
+	cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
+	cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
 	cdm_cfg->output_fmt = dpu_fmt;
-	cdm_cfg->output_type = CDM_CDWN_OUTPUT_WB;
+	cdm_cfg->output_type = output_type;
 	cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
 			CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
 	cdm_cfg->csc_cfg = &dpu_csc10_rgb2yuv_601l;
@@ -462,6 +455,14 @@ static void dpu_encoder_phys_wb_setup(
 	struct dpu_hw_wb *hw_wb = phys_enc->hw_wb;
 	struct drm_display_mode mode = phys_enc->cached_mode;
 	struct drm_framebuffer *fb = NULL;
+	struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc);
+	struct drm_writeback_job *wb_job;
+	const struct msm_format *format;
+	const struct dpu_format *dpu_fmt;
+
+	wb_job = wb_enc->wb_job;
+	format = msm_framebuffer_format(wb_enc->wb_job->fb);
+	dpu_fmt = dpu_get_dpu_format_ext(format->pixel_format, wb_job->fb->modifier);
 
 	DPU_DEBUG("[mode_set:%d, \"%s\",%d,%d]\n",
 			hw_wb->idx - WB_0, mode.name,
@@ -475,7 +476,7 @@ static void dpu_encoder_phys_wb_setup(
 
 	dpu_encoder_phys_wb_setup_fb(phys_enc, fb);
 
-	dpu_encoder_helper_phys_setup_cdm(phys_enc);
+	dpu_encoder_helper_phys_setup_cdm(phys_enc, dpu_fmt, CDM_CDWN_OUTPUT_WB);
 
 	dpu_encoder_phys_wb_setup_ctl(phys_enc);
 }
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 02/17] drm/msm/dpu: move dpu_encoder_helper_phys_setup_cdm to dpu_encoder
  2024-01-25 19:38 [PATCH 00/17] Add support for CDM over DP Paloma Arellano
  2024-01-25 19:38 ` [PATCH 01/17] drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP Paloma Arellano
@ 2024-01-25 19:38 ` Paloma Arellano
  2024-01-25 21:16   ` Dmitry Baryshkov
  2024-01-25 19:38 ` [PATCH 03/17] drm/msm/dp: rename wide_bus_en to wide_bus_supported Paloma Arellano
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-25 19:38 UTC (permalink / raw)
  To: freedreno
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, quic_abhinavk,
	dri-devel, swboyd, seanpaul, quic_jesszhan, dmitry.baryshkov,
	Paloma Arellano, quic_khsieh

Move dpu_encoder_helper_phys_setup_cdm to dpu_encoder in preparation for
implementing CDM compatibility for DP.

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 78 +++++++++++++++++
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  9 ++
 .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 84 -------------------
 3 files changed, 87 insertions(+), 84 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 83380bc92a00a..6cef98f046ea6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2114,6 +2114,84 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
 	ctl->ops.clear_pending_flush(ctl);
 }
 
+void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc,
+				       const struct dpu_format *dpu_fmt,
+				       u32 output_type)
+{
+	struct dpu_hw_cdm *hw_cdm;
+	struct dpu_hw_cdm_cfg *cdm_cfg;
+	struct dpu_hw_pingpong *hw_pp;
+	int ret;
+
+	if (!phys_enc)
+		return;
+
+	cdm_cfg = &phys_enc->cdm_cfg;
+	hw_pp = phys_enc->hw_pp;
+	hw_cdm = phys_enc->hw_cdm;
+
+	if (!hw_cdm)
+		return;
+
+	if (!DPU_FORMAT_IS_YUV(dpu_fmt)) {
+		DPU_DEBUG("[enc:%d] cdm_disable fmt:%x\n", DRMID(phys_enc->parent),
+			  dpu_fmt->base.pixel_format);
+		if (hw_cdm->ops.bind_pingpong_blk)
+			hw_cdm->ops.bind_pingpong_blk(hw_cdm, PINGPONG_NONE);
+
+		return;
+	}
+
+	memset(cdm_cfg, 0, sizeof(struct dpu_hw_cdm_cfg));
+
+	cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
+	cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
+	cdm_cfg->output_fmt = dpu_fmt;
+	cdm_cfg->output_type = output_type;
+	cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
+			CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
+	cdm_cfg->csc_cfg = &dpu_csc10_rgb2yuv_601l;
+
+	/* enable 10 bit logic */
+	switch (cdm_cfg->output_fmt->chroma_sample) {
+	case DPU_CHROMA_RGB:
+		cdm_cfg->h_cdwn_type = CDM_CDWN_DISABLE;
+		cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
+		break;
+	case DPU_CHROMA_H2V1:
+		cdm_cfg->h_cdwn_type = CDM_CDWN_COSITE;
+		cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
+		break;
+	case DPU_CHROMA_420:
+		cdm_cfg->h_cdwn_type = CDM_CDWN_COSITE;
+		cdm_cfg->v_cdwn_type = CDM_CDWN_OFFSITE;
+		break;
+	case DPU_CHROMA_H1V2:
+	default:
+		DPU_ERROR("[enc:%d] unsupported chroma sampling type\n",
+			  DRMID(phys_enc->parent));
+		cdm_cfg->h_cdwn_type = CDM_CDWN_DISABLE;
+		cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
+		break;
+	}
+
+	DPU_DEBUG("[enc:%d] cdm_enable:%d,%d,%X,%d,%d,%d,%d]\n",
+		  DRMID(phys_enc->parent), cdm_cfg->output_width,
+		  cdm_cfg->output_height, cdm_cfg->output_fmt->base.pixel_format,
+		  cdm_cfg->output_type, cdm_cfg->output_bit_depth,
+		  cdm_cfg->h_cdwn_type, cdm_cfg->v_cdwn_type);
+
+	if (hw_cdm->ops.enable) {
+		cdm_cfg->pp_id = hw_pp->idx;
+		ret = hw_cdm->ops.enable(hw_cdm, cdm_cfg);
+		if (ret < 0) {
+			DPU_ERROR("[enc:%d] failed to enable CDM; ret:%d\n",
+				  DRMID(phys_enc->parent), ret);
+			return;
+		}
+	}
+}
+
 #ifdef CONFIG_DEBUG_FS
 static int _dpu_encoder_status_show(struct seq_file *s, void *data)
 {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index 37ac385727c3b..310944303a056 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -381,6 +381,15 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc,
  */
 void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc);
 
+/**
+ * dpu_encoder_helper_phys_setup_cdm - setup chroma down sampling block
+ * @phys_enc: Pointer to physical encoder
+ * @output_type: HDMI/WB
+ */
+void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc,
+				       const struct dpu_format *dpu_fmt,
+				       u32 output_type);
+
 /**
  * dpu_encoder_vblank_callback - Notify virtual encoder of vblank IRQ reception
  * @drm_enc:    Pointer to drm encoder structure
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
index 072fc6950e496..400580847bde7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -264,89 +264,6 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
 	}
 }
 
-/**
- * dpu_encoder_helper_phys_setup_cdm - setup chroma down sampling block
- *                                     This API does not handle DPU_CHROMA_H1V2.
- * @phys_enc:Pointer to physical encoder
- */
-static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc,
-					      const struct dpu_format *dpu_fmt,
-					      u32 output_type)
-{
-	struct dpu_hw_cdm *hw_cdm;
-	struct dpu_hw_cdm_cfg *cdm_cfg;
-	struct dpu_hw_pingpong *hw_pp;
-	int ret;
-
-	if (!phys_enc)
-		return;
-
-	cdm_cfg = &phys_enc->cdm_cfg;
-	hw_pp = phys_enc->hw_pp;
-	hw_cdm = phys_enc->hw_cdm;
-
-	if (!hw_cdm)
-		return;
-
-	if (!DPU_FORMAT_IS_YUV(dpu_fmt)) {
-		DPU_DEBUG("[enc:%d] cdm_disable fmt:%x\n", DRMID(phys_enc->parent),
-			  dpu_fmt->base.pixel_format);
-		if (hw_cdm->ops.bind_pingpong_blk)
-			hw_cdm->ops.bind_pingpong_blk(hw_cdm, PINGPONG_NONE);
-
-		return;
-	}
-
-	memset(cdm_cfg, 0, sizeof(struct dpu_hw_cdm_cfg));
-
-	cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
-	cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
-	cdm_cfg->output_fmt = dpu_fmt;
-	cdm_cfg->output_type = output_type;
-	cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
-			CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
-	cdm_cfg->csc_cfg = &dpu_csc10_rgb2yuv_601l;
-
-	/* enable 10 bit logic */
-	switch (cdm_cfg->output_fmt->chroma_sample) {
-	case DPU_CHROMA_RGB:
-		cdm_cfg->h_cdwn_type = CDM_CDWN_DISABLE;
-		cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
-		break;
-	case DPU_CHROMA_H2V1:
-		cdm_cfg->h_cdwn_type = CDM_CDWN_COSITE;
-		cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
-		break;
-	case DPU_CHROMA_420:
-		cdm_cfg->h_cdwn_type = CDM_CDWN_COSITE;
-		cdm_cfg->v_cdwn_type = CDM_CDWN_OFFSITE;
-		break;
-	case DPU_CHROMA_H1V2:
-	default:
-		DPU_ERROR("[enc:%d] unsupported chroma sampling type\n",
-			  DRMID(phys_enc->parent));
-		cdm_cfg->h_cdwn_type = CDM_CDWN_DISABLE;
-		cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
-		break;
-	}
-
-	DPU_DEBUG("[enc:%d] cdm_enable:%d,%d,%X,%d,%d,%d,%d]\n",
-		  DRMID(phys_enc->parent), cdm_cfg->output_width,
-		  cdm_cfg->output_height, cdm_cfg->output_fmt->base.pixel_format,
-		  cdm_cfg->output_type, cdm_cfg->output_bit_depth,
-		  cdm_cfg->h_cdwn_type, cdm_cfg->v_cdwn_type);
-
-	if (hw_cdm->ops.enable) {
-		cdm_cfg->pp_id = hw_pp->idx;
-		ret = hw_cdm->ops.enable(hw_cdm, cdm_cfg);
-		if (ret < 0) {
-			DPU_ERROR("[enc:%d] failed to enable CDM; ret:%d\n",
-				  DRMID(phys_enc->parent), ret);
-			return;
-		}
-	}
-}
-
 /**
  * dpu_encoder_phys_wb_atomic_check - verify and fixup given atomic states
  * @phys_enc:	Pointer to physical encoder
@@ -399,7 +316,6 @@ static int dpu_encoder_phys_wb_atomic_check(
 	return drm_atomic_helper_check_wb_connector_state(conn_state->connector, conn_state->state);
 }
 
-
 /**
  * _dpu_encoder_phys_wb_update_flush - flush hardware update
  * @phys_enc:	Pointer to physical encoder
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 03/17] drm/msm/dp: rename wide_bus_en to wide_bus_supported
  2024-01-25 19:38 [PATCH 00/17] Add support for CDM over DP Paloma Arellano
  2024-01-25 19:38 ` [PATCH 01/17] drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP Paloma Arellano
  2024-01-25 19:38 ` [PATCH 02/17] drm/msm/dpu: move dpu_encoder_helper_phys_setup_cdm to dpu_encoder Paloma Arellano
@ 2024-01-25 19:38 ` Paloma Arellano
  2024-01-25 21:17   ` Dmitry Baryshkov
  2024-01-25 19:38 ` [PATCH 04/17] drm/msm/dp: store mode YUV420 information to be used by rest of DP Paloma Arellano
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-25 19:38 UTC (permalink / raw)
  To: freedreno
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, quic_abhinavk,
	dri-devel, swboyd, seanpaul, quic_jesszhan, dmitry.baryshkov,
	Paloma Arellano, quic_khsieh

Rename wide_bus_en to wide_bus_supported in dp_display_private to
correctly establish that the parameter is referencing if wide bus is
supported instead of enabled.

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 drivers/gpu/drm/msm/dp/dp_display.c | 42 ++++++++++++++---------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index d37d599aec273..9df2a8b21021e 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -113,7 +113,7 @@ struct dp_display_private {
 	struct dp_event event_list[DP_EVENT_Q_MAX];
 	spinlock_t event_lock;
 
-	bool wide_bus_en;
+	bool wide_bus_supported;
 
 	struct dp_audio *audio;
 };
@@ -122,7 +122,7 @@ struct msm_dp_desc {
 	phys_addr_t io_start;
 	unsigned int id;
 	unsigned int connector_type;
-	bool wide_bus_en;
+	bool wide_bus_supported;
 };
 
 static const struct msm_dp_desc sc7180_dp_descs[] = {
@@ -131,8 +131,8 @@ static const struct msm_dp_desc sc7180_dp_descs[] = {
 };
 
 static const struct msm_dp_desc sc7280_dp_descs[] = {
-	{ .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-	{ .io_start = 0x0aea0000, .id = MSM_DP_CONTROLLER_1, .connector_type = DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true },
+	{ .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+	{ .io_start = 0x0aea0000, .id = MSM_DP_CONTROLLER_1, .connector_type = DRM_MODE_CONNECTOR_eDP, .wide_bus_supported = true },
 	{}
 };
 
@@ -144,22 +144,22 @@ static const struct msm_dp_desc sc8180x_dp_descs[] = {
 };
 
 static const struct msm_dp_desc sc8280xp_dp_descs[] = {
-	{ .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-	{ .io_start = 0x0ae98000, .id = MSM_DP_CONTROLLER_1, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-	{ .io_start = 0x0ae9a000, .id = MSM_DP_CONTROLLER_2, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-	{ .io_start = 0x0aea0000, .id = MSM_DP_CONTROLLER_3, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-	{ .io_start = 0x22090000, .id = MSM_DP_CONTROLLER_0, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-	{ .io_start = 0x22098000, .id = MSM_DP_CONTROLLER_1, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-	{ .io_start = 0x2209a000, .id = MSM_DP_CONTROLLER_2, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
-	{ .io_start = 0x220a0000, .id = MSM_DP_CONTROLLER_3, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_en = true },
+	{ .io_start = 0x0ae90000, .id = MSM_DP_CONTROLLER_0, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+	{ .io_start = 0x0ae98000, .id = MSM_DP_CONTROLLER_1, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+	{ .io_start = 0x0ae9a000, .id = MSM_DP_CONTROLLER_2, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+	{ .io_start = 0x0aea0000, .id = MSM_DP_CONTROLLER_3, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+	{ .io_start = 0x22090000, .id = MSM_DP_CONTROLLER_0, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+	{ .io_start = 0x22098000, .id = MSM_DP_CONTROLLER_1, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+	{ .io_start = 0x2209a000, .id = MSM_DP_CONTROLLER_2, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
+	{ .io_start = 0x220a0000, .id = MSM_DP_CONTROLLER_3, .connector_type = DRM_MODE_CONNECTOR_DisplayPort, .wide_bus_supported = true },
 	{}
 };
 
 static const struct msm_dp_desc sc8280xp_edp_descs[] = {
-	{ .io_start = 0x0ae9a000, .id = MSM_DP_CONTROLLER_2, .connector_type = DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true },
-	{ .io_start = 0x0aea0000, .id = MSM_DP_CONTROLLER_3, .connector_type = DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true },
-	{ .io_start = 0x2209a000, .id = MSM_DP_CONTROLLER_2, .connector_type = DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true },
-	{ .io_start = 0x220a0000, .id = MSM_DP_CONTROLLER_3, .connector_type = DRM_MODE_CONNECTOR_eDP, .wide_bus_en = true },
+	{ .io_start = 0x0ae9a000, .id = MSM_DP_CONTROLLER_2, .connector_type = DRM_MODE_CONNECTOR_eDP, .wide_bus_supported = true },
+	{ .io_start = 0x0aea0000, .id = MSM_DP_CONTROLLER_3, .connector_type = DRM_MODE_CONNECTOR_eDP, .wide_bus_supported = true },
+	{ .io_start = 0x2209a000, .id = MSM_DP_CONTROLLER_2, .connector_type = DRM_MODE_CONNECTOR_eDP, .wide_bus_supported = true },
+	{ .io_start = 0x220a0000, .id = MSM_DP_CONTROLLER_3, .connector_type = DRM_MODE_CONNECTOR_eDP, .wide_bus_supported = true },
 	{}
 };
 
@@ -784,9 +784,9 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
 		goto error_ctrl;
 	}
 
-	/* populate wide_bus_en to differernt layers */
-	dp->ctrl->wide_bus_en = dp->wide_bus_en;
-	dp->catalog->wide_bus_en = dp->wide_bus_en;
+	/* populate wide_bus_supported to different layers */
+	dp->ctrl->wide_bus_en = dp->wide_bus_supported;
+	dp->catalog->wide_bus_en = dp->wide_bus_supported;
 
 	return rc;
 
@@ -1256,7 +1256,7 @@ static int dp_display_probe(struct platform_device *pdev)
 	dp->name = "drm_dp";
 	dp->id = desc->id;
 	dp->dp_display.connector_type = desc->connector_type;
-	dp->wide_bus_en = desc->wide_bus_en;
+	dp->wide_bus_supported = desc->wide_bus_supported;
 	dp->dp_display.is_edp =
 		(dp->dp_display.connector_type == DRM_MODE_CONNECTOR_eDP);
 
@@ -1402,7 +1402,7 @@ bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)
 
 	dp = container_of(dp_display, struct dp_display_private, dp_display);
 
-	return dp->wide_bus_en;
+	return dp->wide_bus_supported;
 }
 
 void dp_display_debugfs_init(struct msm_dp *dp_display, struct dentry *root, bool is_edp)
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 04/17] drm/msm/dp: store mode YUV420 information to be used by rest of DP
  2024-01-25 19:38 [PATCH 00/17] Add support for CDM over DP Paloma Arellano
                   ` (2 preceding siblings ...)
  2024-01-25 19:38 ` [PATCH 03/17] drm/msm/dp: rename wide_bus_en to wide_bus_supported Paloma Arellano
@ 2024-01-25 19:38 ` Paloma Arellano
  2024-01-25 21:20   ` Dmitry Baryshkov
  2024-01-25 19:38 ` [PATCH 05/17] drm/msm/dp: add an API to indicate if sink supports VSC SDP Paloma Arellano
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-25 19:38 UTC (permalink / raw)
  To: freedreno
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, quic_abhinavk,
	dri-devel, swboyd, seanpaul, quic_jesszhan, dmitry.baryshkov,
	Paloma Arellano, quic_khsieh

Wide bus is not supported when the mode is YUV420 in DP. In preparation
for changing the DPU programming to reflect this, the value and
assignment location of wide_bus_en for the DP submodules must be
changed. Move it from boot time in dp_init_sub_modules() to run time in
dp_display_mode_set.

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 drivers/gpu/drm/msm/dp/dp_display.c | 17 +++++++++++++----
 drivers/gpu/drm/msm/dp/dp_panel.h   |  1 +
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 9df2a8b21021e..ddac55f45a722 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -784,10 +784,6 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
 		goto error_ctrl;
 	}
 
-	/* populate wide_bus_supported to different layers */
-	dp->ctrl->wide_bus_en = dp->wide_bus_supported;
-	dp->catalog->wide_bus_en = dp->wide_bus_supported;
-
 	return rc;
 
 error_ctrl:
@@ -808,6 +804,7 @@ static int dp_display_set_mode(struct msm_dp *dp_display,
 	drm_mode_copy(&dp->panel->dp_mode.drm_mode, &mode->drm_mode);
 	dp->panel->dp_mode.bpp = mode->bpp;
 	dp->panel->dp_mode.capabilities = mode->capabilities;
+	dp->panel->dp_mode.out_fmt_is_yuv_420 = mode->out_fmt_is_yuv_420;
 	dp_panel_init_panel_info(dp->panel);
 	return 0;
 }
@@ -1402,6 +1399,9 @@ bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)
 
 	dp = container_of(dp_display, struct dp_display_private, dp_display);
 
+	if (dp->dp_mode.out_fmt_is_yuv_420)
+		return false;
+
 	return dp->wide_bus_supported;
 }
 
@@ -1615,6 +1615,15 @@ void dp_bridge_mode_set(struct drm_bridge *drm_bridge,
 
 	dp_display->dp_mode.h_active_low =
 		!!(dp_display->dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC);
+
+	dp_display->dp_mode.out_fmt_is_yuv_420 =
+		drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode);
+
+	/* populate wide_bus_support to different layers */
+	dp_display->ctrl->wide_bus_en =
+		dp_display->dp_mode.out_fmt_is_yuv_420 ? false : dp_display->wide_bus_supported;
+	dp_display->catalog->wide_bus_en =
+		dp_display->dp_mode.out_fmt_is_yuv_420 ? false : dp_display->wide_bus_supported;
 }
 
 void dp_bridge_hpd_enable(struct drm_bridge *bridge)
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h
index a0dfc579c5f9f..6ec68be9f2366 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.h
+++ b/drivers/gpu/drm/msm/dp/dp_panel.h
@@ -19,6 +19,7 @@ struct dp_display_mode {
 	u32 bpp;
 	u32 h_active_low;
 	u32 v_active_low;
+	bool out_fmt_is_yuv_420;
 };
 
 struct dp_panel_in {
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 05/17] drm/msm/dp: add an API to indicate if sink supports VSC SDP
  2024-01-25 19:38 [PATCH 00/17] Add support for CDM over DP Paloma Arellano
                   ` (3 preceding siblings ...)
  2024-01-25 19:38 ` [PATCH 04/17] drm/msm/dp: store mode YUV420 information to be used by rest of DP Paloma Arellano
@ 2024-01-25 19:38 ` Paloma Arellano
  2024-01-25 21:23   ` Dmitry Baryshkov
  2024-01-25 19:38 ` [PATCH 06/17] drm/msm/dpu: move widebus logic to its own API Paloma Arellano
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-25 19:38 UTC (permalink / raw)
  To: freedreno
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, quic_abhinavk,
	dri-devel, swboyd, seanpaul, quic_jesszhan, dmitry.baryshkov,
	Paloma Arellano, quic_khsieh

YUV420 format is supported only in the VSC SDP packet and not through
MSA. Hence add an API which indicates the sink support which can be used
by the rest of the DP programming.

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 drivers/gpu/drm/msm/dp/dp_display.c |  3 ++-
 drivers/gpu/drm/msm/dp/dp_panel.c   | 35 +++++++++++++++++++++++++----
 drivers/gpu/drm/msm/dp/dp_panel.h   |  1 +
 3 files changed, 34 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index ddac55f45a722..f6b3b6ca242f8 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1617,7 +1617,8 @@ void dp_bridge_mode_set(struct drm_bridge *drm_bridge,
 		!!(dp_display->dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC);
 
 	dp_display->dp_mode.out_fmt_is_yuv_420 =
-		drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode);
+		drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode) &&
+		dp_panel_vsc_sdp_supported(dp_display->panel);
 
 	/* populate wide_bus_support to different layers */
 	dp_display->ctrl->wide_bus_en =
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c
index 127f6af995cd1..af7820b6d35ec 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
@@ -17,6 +17,9 @@ struct dp_panel_private {
 	struct dp_link *link;
 	struct dp_catalog *catalog;
 	bool panel_on;
+	bool vsc_supported;
+	u8 major;
+	u8 minor;
 };
 
 static void dp_panel_read_psr_cap(struct dp_panel_private *panel)
@@ -43,9 +46,10 @@ static void dp_panel_read_psr_cap(struct dp_panel_private *panel)
 static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
 {
 	int rc;
+	ssize_t rlen;
 	struct dp_panel_private *panel;
 	struct dp_link_info *link_info;
-	u8 *dpcd, major, minor;
+	u8 *dpcd, rx_feature;
 
 	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
 	dpcd = dp_panel->dpcd;
@@ -53,10 +57,19 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
 	if (rc)
 		return rc;
 
+	rlen = drm_dp_dpcd_read(panel->aux, DP_DPRX_FEATURE_ENUMERATION_LIST, &rx_feature, 1);
+	if (rlen != 1) {
+		panel->vsc_supported = false;
+		pr_debug("failed to read DP_DPRX_FEATURE_ENUMERATION_LIST\n");
+	} else {
+		panel->vsc_supported = !!(rx_feature & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED);
+		pr_debug("vsc=%d\n", panel->vsc_supported);
+	}
+
 	link_info = &dp_panel->link_info;
 	link_info->revision = dpcd[DP_DPCD_REV];
-	major = (link_info->revision >> 4) & 0x0f;
-	minor = link_info->revision & 0x0f;
+	panel->major = (link_info->revision >> 4) & 0x0f;
+	panel->minor = link_info->revision & 0x0f;
 
 	link_info->rate = drm_dp_max_link_rate(dpcd);
 	link_info->num_lanes = drm_dp_max_lane_count(dpcd);
@@ -69,7 +82,7 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
 	if (link_info->rate > dp_panel->max_dp_link_rate)
 		link_info->rate = dp_panel->max_dp_link_rate;
 
-	drm_dbg_dp(panel->drm_dev, "version: %d.%d\n", major, minor);
+	drm_dbg_dp(panel->drm_dev, "version: %d.%d\n", panel->major, panel->minor);
 	drm_dbg_dp(panel->drm_dev, "link_rate=%d\n", link_info->rate);
 	drm_dbg_dp(panel->drm_dev, "lane_count=%d\n", link_info->num_lanes);
 
@@ -280,6 +293,20 @@ void dp_panel_tpg_config(struct dp_panel *dp_panel, bool enable)
 	dp_catalog_panel_tpg_enable(catalog, &panel->dp_panel.dp_mode.drm_mode);
 }
 
+bool dp_panel_vsc_sdp_supported(struct dp_panel *dp_panel)
+{
+	struct dp_panel_private *panel;
+
+	if (!dp_panel) {
+		pr_err("invalid input\n");
+		return false;
+	}
+
+	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
+
+	return panel->major >= 1 && panel->minor >= 3 && panel->vsc_supported;
+}
+
 void dp_panel_dump_regs(struct dp_panel *dp_panel)
 {
 	struct dp_catalog *catalog;
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h
index 6ec68be9f2366..590eca5ce304b 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.h
+++ b/drivers/gpu/drm/msm/dp/dp_panel.h
@@ -66,6 +66,7 @@ int dp_panel_get_modes(struct dp_panel *dp_panel,
 		struct drm_connector *connector);
 void dp_panel_handle_sink_request(struct dp_panel *dp_panel);
 void dp_panel_tpg_config(struct dp_panel *dp_panel, bool enable);
+bool dp_panel_vsc_sdp_supported(struct dp_panel *dp_panel);
 
 /**
  * is_link_rate_valid() - validates the link rate
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 06/17] drm/msm/dpu: move widebus logic to its own API
  2024-01-25 19:38 [PATCH 00/17] Add support for CDM over DP Paloma Arellano
                   ` (4 preceding siblings ...)
  2024-01-25 19:38 ` [PATCH 05/17] drm/msm/dp: add an API to indicate if sink supports VSC SDP Paloma Arellano
@ 2024-01-25 19:38 ` Paloma Arellano
  2024-01-25 21:25   ` Dmitry Baryshkov
  2024-01-25 19:38 ` [PATCH 07/17] drm/msm/dpu: disallow widebus en in INTF_CONFIG2 when DP is YUV420 Paloma Arellano
                   ` (10 subsequent siblings)
  16 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-25 19:38 UTC (permalink / raw)
  To: freedreno
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, quic_abhinavk,
	dri-devel, swboyd, seanpaul, quic_jesszhan, dmitry.baryshkov,
	Paloma Arellano, quic_khsieh

Widebus enablement is decided by the interfaces based on their specific
checks and that already happens with DSI/DP specific helpers. Let's
invoke these helpers from dpu_encoder_is_widebus_enabled() to make it
cleaner overall.

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 29 ++++++++++++---------
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h |  4 +++
 2 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 6cef98f046ea6..b0896814c1562 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -225,9 +225,21 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = {
 
 bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc)
 {
-	const struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
+	const struct dpu_encoder_virt *dpu_enc;
+	struct msm_drm_private *priv = drm_enc->dev->dev_private;
+	const struct msm_display_info *disp_info;
+	int index;
+
+	dpu_enc = to_dpu_encoder_virt(drm_enc);
+	disp_info = &dpu_enc->disp_info;
+	index = disp_info->h_tile_instance[0];
 
-	return dpu_enc->wide_bus_en;
+	if (disp_info->intf_type == INTF_DP)
+		return msm_dp_wide_bus_available(priv->dp[index]);
+	else if (disp_info->intf_type == INTF_DSI)
+		return msm_dsi_wide_bus_enabled(priv->dsi[index]);
+
+	return false;
 }
 
 int dpu_encoder_get_crc_values_cnt(const struct drm_encoder *drm_enc)
@@ -1192,26 +1204,17 @@ static void dpu_encoder_virt_atomic_enable(struct drm_encoder *drm_enc,
 	struct dpu_encoder_virt *dpu_enc = NULL;
 	int ret = 0;
 	struct drm_display_mode *cur_mode = NULL;
-	struct msm_drm_private *priv = drm_enc->dev->dev_private;
-	struct msm_display_info *disp_info;
-	int index;
 
 	dpu_enc = to_dpu_encoder_virt(drm_enc);
-	disp_info = &dpu_enc->disp_info;
-	index = disp_info->h_tile_instance[0];
-
 	dpu_enc->dsc = dpu_encoder_get_dsc_config(drm_enc);
 
 	atomic_set(&dpu_enc->frame_done_timeout_cnt, 0);
 
-	if (disp_info->intf_type == INTF_DP)
-		dpu_enc->wide_bus_en = msm_dp_wide_bus_available(priv->dp[index]);
-	else if (disp_info->intf_type == INTF_DSI)
-		dpu_enc->wide_bus_en = msm_dsi_wide_bus_enabled(priv->dsi[index]);
-
 	mutex_lock(&dpu_enc->enc_lock);
 	cur_mode = &dpu_enc->base.crtc->state->adjusted_mode;
 
+	dpu_enc->wide_bus_en = dpu_encoder_is_widebus_enabled(drm_enc);
+
 	trace_dpu_enc_enable(DRMID(drm_enc), cur_mode->hdisplay,
 			     cur_mode->vdisplay);
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index 4c05fd5e9ed18..7b4afa71f1f96 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -156,6 +156,10 @@ int dpu_encoder_get_linecount(struct drm_encoder *drm_enc);
  */
 int dpu_encoder_get_vsync_count(struct drm_encoder *drm_enc);
 
+/**
+ * dpu_encoder_is_widebus_enabled - return bool value if widebus is enabled
+ * @drm_enc:    Pointer to previously created drm encoder structure
+ */
 bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc);
 
 /**
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 07/17] drm/msm/dpu: disallow widebus en in INTF_CONFIG2 when DP is YUV420
  2024-01-25 19:38 [PATCH 00/17] Add support for CDM over DP Paloma Arellano
                   ` (5 preceding siblings ...)
  2024-01-25 19:38 ` [PATCH 06/17] drm/msm/dpu: move widebus logic to its own API Paloma Arellano
@ 2024-01-25 19:38 ` Paloma Arellano
  2024-01-25 21:26   ` Dmitry Baryshkov
  2024-01-25 19:38 ` [PATCH 08/17] drm/msm/dp: change YUV420 related programming for DP Paloma Arellano
                   ` (9 subsequent siblings)
  16 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-25 19:38 UTC (permalink / raw)
  To: freedreno
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, quic_abhinavk,
	dri-devel, swboyd, seanpaul, quic_jesszhan, dmitry.baryshkov,
	Paloma Arellano, quic_khsieh

INTF_CONFIG2 register cannot have widebus enabled when DP format is
YUV420. Therefore, program the INTF to send 1 ppc.

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
index 6bba531d6dc41..bfb93f02fe7c1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
@@ -168,7 +168,9 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
 	 * video timing. It is recommended to enable it for all cases, except
 	 * if compression is enabled in 1 pixel per clock mode
 	 */
-	if (p->wide_bus_en)
+	if (dp_intf && fmt->base.pixel_format == DRM_FORMAT_YUV420)
+		intf_cfg2 |= INTF_CFG2_DATA_HCTL_EN;
+	else if (p->wide_bus_en)
 		intf_cfg2 |= INTF_CFG2_DATABUS_WIDEN | INTF_CFG2_DATA_HCTL_EN;
 
 	data_width = p->width;
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 08/17] drm/msm/dp: change YUV420 related programming for DP
  2024-01-25 19:38 [PATCH 00/17] Add support for CDM over DP Paloma Arellano
                   ` (6 preceding siblings ...)
  2024-01-25 19:38 ` [PATCH 07/17] drm/msm/dpu: disallow widebus en in INTF_CONFIG2 when DP is YUV420 Paloma Arellano
@ 2024-01-25 19:38 ` Paloma Arellano
  2024-01-25 21:29   ` Dmitry Baryshkov
  2024-01-25 19:38 ` [PATCH 09/17] drm/msm/dp: move parity calculation to dp_catalog Paloma Arellano
                   ` (8 subsequent siblings)
  16 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-25 19:38 UTC (permalink / raw)
  To: freedreno
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, quic_abhinavk,
	dri-devel, swboyd, seanpaul, quic_jesszhan, dmitry.baryshkov,
	Paloma Arellano, quic_khsieh

Change all relevant DP controller related programming for YUV420 cases.
Namely, change the pixel clock math to consider YUV420, program the
configuration control to indicate YUV420, as well as modify the MVID
programming to consider YUV420.

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 drivers/gpu/drm/msm/dp/dp_catalog.c |  5 ++++-
 drivers/gpu/drm/msm/dp/dp_catalog.h |  2 +-
 drivers/gpu/drm/msm/dp/dp_ctrl.c    | 12 +++++++++---
 drivers/gpu/drm/msm/dp/dp_display.c |  8 +++++++-
 drivers/gpu/drm/msm/msm_kms.h       |  3 +++
 5 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 5142aeb705a44..5d84c089e520a 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -442,7 +442,7 @@ void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog,
 
 void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog,
 					u32 rate, u32 stream_rate_khz,
-					bool fixed_nvid)
+					bool fixed_nvid, bool is_ycbcr_420)
 {
 	u32 pixel_m, pixel_n;
 	u32 mvid, nvid, pixel_div = 0, dispcc_input_rate;
@@ -485,6 +485,9 @@ void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog,
 		nvid = temp;
 	}
 
+	if (is_ycbcr_420)
+		mvid /= 2;
+
 	if (link_rate_hbr2 == rate)
 		nvid *= 2;
 
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
index 38786e855b51a..6cb5e2a243de2 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -96,7 +96,7 @@ void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog, bool enable);
 void dp_catalog_ctrl_psr_mainlink_enable(struct dp_catalog *dp_catalog, bool enable);
 void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, u32 cc, u32 tb);
 void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 rate,
-				u32 stream_rate_khz, bool fixed_nvid);
+				u32 stream_rate_khz, bool fixed_nvid, bool is_ycbcr_420);
 int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog, u32 pattern);
 u32 dp_catalog_hw_revision(const struct dp_catalog *dp_catalog);
 void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog);
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index 77a8d9366ed7b..209cf2a35642f 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -128,6 +128,9 @@ static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl)
 	/* Default-> LSCLK DIV: 1/4 LCLK  */
 	config |= (2 << DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT);
 
+	if (ctrl->panel->dp_mode.out_fmt_is_yuv_420)
+		config |= DP_CONFIGURATION_CTRL_RGB_YUV; /* YUV420 */
+
 	/* Scrambler reset enable */
 	if (drm_dp_alternate_scrambler_reset_cap(dpcd))
 		config |= DP_CONFIGURATION_CTRL_ASSR;
@@ -957,7 +960,7 @@ static void dp_ctrl_calc_tu_parameters(struct dp_ctrl_private *ctrl,
 	in.hporch = drm_mode->htotal - drm_mode->hdisplay;
 	in.nlanes = ctrl->link->link_params.num_lanes;
 	in.bpp = ctrl->panel->dp_mode.bpp;
-	in.pixel_enc = 444;
+	in.pixel_enc = ctrl->panel->dp_mode.out_fmt_is_yuv_420 ? 420 : 444;
 	in.dsc_en = 0;
 	in.async_en = 0;
 	in.fec_en = 0;
@@ -1763,6 +1766,8 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
 		ctrl->link->link_params.rate = rate;
 		ctrl->link->link_params.num_lanes =
 			ctrl->panel->link_info.num_lanes;
+		if (ctrl->panel->dp_mode.out_fmt_is_yuv_420)
+			pixel_rate >>= 1;
 	}
 
 	drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, pixel_rate=%lu\n",
@@ -1878,7 +1883,7 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train)
 
 	pixel_rate = pixel_rate_orig = ctrl->panel->dp_mode.drm_mode.clock;
 
-	if (dp_ctrl->wide_bus_en)
+	if (dp_ctrl->wide_bus_en || ctrl->panel->dp_mode.out_fmt_is_yuv_420)
 		pixel_rate >>= 1;
 
 	drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, pixel_rate=%lu\n",
@@ -1917,7 +1922,8 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train)
 
 	dp_catalog_ctrl_config_msa(ctrl->catalog,
 		ctrl->link->link_params.rate,
-		pixel_rate_orig, dp_ctrl_use_fixed_nvid(ctrl));
+		pixel_rate_orig, dp_ctrl_use_fixed_nvid(ctrl),
+		ctrl->panel->dp_mode.out_fmt_is_yuv_420);
 
 	dp_ctrl_setup_tr_unit(ctrl);
 
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index f6b3b6ca242f8..6d764f5b08727 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -916,9 +916,10 @@ enum drm_mode_status dp_bridge_mode_valid(struct drm_bridge *bridge,
 	const u32 num_components = 3, default_bpp = 24;
 	struct dp_display_private *dp_display;
 	struct dp_link_info *link_info;
-	u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0;
 	struct msm_dp *dp;
 	int mode_pclk_khz = mode->clock;
+	int rate_ratio = RGB_24BPP_TMDS_CHAR_RATE_RATIO;
+	u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0;
 
 	dp = to_dp_bridge(bridge)->dp_display;
 
@@ -933,6 +934,11 @@ enum drm_mode_status dp_bridge_mode_valid(struct drm_bridge *bridge,
 	dp_display = container_of(dp, struct dp_display_private, dp_display);
 	link_info = &dp_display->panel->link_info;
 
+	if (drm_mode_is_420_only(&dp->connector->display_info, mode))
+		rate_ratio = YUV420_24BPP_TMDS_CHAR_RATE_RATIO;
+
+	mode_pclk_khz /= rate_ratio;
+
 	mode_bpp = dp->connector->display_info.bpc * num_components;
 	if (!mode_bpp)
 		mode_bpp = default_bpp;
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index 44aa435d68ce2..66e8151951807 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -15,6 +15,9 @@
 
 #define MAX_PLANE	4
 
+#define RGB_24BPP_TMDS_CHAR_RATE_RATIO		1
+#define YUV420_24BPP_TMDS_CHAR_RATE_RATIO	2
+
 /* As there are different display controller blocks depending on the
  * snapdragon version, the kms support is split out and the appropriate
  * implementation is loaded at runtime.  The kms module is responsible
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 09/17] drm/msm/dp: move parity calculation to dp_catalog
  2024-01-25 19:38 [PATCH 00/17] Add support for CDM over DP Paloma Arellano
                   ` (7 preceding siblings ...)
  2024-01-25 19:38 ` [PATCH 08/17] drm/msm/dp: change YUV420 related programming for DP Paloma Arellano
@ 2024-01-25 19:38 ` Paloma Arellano
  2024-01-25 21:32   ` Dmitry Baryshkov
  2024-01-25 19:38 ` [PATCH 10/17] drm/msm/dp: modify dp_catalog_hw_revision to show major and minor val Paloma Arellano
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-25 19:38 UTC (permalink / raw)
  To: freedreno
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, quic_abhinavk,
	dri-devel, swboyd, seanpaul, quic_jesszhan, dmitry.baryshkov,
	Paloma Arellano, quic_khsieh

Parity calculation is necessary for VSC SDP implementation, therefore
move it to dp_catalog so it usable by both SDP programming and
dp_audio.c

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 drivers/gpu/drm/msm/dp/dp_audio.c   | 100 ++++------------------------
 drivers/gpu/drm/msm/dp/dp_catalog.h |  72 ++++++++++++++++++++
 2 files changed, 86 insertions(+), 86 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c
index 4a2e479723a85..7aa785018155a 100644
--- a/drivers/gpu/drm/msm/dp/dp_audio.c
+++ b/drivers/gpu/drm/msm/dp/dp_audio.c
@@ -16,13 +16,6 @@
 #include "dp_panel.h"
 #include "dp_display.h"
 
-#define HEADER_BYTE_2_BIT	 0
-#define PARITY_BYTE_2_BIT	 8
-#define HEADER_BYTE_1_BIT	16
-#define PARITY_BYTE_1_BIT	24
-#define HEADER_BYTE_3_BIT	16
-#define PARITY_BYTE_3_BIT	24
-
 struct dp_audio_private {
 	struct platform_device *audio_pdev;
 	struct platform_device *pdev;
@@ -36,71 +29,6 @@ struct dp_audio_private {
 	struct dp_audio dp_audio;
 };
 
-static u8 dp_audio_get_g0_value(u8 data)
-{
-	u8 c[4];
-	u8 g[4];
-	u8 ret_data = 0;
-	u8 i;
-
-	for (i = 0; i < 4; i++)
-		c[i] = (data >> i) & 0x01;
-
-	g[0] = c[3];
-	g[1] = c[0] ^ c[3];
-	g[2] = c[1];
-	g[3] = c[2];
-
-	for (i = 0; i < 4; i++)
-		ret_data = ((g[i] & 0x01) << i) | ret_data;
-
-	return ret_data;
-}
-
-static u8 dp_audio_get_g1_value(u8 data)
-{
-	u8 c[4];
-	u8 g[4];
-	u8 ret_data = 0;
-	u8 i;
-
-	for (i = 0; i < 4; i++)
-		c[i] = (data >> i) & 0x01;
-
-	g[0] = c[0] ^ c[3];
-	g[1] = c[0] ^ c[1] ^ c[3];
-	g[2] = c[1] ^ c[2];
-	g[3] = c[2] ^ c[3];
-
-	for (i = 0; i < 4; i++)
-		ret_data = ((g[i] & 0x01) << i) | ret_data;
-
-	return ret_data;
-}
-
-static u8 dp_audio_calculate_parity(u32 data)
-{
-	u8 x0 = 0;
-	u8 x1 = 0;
-	u8 ci = 0;
-	u8 iData = 0;
-	u8 i = 0;
-	u8 parity_byte;
-	u8 num_byte = (data & 0xFF00) > 0 ? 8 : 2;
-
-	for (i = 0; i < num_byte; i++) {
-		iData = (data >> i*4) & 0xF;
-
-		ci = iData ^ x1;
-		x1 = x0 ^ dp_audio_get_g1_value(ci);
-		x0 = dp_audio_get_g0_value(ci);
-	}
-
-	parity_byte = x1 | (x0 << 4);
-
-	return parity_byte;
-}
-
 static u32 dp_audio_get_header(struct dp_catalog *catalog,
 		enum dp_catalog_audio_sdp_type sdp,
 		enum dp_catalog_audio_header_type header)
@@ -134,7 +62,7 @@ static void dp_audio_stream_sdp(struct dp_audio_private *audio)
 			DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1);
 
 	new_value = 0x02;
-	parity_byte = dp_audio_calculate_parity(new_value);
+	parity_byte = dp_catalog_calculate_parity(new_value);
 	value |= ((new_value << HEADER_BYTE_1_BIT)
 			| (parity_byte << PARITY_BYTE_1_BIT));
 	drm_dbg_dp(audio->drm_dev,
@@ -147,7 +75,7 @@ static void dp_audio_stream_sdp(struct dp_audio_private *audio)
 	value = dp_audio_get_header(catalog,
 			DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2);
 	new_value = value;
-	parity_byte = dp_audio_calculate_parity(new_value);
+	parity_byte = dp_catalog_calculate_parity(new_value);
 	value |= ((new_value << HEADER_BYTE_2_BIT)
 			| (parity_byte << PARITY_BYTE_2_BIT));
 	drm_dbg_dp(audio->drm_dev,
@@ -162,7 +90,7 @@ static void dp_audio_stream_sdp(struct dp_audio_private *audio)
 			DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3);
 
 	new_value = audio->channels - 1;
-	parity_byte = dp_audio_calculate_parity(new_value);
+	parity_byte = dp_catalog_calculate_parity(new_value);
 	value |= ((new_value << HEADER_BYTE_3_BIT)
 			| (parity_byte << PARITY_BYTE_3_BIT));
 	drm_dbg_dp(audio->drm_dev,
@@ -184,7 +112,7 @@ static void dp_audio_timestamp_sdp(struct dp_audio_private *audio)
 			DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1);
 
 	new_value = 0x1;
-	parity_byte = dp_audio_calculate_parity(new_value);
+	parity_byte = dp_catalog_calculate_parity(new_value);
 	value |= ((new_value << HEADER_BYTE_1_BIT)
 			| (parity_byte << PARITY_BYTE_1_BIT));
 	drm_dbg_dp(audio->drm_dev,
@@ -198,7 +126,7 @@ static void dp_audio_timestamp_sdp(struct dp_audio_private *audio)
 			DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2);
 
 	new_value = 0x17;
-	parity_byte = dp_audio_calculate_parity(new_value);
+	parity_byte = dp_catalog_calculate_parity(new_value);
 	value |= ((new_value << HEADER_BYTE_2_BIT)
 			| (parity_byte << PARITY_BYTE_2_BIT));
 	drm_dbg_dp(audio->drm_dev,
@@ -212,7 +140,7 @@ static void dp_audio_timestamp_sdp(struct dp_audio_private *audio)
 			DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3);
 
 	new_value = (0x0 | (0x11 << 2));
-	parity_byte = dp_audio_calculate_parity(new_value);
+	parity_byte = dp_catalog_calculate_parity(new_value);
 	value |= ((new_value << HEADER_BYTE_3_BIT)
 			| (parity_byte << PARITY_BYTE_3_BIT));
 	drm_dbg_dp(audio->drm_dev,
@@ -233,7 +161,7 @@ static void dp_audio_infoframe_sdp(struct dp_audio_private *audio)
 			DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1);
 
 	new_value = 0x84;
-	parity_byte = dp_audio_calculate_parity(new_value);
+	parity_byte = dp_catalog_calculate_parity(new_value);
 	value |= ((new_value << HEADER_BYTE_1_BIT)
 			| (parity_byte << PARITY_BYTE_1_BIT));
 	drm_dbg_dp(audio->drm_dev,
@@ -247,7 +175,7 @@ static void dp_audio_infoframe_sdp(struct dp_audio_private *audio)
 			DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2);
 
 	new_value = 0x1b;
-	parity_byte = dp_audio_calculate_parity(new_value);
+	parity_byte = dp_catalog_calculate_parity(new_value);
 	value |= ((new_value << HEADER_BYTE_2_BIT)
 			| (parity_byte << PARITY_BYTE_2_BIT));
 	drm_dbg_dp(audio->drm_dev,
@@ -261,7 +189,7 @@ static void dp_audio_infoframe_sdp(struct dp_audio_private *audio)
 			DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3);
 
 	new_value = (0x0 | (0x11 << 2));
-	parity_byte = dp_audio_calculate_parity(new_value);
+	parity_byte = dp_catalog_calculate_parity(new_value);
 	value |= ((new_value << HEADER_BYTE_3_BIT)
 			| (parity_byte << PARITY_BYTE_3_BIT));
 	drm_dbg_dp(audio->drm_dev,
@@ -282,7 +210,7 @@ static void dp_audio_copy_management_sdp(struct dp_audio_private *audio)
 			DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1);
 
 	new_value = 0x05;
-	parity_byte = dp_audio_calculate_parity(new_value);
+	parity_byte = dp_catalog_calculate_parity(new_value);
 	value |= ((new_value << HEADER_BYTE_1_BIT)
 			| (parity_byte << PARITY_BYTE_1_BIT));
 	drm_dbg_dp(audio->drm_dev,
@@ -296,7 +224,7 @@ static void dp_audio_copy_management_sdp(struct dp_audio_private *audio)
 			DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2);
 
 	new_value = 0x0F;
-	parity_byte = dp_audio_calculate_parity(new_value);
+	parity_byte = dp_catalog_calculate_parity(new_value);
 	value |= ((new_value << HEADER_BYTE_2_BIT)
 			| (parity_byte << PARITY_BYTE_2_BIT));
 	drm_dbg_dp(audio->drm_dev,
@@ -310,7 +238,7 @@ static void dp_audio_copy_management_sdp(struct dp_audio_private *audio)
 			DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3);
 
 	new_value = 0x0;
-	parity_byte = dp_audio_calculate_parity(new_value);
+	parity_byte = dp_catalog_calculate_parity(new_value);
 	value |= ((new_value << HEADER_BYTE_3_BIT)
 			| (parity_byte << PARITY_BYTE_3_BIT));
 	drm_dbg_dp(audio->drm_dev,
@@ -331,7 +259,7 @@ static void dp_audio_isrc_sdp(struct dp_audio_private *audio)
 			DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1);
 
 	new_value = 0x06;
-	parity_byte = dp_audio_calculate_parity(new_value);
+	parity_byte = dp_catalog_calculate_parity(new_value);
 	value |= ((new_value << HEADER_BYTE_1_BIT)
 			| (parity_byte << PARITY_BYTE_1_BIT));
 	drm_dbg_dp(audio->drm_dev,
@@ -345,7 +273,7 @@ static void dp_audio_isrc_sdp(struct dp_audio_private *audio)
 			DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2);
 
 	new_value = 0x0F;
-	parity_byte = dp_audio_calculate_parity(new_value);
+	parity_byte = dp_catalog_calculate_parity(new_value);
 	value |= ((new_value << HEADER_BYTE_2_BIT)
 			| (parity_byte << PARITY_BYTE_2_BIT));
 	drm_dbg_dp(audio->drm_dev,
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
index 6cb5e2a243de2..563903605b3a7 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -45,6 +45,13 @@ enum dp_phy_aux_config_type {
 	PHY_AUX_CFG_MAX,
 };
 
+#define HEADER_BYTE_2_BIT	 0
+#define PARITY_BYTE_2_BIT	 8
+#define HEADER_BYTE_1_BIT	16
+#define PARITY_BYTE_1_BIT	24
+#define HEADER_BYTE_3_BIT	16
+#define PARITY_BYTE_3_BIT	24
+
 enum dp_catalog_audio_sdp_type {
 	DP_AUDIO_SDP_STREAM,
 	DP_AUDIO_SDP_TIMESTAMP,
@@ -73,6 +80,71 @@ struct dp_catalog {
 	bool wide_bus_en;
 };
 
+static inline u8 dp_catalog_get_g0_value(u8 data)
+{
+	u8 c[4];
+	u8 g[4];
+	u8 ret_data = 0;
+	u8 i;
+
+	for (i = 0; i < 4; i++)
+		c[i] = (data >> i) & 0x01;
+
+	g[0] = c[3];
+	g[1] = c[0] ^ c[3];
+	g[2] = c[1];
+	g[3] = c[2];
+
+	for (i = 0; i < 4; i++)
+		ret_data = ((g[i] & 0x01) << i) | ret_data;
+
+	return ret_data;
+}
+
+static inline u8 dp_catalog_get_g1_value(u8 data)
+{
+	u8 c[4];
+	u8 g[4];
+	u8 ret_data = 0;
+	u8 i;
+
+	for (i = 0; i < 4; i++)
+		c[i] = (data >> i) & 0x01;
+
+	g[0] = c[0] ^ c[3];
+	g[1] = c[0] ^ c[1] ^ c[3];
+	g[2] = c[1] ^ c[2];
+	g[3] = c[2] ^ c[3];
+
+	for (i = 0; i < 4; i++)
+		ret_data = ((g[i] & 0x01) << i) | ret_data;
+
+	return ret_data;
+}
+
+static inline u8 dp_catalog_calculate_parity(u32 data)
+{
+	u8 x0 = 0;
+	u8 x1 = 0;
+	u8 ci = 0;
+	u8 iData = 0;
+	u8 i = 0;
+	u8 parity_byte;
+	u8 num_byte = (data & 0xFF00) > 0 ? 8 : 2;
+
+	for (i = 0; i < num_byte; i++) {
+		iData = (data >> i * 4) & 0xF;
+
+		ci = iData ^ x1;
+		x1 = x0 ^ dp_catalog_get_g1_value(ci);
+		x0 = dp_catalog_get_g0_value(ci);
+	}
+
+	parity_byte = x1 | (x0 << 4);
+
+	return parity_byte;
+}
+
 /* Debug module */
 void dp_catalog_snapshot(struct dp_catalog *dp_catalog, struct msm_disp_state *disp_state);
 
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 10/17] drm/msm/dp: modify dp_catalog_hw_revision to show major and minor val
  2024-01-25 19:38 [PATCH 00/17] Add support for CDM over DP Paloma Arellano
                   ` (8 preceding siblings ...)
  2024-01-25 19:38 ` [PATCH 09/17] drm/msm/dp: move parity calculation to dp_catalog Paloma Arellano
@ 2024-01-25 19:38 ` Paloma Arellano
  2024-01-25 22:07   ` Dmitry Baryshkov
                     ` (2 more replies)
  2024-01-25 19:38 ` [PATCH 11/17] drm/msm/dp: add VSC SDP support for YUV420 over DP Paloma Arellano
                   ` (6 subsequent siblings)
  16 siblings, 3 replies; 95+ messages in thread
From: Paloma Arellano @ 2024-01-25 19:38 UTC (permalink / raw)
  To: freedreno
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, quic_abhinavk,
	dri-devel, swboyd, seanpaul, quic_jesszhan, dmitry.baryshkov,
	Paloma Arellano, quic_khsieh

Modify dp_catalog_hw_revision to make the major and minor version values
known instead of outputting the entire hex value of the hardware version
register in preparation of using it for VSC SDP programming.

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 drivers/gpu/drm/msm/dp/dp_catalog.c | 12 +++++++++---
 drivers/gpu/drm/msm/dp/dp_catalog.h |  2 +-
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 5d84c089e520a..c025786170ba5 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -24,6 +24,9 @@
 #define DP_INTERRUPT_STATUS_ACK_SHIFT	1
 #define DP_INTERRUPT_STATUS_MASK_SHIFT	2
 
+#define DP_HW_VERSION_MAJOR(reg)	FIELD_GET(GENMASK(31, 28), reg)
+#define DP_HW_VERSION_MINOR(reg)	FIELD_GET(GENMASK(27, 16), reg)
+
 #define DP_INTF_CONFIG_DATABUS_WIDEN     BIT(4)
 
 #define DP_INTERRUPT_STATUS1 \
@@ -531,15 +534,18 @@ int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog,
  *
  * @dp_catalog: DP catalog structure
  *
- * Return: DP controller hw revision
+ * Return: void
  *
  */
-u32 dp_catalog_hw_revision(const struct dp_catalog *dp_catalog)
+void dp_catalog_hw_revision(const struct dp_catalog *dp_catalog, u16 *major, u16 *minor)
 {
 	const struct dp_catalog_private *catalog = container_of(dp_catalog,
 				struct dp_catalog_private, dp_catalog);
+	u32 reg_dp_hw_version;
 
-	return dp_read_ahb(catalog, REG_DP_HW_VERSION);
+	reg_dp_hw_version = dp_read_ahb(catalog, REG_DP_HW_VERSION);
+	*major = DP_HW_VERSION_MAJOR(reg_dp_hw_version);
+	*minor = DP_HW_VERSION_MINOR(reg_dp_hw_version);
 }
 
 /**
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
index 563903605b3a7..94c377ef90c35 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -170,7 +170,7 @@ void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, u32 cc, u32 tb);
 void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 rate,
 				u32 stream_rate_khz, bool fixed_nvid, bool is_ycbcr_420);
 int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog, u32 pattern);
-u32 dp_catalog_hw_revision(const struct dp_catalog *dp_catalog);
+void dp_catalog_hw_revision(const struct dp_catalog *dp_catalog, u16 *major, u16 *minor);
 void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog);
 bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog *dp_catalog);
 void dp_catalog_ctrl_enable_irq(struct dp_catalog *dp_catalog, bool enable);
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 11/17] drm/msm/dp: add VSC SDP support for YUV420 over DP
  2024-01-25 19:38 [PATCH 00/17] Add support for CDM over DP Paloma Arellano
                   ` (9 preceding siblings ...)
  2024-01-25 19:38 ` [PATCH 10/17] drm/msm/dp: modify dp_catalog_hw_revision to show major and minor val Paloma Arellano
@ 2024-01-25 19:38 ` Paloma Arellano
  2024-01-25 21:48   ` Dmitry Baryshkov
  2024-01-25 19:38 ` [PATCH 12/17] drm/msm/dpu: add support of new peripheral flush mechanism Paloma Arellano
                   ` (5 subsequent siblings)
  16 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-25 19:38 UTC (permalink / raw)
  To: freedreno
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, quic_abhinavk,
	dri-devel, swboyd, seanpaul, quic_jesszhan, dmitry.baryshkov,
	Paloma Arellano, quic_khsieh

Add support to pack and send the VSC SDP packet for DP. This therefore
allows the transmision of format information to the sinks which is
needed for YUV420 support over DP.

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 drivers/gpu/drm/msm/dp/dp_catalog.c | 147 ++++++++++++++++++++++++++++
 drivers/gpu/drm/msm/dp/dp_catalog.h |   4 +
 drivers/gpu/drm/msm/dp/dp_ctrl.c    |   4 +
 drivers/gpu/drm/msm/dp/dp_panel.c   |  47 +++++++++
 drivers/gpu/drm/msm/dp/dp_reg.h     |   3 +
 5 files changed, 205 insertions(+)

diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
index c025786170ba5..7e4c68be23e56 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -29,6 +29,9 @@
 
 #define DP_INTF_CONFIG_DATABUS_WIDEN     BIT(4)
 
+#define DP_GENERIC0_6_YUV_8_BPC		BIT(0)
+#define DP_GENERIC0_6_YUV_10_BPC	BIT(1)
+
 #define DP_INTERRUPT_STATUS1 \
 	(DP_INTR_AUX_XFER_DONE| \
 	DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \
@@ -907,6 +910,150 @@ int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog)
 	return 0;
 }
 
+static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog *dp_catalog)
+{
+	struct dp_catalog_private *catalog;
+	u32 header, parity, data;
+	u8 bpc, off = 0;
+	u8 buf[SZ_128];
+
+	if (!dp_catalog) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
+
+	/* HEADER BYTE 1 */
+	header = dp_catalog->sdp.sdp_header.HB1;
+	parity = dp_catalog_calculate_parity(header);
+	data   = ((header << HEADER_BYTE_1_BIT) | (parity << PARITY_BYTE_1_BIT));
+	dp_write_link(catalog, MMSS_DP_GENERIC0_0, data);
+	memcpy(buf + off, &data, sizeof(data));
+	off += sizeof(data);
+
+	/* HEADER BYTE 2 */
+	header = dp_catalog->sdp.sdp_header.HB2;
+	parity = dp_catalog_calculate_parity(header);
+	data   = ((header << HEADER_BYTE_2_BIT) | (parity << PARITY_BYTE_2_BIT));
+	dp_write_link(catalog, MMSS_DP_GENERIC0_1, data);
+
+	/* HEADER BYTE 3 */
+	header = dp_catalog->sdp.sdp_header.HB3;
+	parity = dp_catalog_calculate_parity(header);
+	data   = ((header << HEADER_BYTE_3_BIT) | (parity << PARITY_BYTE_3_BIT));
+	data |= dp_read_link(catalog, MMSS_DP_GENERIC0_1);
+	dp_write_link(catalog, MMSS_DP_GENERIC0_1, data);
+	memcpy(buf + off, &data, sizeof(data));
+	off += sizeof(data);
+
+	data = 0;
+	dp_write_link(catalog, MMSS_DP_GENERIC0_2, data);
+	memcpy(buf + off, &data, sizeof(data));
+	off += sizeof(data);
+
+	dp_write_link(catalog, MMSS_DP_GENERIC0_3, data);
+	memcpy(buf + off, &data, sizeof(data));
+	off += sizeof(data);
+
+	dp_write_link(catalog, MMSS_DP_GENERIC0_4, data);
+	memcpy(buf + off, &data, sizeof(data));
+	off += sizeof(data);
+
+	dp_write_link(catalog, MMSS_DP_GENERIC0_5, data);
+	memcpy(buf + off, &data, sizeof(data));
+	off += sizeof(data);
+
+	switch (dp_catalog->vsc_sdp_data.bpc) {
+	case 10:
+		bpc = DP_GENERIC0_6_YUV_10_BPC;
+		break;
+	case 8:
+	default:
+		bpc = DP_GENERIC0_6_YUV_8_BPC;
+		break;
+	}
+
+	/* VSC SDP payload as per table 2-117 of DP 1.4 specification */
+	data = (dp_catalog->vsc_sdp_data.colorimetry & 0xF) |
+	       ((dp_catalog->vsc_sdp_data.pixelformat & 0xF) << 4) |
+	       (bpc << 8) |
+	       ((dp_catalog->vsc_sdp_data.dynamic_range & 0x1) << 15) |
+	       ((dp_catalog->vsc_sdp_data.content_type & 0x7) << 16);
+
+	dp_write_link(catalog, MMSS_DP_GENERIC0_6, data);
+	memcpy(buf + off, &data, sizeof(data));
+	off += sizeof(data);
+
+	data = 0;
+	dp_write_link(catalog, MMSS_DP_GENERIC0_7, data);
+	memcpy(buf + off, &data, sizeof(data));
+	off += sizeof(data);
+
+	dp_write_link(catalog, MMSS_DP_GENERIC0_8, data);
+	memcpy(buf + off, &data, sizeof(data));
+	off += sizeof(data);
+
+	dp_write_link(catalog, MMSS_DP_GENERIC0_9, data);
+	memcpy(buf + off, &data, sizeof(data));
+	off += sizeof(data);
+
+	print_hex_dump(KERN_DEBUG, "[drm-dp] VSC: ", DUMP_PREFIX_NONE, 16, 4, buf, off, false);
+}
+
+void dp_catalog_panel_config_vsc_sdp(struct dp_catalog *dp_catalog, bool en)
+{
+	struct dp_catalog_private *catalog;
+	u32 cfg, cfg2, misc;
+	u16 major = 0, minor = 0;
+
+	if (!dp_catalog) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
+
+	cfg = dp_read_link(catalog, MMSS_DP_SDP_CFG);
+	cfg2 = dp_read_link(catalog, MMSS_DP_SDP_CFG2);
+	misc = dp_read_link(catalog, REG_DP_MISC1_MISC0);
+
+	if (en) {
+		cfg |= GEN0_SDP_EN;
+		dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
+
+		cfg2 |= GENERIC0_SDPSIZE;
+		dp_write_link(catalog, MMSS_DP_SDP_CFG2, cfg2);
+
+		dp_catalog_panel_setup_vsc_sdp(dp_catalog);
+
+		/* indicates presence of VSC (BIT(6) of MISC1) */
+		misc |= DP_MISC1_VSC_SDP;
+
+		drm_dbg_dp(catalog->drm_dev, "vsc sdp enable=%d\n", en);
+	} else {
+		cfg &= ~GEN0_SDP_EN;
+		dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
+
+		cfg2 &= ~GENERIC0_SDPSIZE;
+		dp_write_link(catalog, MMSS_DP_SDP_CFG2, cfg2);
+
+		/* switch back to MSA */
+		misc &= ~DP_MISC1_VSC_SDP;
+
+		drm_dbg_dp(catalog->drm_dev, "vsc sdp enable=%d\n", en);
+	}
+
+	pr_debug("misc settings = 0x%x\n", misc);
+	dp_write_link(catalog, REG_DP_MISC1_MISC0, misc);
+
+	dp_catalog_hw_revision(dp_catalog, &major, &minor);
+	if (major == 1 && minor < 2) {
+		dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x01);
+		dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x00);
+	}
+}
+
 void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog,
 				struct drm_display_mode *drm_mode)
 {
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
index 94c377ef90c35..6b757249c0698 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -7,6 +7,7 @@
 #define _DP_CATALOG_H_
 
 #include <drm/drm_modes.h>
+#include <drm/display/drm_dp_helper.h>
 
 #include "dp_parser.h"
 #include "disp/msm_disp_snapshot.h"
@@ -76,6 +77,8 @@ struct dp_catalog {
 	u32 dp_active;
 	enum dp_catalog_audio_sdp_type sdp_type;
 	enum dp_catalog_audio_header_type sdp_header;
+	struct dp_sdp sdp;
+	struct drm_dp_vsc_sdp vsc_sdp_data;
 	u32 audio_data;
 	bool wide_bus_en;
 };
@@ -196,6 +199,7 @@ u32 dp_catalog_ctrl_read_phy_pattern(struct dp_catalog *dp_catalog);
 
 /* DP Panel APIs */
 int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog);
+void dp_catalog_panel_config_vsc_sdp(struct dp_catalog *dp_catalog, bool en);
 void dp_catalog_dump_regs(struct dp_catalog *dp_catalog);
 void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog,
 				struct drm_display_mode *drm_mode);
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index 209cf2a35642f..ddd92a63d5a67 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -1952,6 +1952,8 @@ int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl)
 	dp_io = &ctrl->parser->io;
 	phy = dp_io->phy;
 
+	dp_catalog_panel_config_vsc_sdp(ctrl->catalog, false);
+
 	/* set dongle to D3 (power off) mode */
 	dp_link_psm_config(ctrl->link, &ctrl->panel->link_info, true);
 
@@ -2026,6 +2028,8 @@ int dp_ctrl_off(struct dp_ctrl *dp_ctrl)
 	dp_io = &ctrl->parser->io;
 	phy = dp_io->phy;
 
+	dp_catalog_panel_config_vsc_sdp(ctrl->catalog, false);
+
 	dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);
 
 	dp_catalog_ctrl_reset(ctrl->catalog);
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c
index af7820b6d35ec..d6af9898b00d8 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
@@ -307,6 +307,49 @@ bool dp_panel_vsc_sdp_supported(struct dp_panel *dp_panel)
 	return panel->major >= 1 && panel->minor >= 3 && panel->vsc_supported;
 }
 
+static int dp_panel_setup_vsc_sdp(struct dp_panel *dp_panel)
+{
+	struct dp_catalog *catalog;
+	struct dp_panel_private *panel;
+	struct dp_display_mode *dp_mode;
+	int rc = 0;
+
+	if (!dp_panel) {
+		pr_err("invalid input\n");
+		rc = -EINVAL;
+		return rc;
+	}
+
+	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
+	catalog = panel->catalog;
+	dp_mode = &dp_panel->dp_mode;
+
+	memset(&catalog->sdp, 0, sizeof(catalog->sdp));
+	memset(&catalog->vsc_sdp_data, 0, sizeof(catalog->vsc_sdp_data));
+
+	/* VSC SDP header as per table 2-118 of DP 1.4 specification */
+	catalog->sdp.sdp_header.HB0 = 0x00;
+	catalog->sdp.sdp_header.HB1 = 0x07;
+	catalog->sdp.sdp_header.HB2 = 0x05;
+	catalog->sdp.sdp_header.HB3 = 0x13;
+
+	/* VSC SDP Payload for DB16 */
+	catalog->vsc_sdp_data.pixelformat = DP_PIXELFORMAT_YUV420;
+	catalog->vsc_sdp_data.colorimetry = DP_COLORIMETRY_DEFAULT;
+
+	/* VSC SDP Payload for DB17 */
+	catalog->vsc_sdp_data.dynamic_range = DP_DYNAMIC_RANGE_CTA;
+
+	/* VSC SDP Payload for DB18 */
+	catalog->vsc_sdp_data.content_type = DP_CONTENT_TYPE_GRAPHICS;
+
+	catalog->vsc_sdp_data.bpc = dp_mode->bpp / 3;
+
+	dp_catalog_panel_config_vsc_sdp(catalog, true);
+
+	return rc;
+}
+
 void dp_panel_dump_regs(struct dp_panel *dp_panel)
 {
 	struct dp_catalog *catalog;
@@ -370,6 +413,10 @@ int dp_panel_timing_cfg(struct dp_panel *dp_panel)
 	catalog->dp_active = data;
 
 	dp_catalog_panel_timing_cfg(catalog);
+
+	if (dp_panel->dp_mode.out_fmt_is_yuv_420)
+		dp_panel_setup_vsc_sdp(dp_panel);
+
 	panel->panel_on = true;
 
 	return 0;
diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h
index ea85a691e72b5..756ddf85b1e81 100644
--- a/drivers/gpu/drm/msm/dp/dp_reg.h
+++ b/drivers/gpu/drm/msm/dp/dp_reg.h
@@ -142,6 +142,7 @@
 #define DP_MISC0_SYNCHRONOUS_CLK		(0x00000001)
 #define DP_MISC0_COLORIMETRY_CFG_SHIFT		(0x00000001)
 #define DP_MISC0_TEST_BITS_DEPTH_SHIFT		(0x00000005)
+#define DP_MISC1_VSC_SDP			(0x00004000)
 
 #define REG_DP_VALID_BOUNDARY			(0x00000030)
 #define REG_DP_VALID_BOUNDARY_2			(0x00000034)
@@ -201,9 +202,11 @@
 #define MMSS_DP_AUDIO_CTRL_RESET		(0x00000214)
 
 #define MMSS_DP_SDP_CFG				(0x00000228)
+#define GEN0_SDP_EN				(0x00020000)
 #define MMSS_DP_SDP_CFG2			(0x0000022C)
 #define MMSS_DP_AUDIO_TIMESTAMP_0		(0x00000230)
 #define MMSS_DP_AUDIO_TIMESTAMP_1		(0x00000234)
+#define GENERIC0_SDPSIZE			(0x00010000)
 
 #define MMSS_DP_AUDIO_STREAM_0			(0x00000240)
 #define MMSS_DP_AUDIO_STREAM_1			(0x00000244)
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 12/17] drm/msm/dpu: add support of new peripheral flush mechanism
  2024-01-25 19:38 [PATCH 00/17] Add support for CDM over DP Paloma Arellano
                   ` (10 preceding siblings ...)
  2024-01-25 19:38 ` [PATCH 11/17] drm/msm/dp: add VSC SDP support for YUV420 over DP Paloma Arellano
@ 2024-01-25 19:38 ` Paloma Arellano
  2024-01-25 21:49   ` Dmitry Baryshkov
  2024-01-25 19:38 ` [PATCH 13/17] drm/msm/dp: enable SDP and SDE periph flush update Paloma Arellano
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-25 19:38 UTC (permalink / raw)
  To: freedreno
  Cc: neil.armstrong, linux-arm-msm, Paloma Arellano, quic_abhinavk,
	dri-devel, swboyd, seanpaul, marijn.suijten, dmitry.baryshkov,
	quic_jesszhan, Kuogee Hsieh

From: Kuogee Hsieh <quic_khsieh@quicinc.com>

Introduce a peripheral flushing mechanism to decouple peripheral
metadata flushing from timing engine related flush.

Signed-off-by: Kuogee Hsieh <quic_khsieh@quicinc.com>
Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c    |  3 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c      | 17 +++++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h      | 10 ++++++++++
 3 files changed, 30 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index d0f56c5c4cce9..e284bf448bdda 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -437,6 +437,9 @@ static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc)
 	if (ctl->ops.update_pending_flush_merge_3d && phys_enc->hw_pp->merge_3d)
 		ctl->ops.update_pending_flush_merge_3d(ctl, phys_enc->hw_pp->merge_3d->idx);
 
+	if (ctl->ops.update_pending_flush_periph && phys_enc->hw_intf->cap->type == INTF_DP)
+		ctl->ops.update_pending_flush_periph(ctl, phys_enc->hw_intf->idx);
+
 skip_flush:
 	DPU_DEBUG_VIDENC(phys_enc,
 		"update pending flush ctl %d intf %d\n",
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
index e76565c3e6a43..bf45afeb616d3 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -39,6 +39,7 @@
 #define   CTL_WB_FLUSH                  0x108
 #define   CTL_INTF_FLUSH                0x110
 #define   CTL_CDM_FLUSH                0x114
+#define   CTL_PERIPH_FLUSH              0x128
 #define   CTL_INTF_MASTER               0x134
 #define   CTL_DSPP_n_FLUSH(n)           ((0x13C) + ((n) * 4))
 
@@ -49,6 +50,7 @@
 #define  MERGE_3D_IDX   23
 #define  DSC_IDX        22
 #define CDM_IDX         26
+#define  PERIPH_IDX     30
 #define  INTF_IDX       31
 #define WB_IDX          16
 #define  DSPP_IDX       29  /* From DPU hw rev 7.x.x */
@@ -151,6 +153,10 @@ static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
 				ctx->pending_dspp_flush_mask[dspp - DSPP_0]);
 		}
 
+	if (ctx->pending_flush_mask & BIT(PERIPH_IDX))
+		DPU_REG_WRITE(&ctx->hw, CTL_PERIPH_FLUSH,
+			      ctx->pending_periph_flush_mask);
+
 	if (ctx->pending_flush_mask & BIT(DSC_IDX))
 		DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH,
 			      ctx->pending_dsc_flush_mask);
@@ -311,6 +317,13 @@ static void dpu_hw_ctl_update_pending_flush_intf_v1(struct dpu_hw_ctl *ctx,
 	ctx->pending_flush_mask |= BIT(INTF_IDX);
 }
 
+static void dpu_hw_ctl_update_pending_flush_periph(struct dpu_hw_ctl *ctx,
+		enum dpu_intf intf)
+{
+	ctx->pending_periph_flush_mask |= BIT(intf - INTF_0);
+	ctx->pending_flush_mask |= BIT(PERIPH_IDX);
+}
+
 static void dpu_hw_ctl_update_pending_flush_merge_3d_v1(struct dpu_hw_ctl *ctx,
 		enum dpu_merge_3d merge_3d)
 {
@@ -680,6 +693,10 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
 		ops->reset_intf_cfg = dpu_hw_ctl_reset_intf_cfg_v1;
 		ops->update_pending_flush_intf =
 			dpu_hw_ctl_update_pending_flush_intf_v1;
+
+		ops->update_pending_flush_periph =
+			dpu_hw_ctl_update_pending_flush_periph;
+
 		ops->update_pending_flush_merge_3d =
 			dpu_hw_ctl_update_pending_flush_merge_3d_v1;
 		ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb_v1;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
index ff85b5ee0acf8..5d86c560b6d3f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -122,6 +122,15 @@ struct dpu_hw_ctl_ops {
 	void (*update_pending_flush_intf)(struct dpu_hw_ctl *ctx,
 		enum dpu_intf blk);
 
+	/**
+	 * OR in the given flushbits to the cached pending_(periph_)flush_mask
+	 * No effect on hardware
+	 * @ctx       : ctl path ctx pointer
+	 * @blk       : interface block index
+	 */
+	void (*update_pending_flush_periph)(struct dpu_hw_ctl *ctx,
+		enum dpu_intf blk);
+
 	/**
 	 * OR in the given flushbits to the cached pending_(merge_3d_)flush_mask
 	 * No effect on hardware
@@ -264,6 +273,7 @@ struct dpu_hw_ctl {
 	u32 pending_flush_mask;
 	u32 pending_intf_flush_mask;
 	u32 pending_wb_flush_mask;
+	u32 pending_periph_flush_mask;
 	u32 pending_merge_3d_flush_mask;
 	u32 pending_dspp_flush_mask[DSPP_MAX - DSPP_0];
 	u32 pending_dsc_flush_mask;
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 13/17] drm/msm/dp: enable SDP and SDE periph flush update
  2024-01-25 19:38 [PATCH 00/17] Add support for CDM over DP Paloma Arellano
                   ` (11 preceding siblings ...)
  2024-01-25 19:38 ` [PATCH 12/17] drm/msm/dpu: add support of new peripheral flush mechanism Paloma Arellano
@ 2024-01-25 19:38 ` Paloma Arellano
  2024-01-25 21:50   ` Dmitry Baryshkov
  2024-01-25 19:38 ` [PATCH 14/17] drm/msm/dpu: modify encoder programming for CDM over DP Paloma Arellano
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-25 19:38 UTC (permalink / raw)
  To: freedreno
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, quic_abhinavk,
	dri-devel, swboyd, seanpaul, quic_jesszhan, dmitry.baryshkov,
	Paloma Arellano, quic_khsieh

DP controller can be setup to operate in either SDP update flush mode or
peripheral flush mode based on the DP controller hardware version.

Starting in DP v1.2, the hardware documents require the use of
peripheral flush mode for SDP packets such as PPS OR VSC SDP packets.

In-line with this guidance, lets program the DP controller to use
peripheral flush mode starting DP v1.2

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 drivers/gpu/drm/msm/dp/dp_catalog.c | 18 ++++++++++++++++++
 drivers/gpu/drm/msm/dp/dp_catalog.h |  1 +
 drivers/gpu/drm/msm/dp/dp_ctrl.c    |  1 +
 drivers/gpu/drm/msm/dp/dp_reg.h     |  2 ++
 4 files changed, 22 insertions(+)

diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 7e4c68be23e56..b43083b9c2df6 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -446,6 +446,24 @@ void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog,
 	dp_write_link(catalog, REG_DP_MISC1_MISC0, misc_val);
 }
 
+void dp_catalog_setup_peripheral_flush(struct dp_catalog *dp_catalog)
+{
+	u32 mainlink_ctrl;
+	u16 major = 0, minor = 0;
+	struct dp_catalog_private *catalog = container_of(dp_catalog,
+				struct dp_catalog_private, dp_catalog);
+
+	mainlink_ctrl = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
+
+	dp_catalog_hw_revision(dp_catalog, &major, &minor);
+	if (major >= 1 && minor >= 2)
+		mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE;
+	else
+		mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_UPDATE_SDP;
+
+	dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
+}
+
 void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog,
 					u32 rate, u32 stream_rate_khz,
 					bool fixed_nvid, bool is_ycbcr_420)
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
index 6b757249c0698..1d57988aa6689 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -169,6 +169,7 @@ void dp_catalog_ctrl_config_ctrl(struct dp_catalog *dp_catalog, u32 config);
 void dp_catalog_ctrl_lane_mapping(struct dp_catalog *dp_catalog);
 void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog, bool enable);
 void dp_catalog_ctrl_psr_mainlink_enable(struct dp_catalog *dp_catalog, bool enable);
+void dp_catalog_setup_peripheral_flush(struct dp_catalog *dp_catalog);
 void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, u32 cc, u32 tb);
 void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 rate,
 				u32 stream_rate_khz, bool fixed_nvid, bool is_ycbcr_420);
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index ddd92a63d5a67..c375b36f53ce1 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -170,6 +170,7 @@ static void dp_ctrl_configure_source_params(struct dp_ctrl_private *ctrl)
 
 	dp_catalog_ctrl_lane_mapping(ctrl->catalog);
 	dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true);
+	dp_catalog_setup_peripheral_flush(ctrl->catalog);
 
 	dp_ctrl_config_ctrl(ctrl);
 
diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h
index 756ddf85b1e81..05a1009d2f678 100644
--- a/drivers/gpu/drm/msm/dp/dp_reg.h
+++ b/drivers/gpu/drm/msm/dp/dp_reg.h
@@ -102,6 +102,8 @@
 #define DP_MAINLINK_CTRL_ENABLE			(0x00000001)
 #define DP_MAINLINK_CTRL_RESET			(0x00000002)
 #define DP_MAINLINK_CTRL_SW_BYPASS_SCRAMBLER	(0x00000010)
+#define DP_MAINLINK_FLUSH_MODE_UPDATE_SDP	(0x00800000)
+#define DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE	(0x01800000)
 #define DP_MAINLINK_FB_BOUNDARY_SEL		(0x02000000)
 
 #define REG_DP_STATE_CTRL			(0x00000004)
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 14/17] drm/msm/dpu: modify encoder programming for CDM over DP
  2024-01-25 19:38 [PATCH 00/17] Add support for CDM over DP Paloma Arellano
                   ` (12 preceding siblings ...)
  2024-01-25 19:38 ` [PATCH 13/17] drm/msm/dp: enable SDP and SDE periph flush update Paloma Arellano
@ 2024-01-25 19:38 ` Paloma Arellano
  2024-01-25 21:57   ` Dmitry Baryshkov
  2024-01-25 19:38 ` [PATCH 15/17] drm/msm/dpu: allow certain formats for CDM for DP Paloma Arellano
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-25 19:38 UTC (permalink / raw)
  To: freedreno
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, quic_abhinavk,
	dri-devel, swboyd, seanpaul, quic_jesszhan, dmitry.baryshkov,
	Paloma Arellano, quic_khsieh

Adjust the encoder format programming in the case of video mode for DP
to accommodate CDM related changes.

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 16 +++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |  8 +++++
 .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 35 ++++++++++++++++---
 drivers/gpu/drm/msm/dp/dp_display.c           | 12 +++++++
 drivers/gpu/drm/msm/msm_drv.h                 |  9 ++++-
 5 files changed, 75 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index b0896814c1562..99ec53446ad21 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -222,6 +222,22 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = {
 	15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10
 };
 
+u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc, const struct drm_display_mode *mode)
+{
+	const struct dpu_encoder_virt *dpu_enc;
+	const struct msm_display_info *disp_info;
+	struct msm_drm_private *priv;
+
+	dpu_enc = to_dpu_encoder_virt(drm_enc);
+	disp_info = &dpu_enc->disp_info;
+	priv = drm_enc->dev->dev_private;
+
+	if (disp_info->intf_type == INTF_DP &&
+	    msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]], mode))
+		return DRM_FORMAT_YUV420;
+
+	return DRM_FORMAT_RGB888;
+}
 
 bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc)
 {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index 7b4afa71f1f96..62255d0aa4487 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -162,6 +162,14 @@ int dpu_encoder_get_vsync_count(struct drm_encoder *drm_enc);
  */
 bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc);
 
+/**
+ * dpu_encoder_get_drm_fmt - return DRM fourcc format
+ * @drm_enc:    Pointer to previously created drm encoder structure
+ * @mode:	Corresponding drm_display_mode for dpu encoder
+ */
+u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
+			    const struct drm_display_mode *mode);
+
 /**
  * dpu_encoder_get_crc_values_cnt - get number of physical encoders contained
  *	in virtual encoder that can collect CRC values
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index e284bf448bdda..a1dde0ff35dc8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -234,6 +234,7 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
 {
 	struct drm_display_mode mode;
 	struct dpu_hw_intf_timing_params timing_params = { 0 };
+	struct dpu_hw_cdm *hw_cdm;
 	const struct dpu_format *fmt = NULL;
 	u32 fmt_fourcc = DRM_FORMAT_RGB888;
 	unsigned long lock_flags;
@@ -254,17 +255,26 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
 	DPU_DEBUG_VIDENC(phys_enc, "enabling mode:\n");
 	drm_mode_debug_printmodeline(&mode);
 
-	if (phys_enc->split_role != ENC_ROLE_SOLO) {
+	hw_cdm = phys_enc->hw_cdm;
+	if (hw_cdm) {
+		intf_cfg.cdm = hw_cdm->idx;
+		fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent, &mode);
+	}
+
+	if (phys_enc->split_role != ENC_ROLE_SOLO ||
+	    dpu_encoder_get_drm_fmt(phys_enc->parent, &mode) == DRM_FORMAT_YUV420) {
 		mode.hdisplay >>= 1;
 		mode.htotal >>= 1;
 		mode.hsync_start >>= 1;
 		mode.hsync_end >>= 1;
+		mode.hskew >>= 1;
 
 		DPU_DEBUG_VIDENC(phys_enc,
-			"split_role %d, halve horizontal %d %d %d %d\n",
+			"split_role %d, halve horizontal %d %d %d %d %d\n",
 			phys_enc->split_role,
 			mode.hdisplay, mode.htotal,
-			mode.hsync_start, mode.hsync_end);
+			mode.hsync_start, mode.hsync_end,
+			mode.hskew);
 	}
 
 	drm_mode_to_intf_timing_params(phys_enc, &mode, &timing_params);
@@ -412,8 +422,15 @@ static int dpu_encoder_phys_vid_control_vblank_irq(
 static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc)
 {
 	struct dpu_hw_ctl *ctl;
+	struct dpu_hw_cdm *hw_cdm;
+	const struct dpu_format *fmt = NULL;
+	u32 fmt_fourcc = DRM_FORMAT_RGB888;
 
 	ctl = phys_enc->hw_ctl;
+	hw_cdm = phys_enc->hw_cdm;
+	if (hw_cdm)
+		fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent, &phys_enc->cached_mode);
+	fmt = dpu_get_dpu_format(fmt_fourcc);
 
 	DPU_DEBUG_VIDENC(phys_enc, "\n");
 
@@ -422,6 +439,8 @@ static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc)
 
 	dpu_encoder_helper_split_config(phys_enc, phys_enc->hw_intf->idx);
 
+	dpu_encoder_helper_phys_setup_cdm(phys_enc, fmt, CDM_CDWN_OUTPUT_HDMI);
+
 	dpu_encoder_phys_vid_setup_timing_engine(phys_enc);
 
 	/*
@@ -437,7 +456,15 @@ static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc)
 	if (ctl->ops.update_pending_flush_merge_3d && phys_enc->hw_pp->merge_3d)
 		ctl->ops.update_pending_flush_merge_3d(ctl, phys_enc->hw_pp->merge_3d->idx);
 
-	if (ctl->ops.update_pending_flush_periph && phys_enc->hw_intf->cap->type == INTF_DP)
+	if (ctl->ops.update_pending_flush_cdm && phys_enc->hw_cdm)
+		ctl->ops.update_pending_flush_cdm(ctl, hw_cdm->idx);
+
+	/*
+	 * Peripheral flush must be updated whenever flushing SDP packets is needed.
+	 * SDP packets are required for any YUV format (YUV420, YUV422, YUV444).
+	 */
+	if (ctl->ops.update_pending_flush_periph && phys_enc->hw_intf->cap->type == INTF_DP &&
+	    phys_enc->hw_cdm)
 		ctl->ops.update_pending_flush_periph(ctl, phys_enc->hw_intf->idx);
 
 skip_flush:
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 6d764f5b08727..4329435518351 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1399,6 +1399,18 @@ void __exit msm_dp_unregister(void)
 	platform_driver_unregister(&dp_display_driver);
 }
 
+bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
+			       const struct drm_display_mode *mode)
+{
+	struct dp_display_private *dp;
+	const struct drm_display_info *info;
+
+	dp = container_of(dp_display, struct dp_display_private, dp_display);
+	info = &dp_display->connector->display_info;
+
+	return dp_panel_vsc_sdp_supported(dp->panel) && drm_mode_is_420_only(info, mode);
+}
+
 bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)
 {
 	struct dp_display_private *dp;
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 16a7cbc0b7dd8..b9581bd934e9e 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -387,7 +387,8 @@ void __exit msm_dp_unregister(void);
 int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
 			 struct drm_encoder *encoder);
 void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp_display);
-
+bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
+			       const struct drm_display_mode *mode);
 bool msm_dp_wide_bus_available(const struct msm_dp *dp_display);
 
 #else
@@ -409,6 +410,12 @@ static inline void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm
 {
 }
 
+static inline bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
+					     const struct drm_display_mode *mode)
+{
+	return false;
+}
+
 static inline bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)
 {
 	return false;
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 15/17] drm/msm/dpu: allow certain formats for CDM for DP
  2024-01-25 19:38 [PATCH 00/17] Add support for CDM over DP Paloma Arellano
                   ` (13 preceding siblings ...)
  2024-01-25 19:38 ` [PATCH 14/17] drm/msm/dpu: modify encoder programming for CDM over DP Paloma Arellano
@ 2024-01-25 19:38 ` Paloma Arellano
  2024-01-25 21:58   ` Dmitry Baryshkov
  2024-01-25 19:38 ` [PATCH 16/17] drm/msm/dpu: reserve CDM blocks for DP if mode is YUV420 Paloma Arellano
  2024-01-25 19:38 ` [PATCH 17/17] drm/msm/dp: allow YUV420 mode for DP connector when VSC SDP supported Paloma Arellano
  16 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-25 19:38 UTC (permalink / raw)
  To: freedreno
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, quic_abhinavk,
	dri-devel, swboyd, seanpaul, quic_jesszhan, dmitry.baryshkov,
	Paloma Arellano, quic_khsieh

CDM block supports formats other than H1V2 for DP. Since we are now
adding support for CDM over DP, relax the checks to allow all other
formats for DP other than H1V2.

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
index e9cdc7934a499..9016b3ade6bc3 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
@@ -186,7 +186,7 @@ static int dpu_hw_cdm_enable(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cdm)
 	dpu_hw_cdm_setup_cdwn(ctx, cdm);
 
 	if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
-		if (fmt->chroma_sample != DPU_CHROMA_H1V2)
+		if (fmt->chroma_sample == DPU_CHROMA_H1V2)
 			return -EINVAL; /*unsupported format */
 		opmode = CDM_HDMI_PACK_OP_MODE_EN;
 		opmode |= (fmt->chroma_sample << 1);
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 16/17] drm/msm/dpu: reserve CDM blocks for DP if mode is YUV420
  2024-01-25 19:38 [PATCH 00/17] Add support for CDM over DP Paloma Arellano
                   ` (14 preceding siblings ...)
  2024-01-25 19:38 ` [PATCH 15/17] drm/msm/dpu: allow certain formats for CDM for DP Paloma Arellano
@ 2024-01-25 19:38 ` Paloma Arellano
  2024-01-25 22:01   ` Dmitry Baryshkov
  2024-01-25 19:38 ` [PATCH 17/17] drm/msm/dp: allow YUV420 mode for DP connector when VSC SDP supported Paloma Arellano
  16 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-25 19:38 UTC (permalink / raw)
  To: freedreno
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, quic_abhinavk,
	dri-devel, swboyd, seanpaul, quic_jesszhan, dmitry.baryshkov,
	Paloma Arellano, quic_khsieh

Reserve CDM blocks for DP if the mode format is YUV420. Currently this
reservation only works for writeback and DP if the format is YUV420. But
this can be easily extented to other YUV formats for DP.

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 99ec53446ad21..c7dcda3d54ae6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -613,6 +613,7 @@ static int dpu_encoder_virt_atomic_check(
 	struct dpu_kms *dpu_kms;
 	struct drm_display_mode *adj_mode;
 	struct msm_display_topology topology;
+	struct msm_display_info *disp_info;
 	struct dpu_global_state *global_state;
 	struct drm_framebuffer *fb;
 	struct drm_dsc_config *dsc;
@@ -629,6 +630,7 @@ static int dpu_encoder_virt_atomic_check(
 	DPU_DEBUG_ENC(dpu_enc, "\n");
 
 	priv = drm_enc->dev->dev_private;
+	disp_info = &dpu_enc->disp_info;
 	dpu_kms = to_dpu_kms(priv->kms);
 	adj_mode = &crtc_state->adjusted_mode;
 	global_state = dpu_kms_get_global_state(crtc_state->state);
@@ -656,8 +658,8 @@ static int dpu_encoder_virt_atomic_check(
 	topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode, crtc_state, dsc);
 
 	/*
-	 * Use CDM only for writeback at the moment as other interfaces cannot handle it.
-	 * if writeback itself cannot handle cdm for some reason it will fail in its atomic_check()
+	 * Use CDM only for writeback or DP at the moment as other interfaces cannot handle it.
+	 * If writeback itself cannot handle cdm for some reason it will fail in its atomic_check()
 	 * earlier.
 	 */
 	if (dpu_enc->disp_info.intf_type == INTF_WB && conn_state->writeback_job) {
@@ -665,12 +667,15 @@ static int dpu_encoder_virt_atomic_check(
 
 		if (fb && DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(fb))))
 			topology.needs_cdm = true;
-		if (topology.needs_cdm && !dpu_enc->cur_master->hw_cdm)
-			crtc_state->mode_changed = true;
-		else if (!topology.needs_cdm && dpu_enc->cur_master->hw_cdm)
-			crtc_state->mode_changed = true;
+	} else if (dpu_enc->disp_info.intf_type == INTF_DP) {
+		if (msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]], adj_mode))
+			topology.needs_cdm = true;
 	}
 
+	if (topology.needs_cdm && !dpu_enc->cur_master->hw_cdm)
+		crtc_state->mode_changed = true;
+	else if (!topology.needs_cdm && dpu_enc->cur_master->hw_cdm)
+		crtc_state->mode_changed = true;
 	/*
 	 * Release and Allocate resources on every modeset
 	 * Dont allocate when active is false.
@@ -1111,7 +1116,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
 
 	dpu_enc->dsc_mask = dsc_mask;
 
-	if (dpu_enc->disp_info.intf_type == INTF_WB && conn_state->writeback_job) {
+	if ((dpu_enc->disp_info.intf_type == INTF_WB && conn_state->writeback_job) ||
+	    dpu_enc->disp_info.intf_type == INTF_DP) {
 		struct dpu_hw_blk *hw_cdm = NULL;
 
 		dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* [PATCH 17/17] drm/msm/dp: allow YUV420 mode for DP connector when VSC SDP supported
  2024-01-25 19:38 [PATCH 00/17] Add support for CDM over DP Paloma Arellano
                   ` (15 preceding siblings ...)
  2024-01-25 19:38 ` [PATCH 16/17] drm/msm/dpu: reserve CDM blocks for DP if mode is YUV420 Paloma Arellano
@ 2024-01-25 19:38 ` Paloma Arellano
  2024-01-25 22:05   ` Dmitry Baryshkov
  16 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-25 19:38 UTC (permalink / raw)
  To: freedreno
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, quic_abhinavk,
	dri-devel, swboyd, seanpaul, quic_jesszhan, dmitry.baryshkov,
	Paloma Arellano, quic_khsieh

All the components of YUV420 over DP are added. Therefore, let's mark the
connector property as true for DP connector when the DP type is not eDP
and when VSC SDP is supported.

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 drivers/gpu/drm/msm/dp/dp_display.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 4329435518351..97edd607400b8 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -370,11 +370,14 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp)
 
 	dp_link_process_request(dp->link);
 
-	if (!dp->dp_display.is_edp)
+	if (!dp->dp_display.is_edp) {
+		if (dp_panel_vsc_sdp_supported(dp->panel))
+			dp->dp_display.connector->ycbcr_420_allowed = true;
 		drm_dp_set_subconnector_property(dp->dp_display.connector,
 						 connector_status_connected,
 						 dp->panel->dpcd,
 						 dp->panel->downstream_ports);
+	}
 
 	edid = dp->panel->edid;
 
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 95+ messages in thread

* Re: [PATCH 01/17] drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP
  2024-01-25 19:38 ` [PATCH 01/17] drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP Paloma Arellano
@ 2024-01-25 21:14   ` Dmitry Baryshkov
  2024-01-27  0:39     ` Paloma Arellano
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-25 21:14 UTC (permalink / raw)
  To: Paloma Arellano, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh

On 25/01/2024 21:38, Paloma Arellano wrote:
> Generalize dpu_encoder_helper_phys_setup_cdm to be compatible with DP.
> 
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>   .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  4 +--
>   .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 31 ++++++++++---------
>   2 files changed, 18 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> index 993f263433314..37ac385727c3b 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> @@ -153,6 +153,7 @@ enum dpu_intr_idx {
>    * @hw_intf:		Hardware interface to the intf registers
>    * @hw_wb:		Hardware interface to the wb registers
>    * @hw_cdm:		Hardware interface to the CDM registers
> + * @cdm_cfg:	CDM block config needed to store WB/DP block's CDM configuration

Please realign the description.

>    * @dpu_kms:		Pointer to the dpu_kms top level
>    * @cached_mode:	DRM mode cached at mode_set time, acted on in enable
>    * @vblank_ctl_lock:	Vblank ctl mutex lock to protect vblank_refcount
> @@ -183,6 +184,7 @@ struct dpu_encoder_phys {
>   	struct dpu_hw_intf *hw_intf;
>   	struct dpu_hw_wb *hw_wb;
>   	struct dpu_hw_cdm *hw_cdm;
> +	struct dpu_hw_cdm_cfg cdm_cfg;

It might be slightly better to move it after all the pointers, so after 
the dpu_kms.

>   	struct dpu_kms *dpu_kms;
>   	struct drm_display_mode cached_mode;
>   	struct mutex vblank_ctl_lock;
> @@ -213,7 +215,6 @@ static inline int dpu_encoder_phys_inc_pending(struct dpu_encoder_phys *phys)
>    * @wbirq_refcount:     Reference count of writeback interrupt
>    * @wb_done_timeout_cnt: number of wb done irq timeout errors
>    * @wb_cfg:  writeback block config to store fb related details
> - * @cdm_cfg: cdm block config needed to store writeback block's CDM configuration
>    * @wb_conn: backpointer to writeback connector
>    * @wb_job: backpointer to current writeback job
>    * @dest:   dpu buffer layout for current writeback output buffer
> @@ -223,7 +224,6 @@ struct dpu_encoder_phys_wb {
>   	atomic_t wbirq_refcount;
>   	int wb_done_timeout_cnt;
>   	struct dpu_hw_wb_cfg wb_cfg;
> -	struct dpu_hw_cdm_cfg cdm_cfg;
>   	struct drm_writeback_connector *wb_conn;
>   	struct drm_writeback_job *wb_job;
>   	struct dpu_hw_fmt_layout dest;
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> index 4cd2d9e3131a4..072fc6950e496 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> @@ -269,28 +269,21 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
>    *                                     This API does not handle DPU_CHROMA_H1V2.
>    * @phys_enc:Pointer to physical encoder
>    */
> -static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
> +static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc,
> +					      const struct dpu_format *dpu_fmt,
> +					      u32 output_type)
>   {
>   	struct dpu_hw_cdm *hw_cdm;
>   	struct dpu_hw_cdm_cfg *cdm_cfg;
>   	struct dpu_hw_pingpong *hw_pp;
> -	struct dpu_encoder_phys_wb *wb_enc;
> -	const struct msm_format *format;
> -	const struct dpu_format *dpu_fmt;
> -	struct drm_writeback_job *wb_job;
>   	int ret;
>   
>   	if (!phys_enc)
>   		return;
>   
> -	wb_enc = to_dpu_encoder_phys_wb(phys_enc);
> -	cdm_cfg = &wb_enc->cdm_cfg;
> +	cdm_cfg = &phys_enc->cdm_cfg;
>   	hw_pp = phys_enc->hw_pp;
>   	hw_cdm = phys_enc->hw_cdm;
> -	wb_job = wb_enc->wb_job;
> -
> -	format = msm_framebuffer_format(wb_enc->wb_job->fb);
> -	dpu_fmt = dpu_get_dpu_format_ext(format->pixel_format, wb_job->fb->modifier);
>   
>   	if (!hw_cdm)
>   		return;
> @@ -306,10 +299,10 @@ static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
>   
>   	memset(cdm_cfg, 0, sizeof(struct dpu_hw_cdm_cfg));
>   
> -	cdm_cfg->output_width = wb_job->fb->width;
> -	cdm_cfg->output_height = wb_job->fb->height;
> +	cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
> +	cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;

This is a semantic change. Instead of passing the FB size, this passes 
the mode dimensions. They are not guaranteed to be the same, especially 
for the WB case.

>   	cdm_cfg->output_fmt = dpu_fmt;
> -	cdm_cfg->output_type = CDM_CDWN_OUTPUT_WB;
> +	cdm_cfg->output_type = output_type;
>   	cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
>   			CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
>   	cdm_cfg->csc_cfg = &dpu_csc10_rgb2yuv_601l;
> @@ -462,6 +455,14 @@ static void dpu_encoder_phys_wb_setup(
>   	struct dpu_hw_wb *hw_wb = phys_enc->hw_wb;
>   	struct drm_display_mode mode = phys_enc->cached_mode;
>   	struct drm_framebuffer *fb = NULL;
> +	struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc);
> +	struct drm_writeback_job *wb_job;
> +	const struct msm_format *format;
> +	const struct dpu_format *dpu_fmt;
> +
> +	wb_job = wb_enc->wb_job;
> +	format = msm_framebuffer_format(wb_enc->wb_job->fb);
> +	dpu_fmt = dpu_get_dpu_format_ext(format->pixel_format, wb_job->fb->modifier);
>   
>   	DPU_DEBUG("[mode_set:%d, \"%s\",%d,%d]\n",
>   			hw_wb->idx - WB_0, mode.name,
> @@ -475,7 +476,7 @@ static void dpu_encoder_phys_wb_setup(
>   
>   	dpu_encoder_phys_wb_setup_fb(phys_enc, fb);
>   
> -	dpu_encoder_helper_phys_setup_cdm(phys_enc);
> +	dpu_encoder_helper_phys_setup_cdm(phys_enc, dpu_fmt, CDM_CDWN_OUTPUT_WB);
>   
>   	dpu_encoder_phys_wb_setup_ctl(phys_enc);
>   }

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 02/17] drm/msm/dpu: move dpu_encoder_helper_phys_setup_cdm to dpu_encoder
  2024-01-25 19:38 ` [PATCH 02/17] drm/msm/dpu: move dpu_encoder_helper_phys_setup_cdm to dpu_encoder Paloma Arellano
@ 2024-01-25 21:16   ` Dmitry Baryshkov
  2024-01-27  0:43     ` Paloma Arellano
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-25 21:16 UTC (permalink / raw)
  To: Paloma Arellano, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh

On 25/01/2024 21:38, Paloma Arellano wrote:
> Move dpu_encoder_helper_phys_setup_cdm to dpu_encoder in preparation for
> implementing CDM compatibility for DP.

Nit: s/CDM compatibility/YUV support/. It might make sense to spell it 
out that YUV over DP requires CDM.

> 
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 78 +++++++++++++++++
>   .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  9 ++
>   .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 84 -------------------
>   3 files changed, 87 insertions(+), 84 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 83380bc92a00a..6cef98f046ea6 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -2114,6 +2114,84 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
>   	ctl->ops.clear_pending_flush(ctl);
>   }
>   
> +void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc,
> +				       const struct dpu_format *dpu_fmt,
> +				       u32 output_type)

My email client suggests that the parameters are not idented properly 
anymore.

> +{
> +	struct dpu_hw_cdm *hw_cdm;
> +	struct dpu_hw_cdm_cfg *cdm_cfg;
> +	struct dpu_hw_pingpong *hw_pp;
> +	int ret;
> +
> +	if (!phys_enc)
> +		return;
> +
> +	cdm_cfg = &phys_enc->cdm_cfg;
> +	hw_pp = phys_enc->hw_pp;
> +	hw_cdm = phys_enc->hw_cdm;
> +
> +	if (!hw_cdm)
> +		return;
> +
> +	if (!DPU_FORMAT_IS_YUV(dpu_fmt)) {
> +		DPU_DEBUG("[enc:%d] cdm_disable fmt:%x\n", DRMID(phys_enc->parent),
> +			  dpu_fmt->base.pixel_format);
> +		if (hw_cdm->ops.bind_pingpong_blk)
> +			hw_cdm->ops.bind_pingpong_blk(hw_cdm, PINGPONG_NONE);
> +
> +		return;
> +	}
> +
> +	memset(cdm_cfg, 0, sizeof(struct dpu_hw_cdm_cfg));
> +
> +	cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
> +	cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
> +	cdm_cfg->output_fmt = dpu_fmt;
> +	cdm_cfg->output_type = output_type;
> +	cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
> +			CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
> +	cdm_cfg->csc_cfg = &dpu_csc10_rgb2yuv_601l;
> +
> +	/* enable 10 bit logic */
> +	switch (cdm_cfg->output_fmt->chroma_sample) {
> +	case DPU_CHROMA_RGB:
> +		cdm_cfg->h_cdwn_type = CDM_CDWN_DISABLE;
> +		cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
> +		break;
> +	case DPU_CHROMA_H2V1:
> +		cdm_cfg->h_cdwn_type = CDM_CDWN_COSITE;
> +		cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
> +		break;
> +	case DPU_CHROMA_420:
> +		cdm_cfg->h_cdwn_type = CDM_CDWN_COSITE;
> +		cdm_cfg->v_cdwn_type = CDM_CDWN_OFFSITE;
> +		break;
> +	case DPU_CHROMA_H1V2:
> +	default:
> +		DPU_ERROR("[enc:%d] unsupported chroma sampling type\n",
> +			  DRMID(phys_enc->parent));
> +		cdm_cfg->h_cdwn_type = CDM_CDWN_DISABLE;
> +		cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
> +		break;
> +	}
> +
> +	DPU_DEBUG("[enc:%d] cdm_enable:%d,%d,%X,%d,%d,%d,%d]\n",
> +		  DRMID(phys_enc->parent), cdm_cfg->output_width,
> +		  cdm_cfg->output_height, cdm_cfg->output_fmt->base.pixel_format,
> +		  cdm_cfg->output_type, cdm_cfg->output_bit_depth,
> +		  cdm_cfg->h_cdwn_type, cdm_cfg->v_cdwn_type);
> +
> +	if (hw_cdm->ops.enable) {
> +		cdm_cfg->pp_id = hw_pp->idx;
> +		ret = hw_cdm->ops.enable(hw_cdm, cdm_cfg);
> +		if (ret < 0) {
> +			DPU_ERROR("[enc:%d] failed to enable CDM; ret:%d\n",
> +				  DRMID(phys_enc->parent), ret);
> +			return;
> +		}
> +	}
> +}
> +
>   #ifdef CONFIG_DEBUG_FS
>   static int _dpu_encoder_status_show(struct seq_file *s, void *data)
>   {
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> index 37ac385727c3b..310944303a056 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> @@ -381,6 +381,15 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc,
>    */
>   void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc);
>   
> +/**
> + * dpu_encoder_helper_phys_setup_cdm - setup chroma down sampling block
> + * @phys_enc: Pointer to physical encoder
> + * @output_type: HDMI/WB
> + */
> +void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc,
> +				       const struct dpu_format *dpu_fmt,
> +				       u32 output_type);

Again, indentation.

> +
>   /**
>    * dpu_encoder_vblank_callback - Notify virtual encoder of vblank IRQ reception
>    * @drm_enc:    Pointer to drm encoder structure
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> index 072fc6950e496..400580847bde7 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> @@ -264,89 +264,6 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
>   	}
>   }
>   
> -/**
> - * dpu_encoder_helper_phys_setup_cdm - setup chroma down sampling block
> - *                                     This API does not handle DPU_CHROMA_H1V2.
> - * @phys_enc:Pointer to physical encoder
> - */
> -static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc,
> -					      const struct dpu_format *dpu_fmt,
> -					      u32 output_type)
> -{
> -	struct dpu_hw_cdm *hw_cdm;
> -	struct dpu_hw_cdm_cfg *cdm_cfg;
> -	struct dpu_hw_pingpong *hw_pp;
> -	int ret;
> -
> -	if (!phys_enc)
> -		return;
> -
> -	cdm_cfg = &phys_enc->cdm_cfg;
> -	hw_pp = phys_enc->hw_pp;
> -	hw_cdm = phys_enc->hw_cdm;
> -
> -	if (!hw_cdm)
> -		return;
> -
> -	if (!DPU_FORMAT_IS_YUV(dpu_fmt)) {
> -		DPU_DEBUG("[enc:%d] cdm_disable fmt:%x\n", DRMID(phys_enc->parent),
> -			  dpu_fmt->base.pixel_format);
> -		if (hw_cdm->ops.bind_pingpong_blk)
> -			hw_cdm->ops.bind_pingpong_blk(hw_cdm, PINGPONG_NONE);
> -
> -		return;
> -	}
> -
> -	memset(cdm_cfg, 0, sizeof(struct dpu_hw_cdm_cfg));
> -
> -	cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
> -	cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
> -	cdm_cfg->output_fmt = dpu_fmt;
> -	cdm_cfg->output_type = output_type;
> -	cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
> -			CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
> -	cdm_cfg->csc_cfg = &dpu_csc10_rgb2yuv_601l;
> -
> -	/* enable 10 bit logic */
> -	switch (cdm_cfg->output_fmt->chroma_sample) {
> -	case DPU_CHROMA_RGB:
> -		cdm_cfg->h_cdwn_type = CDM_CDWN_DISABLE;
> -		cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
> -		break;
> -	case DPU_CHROMA_H2V1:
> -		cdm_cfg->h_cdwn_type = CDM_CDWN_COSITE;
> -		cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
> -		break;
> -	case DPU_CHROMA_420:
> -		cdm_cfg->h_cdwn_type = CDM_CDWN_COSITE;
> -		cdm_cfg->v_cdwn_type = CDM_CDWN_OFFSITE;
> -		break;
> -	case DPU_CHROMA_H1V2:
> -	default:
> -		DPU_ERROR("[enc:%d] unsupported chroma sampling type\n",
> -			  DRMID(phys_enc->parent));
> -		cdm_cfg->h_cdwn_type = CDM_CDWN_DISABLE;
> -		cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
> -		break;
> -	}
> -
> -	DPU_DEBUG("[enc:%d] cdm_enable:%d,%d,%X,%d,%d,%d,%d]\n",
> -		  DRMID(phys_enc->parent), cdm_cfg->output_width,
> -		  cdm_cfg->output_height, cdm_cfg->output_fmt->base.pixel_format,
> -		  cdm_cfg->output_type, cdm_cfg->output_bit_depth,
> -		  cdm_cfg->h_cdwn_type, cdm_cfg->v_cdwn_type);
> -
> -	if (hw_cdm->ops.enable) {
> -		cdm_cfg->pp_id = hw_pp->idx;
> -		ret = hw_cdm->ops.enable(hw_cdm, cdm_cfg);
> -		if (ret < 0) {
> -			DPU_ERROR("[enc:%d] failed to enable CDM; ret:%d\n",
> -				  DRMID(phys_enc->parent), ret);
> -			return;
> -		}
> -	}
> -}
> -
>   /**
>    * dpu_encoder_phys_wb_atomic_check - verify and fixup given atomic states
>    * @phys_enc:	Pointer to physical encoder
> @@ -399,7 +316,6 @@ static int dpu_encoder_phys_wb_atomic_check(
>   	return drm_atomic_helper_check_wb_connector_state(conn_state->connector, conn_state->state);
>   }
>   
> -

irrelevant, please drop.

>   /**
>    * _dpu_encoder_phys_wb_update_flush - flush hardware update
>    * @phys_enc:	Pointer to physical encoder

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 03/17] drm/msm/dp: rename wide_bus_en to wide_bus_supported
  2024-01-25 19:38 ` [PATCH 03/17] drm/msm/dp: rename wide_bus_en to wide_bus_supported Paloma Arellano
@ 2024-01-25 21:17   ` Dmitry Baryshkov
  0 siblings, 0 replies; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-25 21:17 UTC (permalink / raw)
  To: Paloma Arellano, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh

On 25/01/2024 21:38, Paloma Arellano wrote:
> Rename wide_bus_en to wide_bus_supported in dp_display_private to
> correctly establish that the parameter is referencing if wide bus is
> supported instead of enabled.
> 
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>   drivers/gpu/drm/msm/dp/dp_display.c | 42 ++++++++++++++---------------
>   1 file changed, 21 insertions(+), 21 deletions(-)

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 04/17] drm/msm/dp: store mode YUV420 information to be used by rest of DP
  2024-01-25 19:38 ` [PATCH 04/17] drm/msm/dp: store mode YUV420 information to be used by rest of DP Paloma Arellano
@ 2024-01-25 21:20   ` Dmitry Baryshkov
  2024-01-27  0:48     ` Paloma Arellano
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-25 21:20 UTC (permalink / raw)
  To: Paloma Arellano, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh

On 25/01/2024 21:38, Paloma Arellano wrote:
> Wide bus is not supported when the mode is YUV420 in DP. In preparation
> for changing the DPU programming to reflect this, the value and
> assignment location of wide_bus_en for the DP submodules must be
> changed. Move it from boot time in dp_init_sub_modules() to run time in
> dp_display_mode_set.
> 
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>   drivers/gpu/drm/msm/dp/dp_display.c | 17 +++++++++++++----
>   drivers/gpu/drm/msm/dp/dp_panel.h   |  1 +
>   2 files changed, 14 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
> index 9df2a8b21021e..ddac55f45a722 100644
> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> @@ -784,10 +784,6 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
>   		goto error_ctrl;
>   	}
>   
> -	/* populate wide_bus_supported to different layers */
> -	dp->ctrl->wide_bus_en = dp->wide_bus_supported;
> -	dp->catalog->wide_bus_en = dp->wide_bus_supported;
> -
>   	return rc;
>   
>   error_ctrl:
> @@ -808,6 +804,7 @@ static int dp_display_set_mode(struct msm_dp *dp_display,
>   	drm_mode_copy(&dp->panel->dp_mode.drm_mode, &mode->drm_mode);
>   	dp->panel->dp_mode.bpp = mode->bpp;
>   	dp->panel->dp_mode.capabilities = mode->capabilities;
> +	dp->panel->dp_mode.out_fmt_is_yuv_420 = mode->out_fmt_is_yuv_420;

Why do we need it in dp_panel too?

>   	dp_panel_init_panel_info(dp->panel);
>   	return 0;
>   }
> @@ -1402,6 +1399,9 @@ bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)
>   
>   	dp = container_of(dp_display, struct dp_display_private, dp_display);
>   
> +	if (dp->dp_mode.out_fmt_is_yuv_420)
> +		return false;
> +
>   	return dp->wide_bus_supported;
>   }
>   
> @@ -1615,6 +1615,15 @@ void dp_bridge_mode_set(struct drm_bridge *drm_bridge,
>   
>   	dp_display->dp_mode.h_active_low =
>   		!!(dp_display->dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC);
> +
> +	dp_display->dp_mode.out_fmt_is_yuv_420 =
> +		drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode);
> +
> +	/* populate wide_bus_support to different layers */
> +	dp_display->ctrl->wide_bus_en =
> +		dp_display->dp_mode.out_fmt_is_yuv_420 ? false : dp_display->wide_bus_supported;
> +	dp_display->catalog->wide_bus_en =
> +		dp_display->dp_mode.out_fmt_is_yuv_420 ? false : dp_display->wide_bus_supported;
>   }
>   
>   void dp_bridge_hpd_enable(struct drm_bridge *bridge)
> diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h
> index a0dfc579c5f9f..6ec68be9f2366 100644
> --- a/drivers/gpu/drm/msm/dp/dp_panel.h
> +++ b/drivers/gpu/drm/msm/dp/dp_panel.h
> @@ -19,6 +19,7 @@ struct dp_display_mode {
>   	u32 bpp;
>   	u32 h_active_low;
>   	u32 v_active_low;
> +	bool out_fmt_is_yuv_420;
>   };
>   
>   struct dp_panel_in {

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 05/17] drm/msm/dp: add an API to indicate if sink supports VSC SDP
  2024-01-25 19:38 ` [PATCH 05/17] drm/msm/dp: add an API to indicate if sink supports VSC SDP Paloma Arellano
@ 2024-01-25 21:23   ` Dmitry Baryshkov
  2024-01-27  0:58     ` Paloma Arellano
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-25 21:23 UTC (permalink / raw)
  To: Paloma Arellano, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh

On 25/01/2024 21:38, Paloma Arellano wrote:
> YUV420 format is supported only in the VSC SDP packet and not through
> MSA. Hence add an API which indicates the sink support which can be used
> by the rest of the DP programming.

This API ideally should go to drm/display/drm_dp_helper.c

> 
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>   drivers/gpu/drm/msm/dp/dp_display.c |  3 ++-
>   drivers/gpu/drm/msm/dp/dp_panel.c   | 35 +++++++++++++++++++++++++----
>   drivers/gpu/drm/msm/dp/dp_panel.h   |  1 +
>   3 files changed, 34 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
> index ddac55f45a722..f6b3b6ca242f8 100644
> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> @@ -1617,7 +1617,8 @@ void dp_bridge_mode_set(struct drm_bridge *drm_bridge,
>   		!!(dp_display->dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC);
>   
>   	dp_display->dp_mode.out_fmt_is_yuv_420 =
> -		drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode);
> +		drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode) &&
> +		dp_panel_vsc_sdp_supported(dp_display->panel);
>   
>   	/* populate wide_bus_support to different layers */
>   	dp_display->ctrl->wide_bus_en =
> diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c
> index 127f6af995cd1..af7820b6d35ec 100644
> --- a/drivers/gpu/drm/msm/dp/dp_panel.c
> +++ b/drivers/gpu/drm/msm/dp/dp_panel.c
> @@ -17,6 +17,9 @@ struct dp_panel_private {
>   	struct dp_link *link;
>   	struct dp_catalog *catalog;
>   	bool panel_on;
> +	bool vsc_supported;
> +	u8 major;
> +	u8 minor;
>   };
>   
>   static void dp_panel_read_psr_cap(struct dp_panel_private *panel)
> @@ -43,9 +46,10 @@ static void dp_panel_read_psr_cap(struct dp_panel_private *panel)
>   static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
>   {
>   	int rc;
> +	ssize_t rlen;
>   	struct dp_panel_private *panel;
>   	struct dp_link_info *link_info;
> -	u8 *dpcd, major, minor;
> +	u8 *dpcd, rx_feature;
>   
>   	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
>   	dpcd = dp_panel->dpcd;
> @@ -53,10 +57,19 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
>   	if (rc)
>   		return rc;
>   
> +	rlen = drm_dp_dpcd_read(panel->aux, DP_DPRX_FEATURE_ENUMERATION_LIST, &rx_feature, 1);
> +	if (rlen != 1) {
> +		panel->vsc_supported = false;
> +		pr_debug("failed to read DP_DPRX_FEATURE_ENUMERATION_LIST\n");
> +	} else {
> +		panel->vsc_supported = !!(rx_feature & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED);
> +		pr_debug("vsc=%d\n", panel->vsc_supported);
> +	}
> +
>   	link_info = &dp_panel->link_info;
>   	link_info->revision = dpcd[DP_DPCD_REV];
> -	major = (link_info->revision >> 4) & 0x0f;
> -	minor = link_info->revision & 0x0f;
> +	panel->major = (link_info->revision >> 4) & 0x0f;
> +	panel->minor = link_info->revision & 0x0f;
>   
>   	link_info->rate = drm_dp_max_link_rate(dpcd);
>   	link_info->num_lanes = drm_dp_max_lane_count(dpcd);
> @@ -69,7 +82,7 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
>   	if (link_info->rate > dp_panel->max_dp_link_rate)
>   		link_info->rate = dp_panel->max_dp_link_rate;
>   
> -	drm_dbg_dp(panel->drm_dev, "version: %d.%d\n", major, minor);
> +	drm_dbg_dp(panel->drm_dev, "version: %d.%d\n", panel->major, panel->minor);
>   	drm_dbg_dp(panel->drm_dev, "link_rate=%d\n", link_info->rate);
>   	drm_dbg_dp(panel->drm_dev, "lane_count=%d\n", link_info->num_lanes);
>   
> @@ -280,6 +293,20 @@ void dp_panel_tpg_config(struct dp_panel *dp_panel, bool enable)
>   	dp_catalog_panel_tpg_enable(catalog, &panel->dp_panel.dp_mode.drm_mode);
>   }
>   
> +bool dp_panel_vsc_sdp_supported(struct dp_panel *dp_panel)
> +{
> +	struct dp_panel_private *panel;
> +
> +	if (!dp_panel) {
> +		pr_err("invalid input\n");
> +		return false;
> +	}
> +
> +	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
> +
> +	return panel->major >= 1 && panel->minor >= 3 && panel->vsc_supported;
> +}
> +
>   void dp_panel_dump_regs(struct dp_panel *dp_panel)
>   {
>   	struct dp_catalog *catalog;
> diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h
> index 6ec68be9f2366..590eca5ce304b 100644
> --- a/drivers/gpu/drm/msm/dp/dp_panel.h
> +++ b/drivers/gpu/drm/msm/dp/dp_panel.h
> @@ -66,6 +66,7 @@ int dp_panel_get_modes(struct dp_panel *dp_panel,
>   		struct drm_connector *connector);
>   void dp_panel_handle_sink_request(struct dp_panel *dp_panel);
>   void dp_panel_tpg_config(struct dp_panel *dp_panel, bool enable);
> +bool dp_panel_vsc_sdp_supported(struct dp_panel *dp_panel);
>   
>   /**
>    * is_link_rate_valid() - validates the link rate

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 06/17] drm/msm/dpu: move widebus logic to its own API
  2024-01-25 19:38 ` [PATCH 06/17] drm/msm/dpu: move widebus logic to its own API Paloma Arellano
@ 2024-01-25 21:25   ` Dmitry Baryshkov
  0 siblings, 0 replies; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-25 21:25 UTC (permalink / raw)
  To: Paloma Arellano, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh

On 25/01/2024 21:38, Paloma Arellano wrote:
> Widebus enablement is decided by the interfaces based on their specific
> checks and that already happens with DSI/DP specific helpers. Let's
> invoke these helpers from dpu_encoder_is_widebus_enabled() to make it
> cleaner overall.
> 
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 29 ++++++++++++---------
>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h |  4 +++
>   2 files changed, 20 insertions(+), 13 deletions(-)
> 

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/17] drm/msm/dpu: disallow widebus en in INTF_CONFIG2 when DP is YUV420
  2024-01-25 19:38 ` [PATCH 07/17] drm/msm/dpu: disallow widebus en in INTF_CONFIG2 when DP is YUV420 Paloma Arellano
@ 2024-01-25 21:26   ` Dmitry Baryshkov
  2024-01-27  5:42     ` Dmitry Baryshkov
  2024-01-28  5:16     ` Paloma Arellano
  0 siblings, 2 replies; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-25 21:26 UTC (permalink / raw)
  To: Paloma Arellano, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh

On 25/01/2024 21:38, Paloma Arellano wrote:
> INTF_CONFIG2 register cannot have widebus enabled when DP format is
> YUV420. Therefore, program the INTF to send 1 ppc.

I think this is handled in the DP driver, where we disallow wide bus for 
YUV 4:2:0 modes.

> 
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 4 +++-
>   1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> index 6bba531d6dc41..bfb93f02fe7c1 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> @@ -168,7 +168,9 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
>   	 * video timing. It is recommended to enable it for all cases, except
>   	 * if compression is enabled in 1 pixel per clock mode
>   	 */
> -	if (p->wide_bus_en)
> +	if (dp_intf && fmt->base.pixel_format == DRM_FORMAT_YUV420)
> +		intf_cfg2 |= INTF_CFG2_DATA_HCTL_EN;
> +	else if (p->wide_bus_en)
>   		intf_cfg2 |= INTF_CFG2_DATABUS_WIDEN | INTF_CFG2_DATA_HCTL_EN;
>   
>   	data_width = p->width;

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 08/17] drm/msm/dp: change YUV420 related programming for DP
  2024-01-25 19:38 ` [PATCH 08/17] drm/msm/dp: change YUV420 related programming for DP Paloma Arellano
@ 2024-01-25 21:29   ` Dmitry Baryshkov
  2024-01-28  5:18     ` Paloma Arellano
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-25 21:29 UTC (permalink / raw)
  To: Paloma Arellano, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh

On 25/01/2024 21:38, Paloma Arellano wrote:
> Change all relevant DP controller related programming for YUV420 cases.
> Namely, change the pixel clock math to consider YUV420, program the
> configuration control to indicate YUV420, as well as modify the MVID
> programming to consider YUV420.

Too many items for a single commit.

> 
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>   drivers/gpu/drm/msm/dp/dp_catalog.c |  5 ++++-
>   drivers/gpu/drm/msm/dp/dp_catalog.h |  2 +-
>   drivers/gpu/drm/msm/dp/dp_ctrl.c    | 12 +++++++++---
>   drivers/gpu/drm/msm/dp/dp_display.c |  8 +++++++-
>   drivers/gpu/drm/msm/msm_kms.h       |  3 +++
>   5 files changed, 24 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
> index 5142aeb705a44..5d84c089e520a 100644
> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
> @@ -442,7 +442,7 @@ void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog,
>   
>   void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog,
>   					u32 rate, u32 stream_rate_khz,
> -					bool fixed_nvid)
> +					bool fixed_nvid, bool is_ycbcr_420)
>   {
>   	u32 pixel_m, pixel_n;
>   	u32 mvid, nvid, pixel_div = 0, dispcc_input_rate;
> @@ -485,6 +485,9 @@ void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog,
>   		nvid = temp;
>   	}
>   
> +	if (is_ycbcr_420)
> +		mvid /= 2;
> +
>   	if (link_rate_hbr2 == rate)
>   		nvid *= 2;
>   
> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
> index 38786e855b51a..6cb5e2a243de2 100644
> --- a/drivers/gpu/drm/msm/dp/dp_catalog.h
> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
> @@ -96,7 +96,7 @@ void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog, bool enable);
>   void dp_catalog_ctrl_psr_mainlink_enable(struct dp_catalog *dp_catalog, bool enable);
>   void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, u32 cc, u32 tb);
>   void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 rate,
> -				u32 stream_rate_khz, bool fixed_nvid);
> +				u32 stream_rate_khz, bool fixed_nvid, bool is_ycbcr_420);
>   int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog, u32 pattern);
>   u32 dp_catalog_hw_revision(const struct dp_catalog *dp_catalog);
>   void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog);
> diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
> index 77a8d9366ed7b..209cf2a35642f 100644
> --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
> +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
> @@ -128,6 +128,9 @@ static void dp_ctrl_config_ctrl(struct dp_ctrl_private *ctrl)
>   	/* Default-> LSCLK DIV: 1/4 LCLK  */
>   	config |= (2 << DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT);
>   
> +	if (ctrl->panel->dp_mode.out_fmt_is_yuv_420)
> +		config |= DP_CONFIGURATION_CTRL_RGB_YUV; /* YUV420 */
> +

This definitely is not related to clock rate calculations.

>   	/* Scrambler reset enable */
>   	if (drm_dp_alternate_scrambler_reset_cap(dpcd))
>   		config |= DP_CONFIGURATION_CTRL_ASSR;
> @@ -957,7 +960,7 @@ static void dp_ctrl_calc_tu_parameters(struct dp_ctrl_private *ctrl,
>   	in.hporch = drm_mode->htotal - drm_mode->hdisplay;
>   	in.nlanes = ctrl->link->link_params.num_lanes;
>   	in.bpp = ctrl->panel->dp_mode.bpp;
> -	in.pixel_enc = 444;
> +	in.pixel_enc = ctrl->panel->dp_mode.out_fmt_is_yuv_420 ? 420 : 444;
>   	in.dsc_en = 0;
>   	in.async_en = 0;
>   	in.fec_en = 0;
> @@ -1763,6 +1766,8 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
>   		ctrl->link->link_params.rate = rate;
>   		ctrl->link->link_params.num_lanes =
>   			ctrl->panel->link_info.num_lanes;
> +		if (ctrl->panel->dp_mode.out_fmt_is_yuv_420)
> +			pixel_rate >>= 1;
>   	}
>   
>   	drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, pixel_rate=%lu\n",
> @@ -1878,7 +1883,7 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train)
>   
>   	pixel_rate = pixel_rate_orig = ctrl->panel->dp_mode.drm_mode.clock;
>   
> -	if (dp_ctrl->wide_bus_en)
> +	if (dp_ctrl->wide_bus_en || ctrl->panel->dp_mode.out_fmt_is_yuv_420)
>   		pixel_rate >>= 1;
>   
>   	drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, pixel_rate=%lu\n",
> @@ -1917,7 +1922,8 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train)
>   
>   	dp_catalog_ctrl_config_msa(ctrl->catalog,
>   		ctrl->link->link_params.rate,
> -		pixel_rate_orig, dp_ctrl_use_fixed_nvid(ctrl));
> +		pixel_rate_orig, dp_ctrl_use_fixed_nvid(ctrl),
> +		ctrl->panel->dp_mode.out_fmt_is_yuv_420);
>   
>   	dp_ctrl_setup_tr_unit(ctrl);
>   
> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
> index f6b3b6ca242f8..6d764f5b08727 100644
> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> @@ -916,9 +916,10 @@ enum drm_mode_status dp_bridge_mode_valid(struct drm_bridge *bridge,
>   	const u32 num_components = 3, default_bpp = 24;
>   	struct dp_display_private *dp_display;
>   	struct dp_link_info *link_info;
> -	u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0;
>   	struct msm_dp *dp;
>   	int mode_pclk_khz = mode->clock;
> +	int rate_ratio = RGB_24BPP_TMDS_CHAR_RATE_RATIO;
> +	u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0;
>   
>   	dp = to_dp_bridge(bridge)->dp_display;
>   
> @@ -933,6 +934,11 @@ enum drm_mode_status dp_bridge_mode_valid(struct drm_bridge *bridge,
>   	dp_display = container_of(dp, struct dp_display_private, dp_display);
>   	link_info = &dp_display->panel->link_info;
>   
> +	if (drm_mode_is_420_only(&dp->connector->display_info, mode))
> +		rate_ratio = YUV420_24BPP_TMDS_CHAR_RATE_RATIO;
> +
> +	mode_pclk_khz /= rate_ratio;

I think it will be more obvious and simple to write:

if (drm_mode_is_420...)
     mode_pclk_khz /= 2;


> +
>   	mode_bpp = dp->connector->display_info.bpc * num_components;
>   	if (!mode_bpp)
>   		mode_bpp = default_bpp;
> diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
> index 44aa435d68ce2..66e8151951807 100644
> --- a/drivers/gpu/drm/msm/msm_kms.h
> +++ b/drivers/gpu/drm/msm/msm_kms.h
> @@ -15,6 +15,9 @@
>   
>   #define MAX_PLANE	4
>   
> +#define RGB_24BPP_TMDS_CHAR_RATE_RATIO		1
> +#define YUV420_24BPP_TMDS_CHAR_RATE_RATIO	2
> +
>   /* As there are different display controller blocks depending on the
>    * snapdragon version, the kms support is split out and the appropriate
>    * implementation is loaded at runtime.  The kms module is responsible

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 09/17] drm/msm/dp: move parity calculation to dp_catalog
  2024-01-25 19:38 ` [PATCH 09/17] drm/msm/dp: move parity calculation to dp_catalog Paloma Arellano
@ 2024-01-25 21:32   ` Dmitry Baryshkov
  2024-01-28  5:18     ` Paloma Arellano
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-25 21:32 UTC (permalink / raw)
  To: Paloma Arellano, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh

On 25/01/2024 21:38, Paloma Arellano wrote:
> Parity calculation is necessary for VSC SDP implementation, therefore
> move it to dp_catalog so it usable by both SDP programming and
> dp_audio.c
> 
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>   drivers/gpu/drm/msm/dp/dp_audio.c   | 100 ++++------------------------
>   drivers/gpu/drm/msm/dp/dp_catalog.h |  72 ++++++++++++++++++++
>   2 files changed, 86 insertions(+), 86 deletions(-)

There is nothing catalog-uish in the parity calculation. Just add 
dp_utils.c. Another options is to push it to the drm/display/

LGTM otherwise.

> 
> diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c
> index 4a2e479723a85..7aa785018155a 100644
> --- a/drivers/gpu/drm/msm/dp/dp_audio.c
> +++ b/drivers/gpu/drm/msm/dp/dp_audio.c
> @@ -16,13 +16,6 @@
>   #include "dp_panel.h"
>   #include "dp_display.h"
>   
> -#define HEADER_BYTE_2_BIT	 0
> -#define PARITY_BYTE_2_BIT	 8
> -#define HEADER_BYTE_1_BIT	16
> -#define PARITY_BYTE_1_BIT	24
> -#define HEADER_BYTE_3_BIT	16
> -#define PARITY_BYTE_3_BIT	24
> -
>   struct dp_audio_private {
>   	struct platform_device *audio_pdev;
>   	struct platform_device *pdev;
> @@ -36,71 +29,6 @@ struct dp_audio_private {
>   	struct dp_audio dp_audio;
>   };
>   
> -static u8 dp_audio_get_g0_value(u8 data)
> -{
> -	u8 c[4];
> -	u8 g[4];
> -	u8 ret_data = 0;
> -	u8 i;
> -
> -	for (i = 0; i < 4; i++)
> -		c[i] = (data >> i) & 0x01;
> -
> -	g[0] = c[3];
> -	g[1] = c[0] ^ c[3];
> -	g[2] = c[1];
> -	g[3] = c[2];
> -
> -	for (i = 0; i < 4; i++)
> -		ret_data = ((g[i] & 0x01) << i) | ret_data;
> -
> -	return ret_data;
> -}
> -
> -static u8 dp_audio_get_g1_value(u8 data)
> -{
> -	u8 c[4];
> -	u8 g[4];
> -	u8 ret_data = 0;
> -	u8 i;
> -
> -	for (i = 0; i < 4; i++)
> -		c[i] = (data >> i) & 0x01;
> -
> -	g[0] = c[0] ^ c[3];
> -	g[1] = c[0] ^ c[1] ^ c[3];
> -	g[2] = c[1] ^ c[2];
> -	g[3] = c[2] ^ c[3];
> -
> -	for (i = 0; i < 4; i++)
> -		ret_data = ((g[i] & 0x01) << i) | ret_data;
> -
> -	return ret_data;
> -}
> -
> -static u8 dp_audio_calculate_parity(u32 data)
> -{
> -	u8 x0 = 0;
> -	u8 x1 = 0;
> -	u8 ci = 0;
> -	u8 iData = 0;
> -	u8 i = 0;
> -	u8 parity_byte;
> -	u8 num_byte = (data & 0xFF00) > 0 ? 8 : 2;
> -
> -	for (i = 0; i < num_byte; i++) {
> -		iData = (data >> i*4) & 0xF;
> -
> -		ci = iData ^ x1;
> -		x1 = x0 ^ dp_audio_get_g1_value(ci);
> -		x0 = dp_audio_get_g0_value(ci);
> -	}
> -
> -	parity_byte = x1 | (x0 << 4);
> -
> -	return parity_byte;
> -}
> -
>   static u32 dp_audio_get_header(struct dp_catalog *catalog,
>   		enum dp_catalog_audio_sdp_type sdp,
>   		enum dp_catalog_audio_header_type header)
> @@ -134,7 +62,7 @@ static void dp_audio_stream_sdp(struct dp_audio_private *audio)
>   			DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1);
>   
>   	new_value = 0x02;
> -	parity_byte = dp_audio_calculate_parity(new_value);
> +	parity_byte = dp_catalog_calculate_parity(new_value);
>   	value |= ((new_value << HEADER_BYTE_1_BIT)
>   			| (parity_byte << PARITY_BYTE_1_BIT));
>   	drm_dbg_dp(audio->drm_dev,
> @@ -147,7 +75,7 @@ static void dp_audio_stream_sdp(struct dp_audio_private *audio)
>   	value = dp_audio_get_header(catalog,
>   			DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2);
>   	new_value = value;
> -	parity_byte = dp_audio_calculate_parity(new_value);
> +	parity_byte = dp_catalog_calculate_parity(new_value);
>   	value |= ((new_value << HEADER_BYTE_2_BIT)
>   			| (parity_byte << PARITY_BYTE_2_BIT));
>   	drm_dbg_dp(audio->drm_dev,
> @@ -162,7 +90,7 @@ static void dp_audio_stream_sdp(struct dp_audio_private *audio)
>   			DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3);
>   
>   	new_value = audio->channels - 1;
> -	parity_byte = dp_audio_calculate_parity(new_value);
> +	parity_byte = dp_catalog_calculate_parity(new_value);
>   	value |= ((new_value << HEADER_BYTE_3_BIT)
>   			| (parity_byte << PARITY_BYTE_3_BIT));
>   	drm_dbg_dp(audio->drm_dev,
> @@ -184,7 +112,7 @@ static void dp_audio_timestamp_sdp(struct dp_audio_private *audio)
>   			DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1);
>   
>   	new_value = 0x1;
> -	parity_byte = dp_audio_calculate_parity(new_value);
> +	parity_byte = dp_catalog_calculate_parity(new_value);
>   	value |= ((new_value << HEADER_BYTE_1_BIT)
>   			| (parity_byte << PARITY_BYTE_1_BIT));
>   	drm_dbg_dp(audio->drm_dev,
> @@ -198,7 +126,7 @@ static void dp_audio_timestamp_sdp(struct dp_audio_private *audio)
>   			DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2);
>   
>   	new_value = 0x17;
> -	parity_byte = dp_audio_calculate_parity(new_value);
> +	parity_byte = dp_catalog_calculate_parity(new_value);
>   	value |= ((new_value << HEADER_BYTE_2_BIT)
>   			| (parity_byte << PARITY_BYTE_2_BIT));
>   	drm_dbg_dp(audio->drm_dev,
> @@ -212,7 +140,7 @@ static void dp_audio_timestamp_sdp(struct dp_audio_private *audio)
>   			DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3);
>   
>   	new_value = (0x0 | (0x11 << 2));
> -	parity_byte = dp_audio_calculate_parity(new_value);
> +	parity_byte = dp_catalog_calculate_parity(new_value);
>   	value |= ((new_value << HEADER_BYTE_3_BIT)
>   			| (parity_byte << PARITY_BYTE_3_BIT));
>   	drm_dbg_dp(audio->drm_dev,
> @@ -233,7 +161,7 @@ static void dp_audio_infoframe_sdp(struct dp_audio_private *audio)
>   			DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1);
>   
>   	new_value = 0x84;
> -	parity_byte = dp_audio_calculate_parity(new_value);
> +	parity_byte = dp_catalog_calculate_parity(new_value);
>   	value |= ((new_value << HEADER_BYTE_1_BIT)
>   			| (parity_byte << PARITY_BYTE_1_BIT));
>   	drm_dbg_dp(audio->drm_dev,
> @@ -247,7 +175,7 @@ static void dp_audio_infoframe_sdp(struct dp_audio_private *audio)
>   			DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2);
>   
>   	new_value = 0x1b;
> -	parity_byte = dp_audio_calculate_parity(new_value);
> +	parity_byte = dp_catalog_calculate_parity(new_value);
>   	value |= ((new_value << HEADER_BYTE_2_BIT)
>   			| (parity_byte << PARITY_BYTE_2_BIT));
>   	drm_dbg_dp(audio->drm_dev,
> @@ -261,7 +189,7 @@ static void dp_audio_infoframe_sdp(struct dp_audio_private *audio)
>   			DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3);
>   
>   	new_value = (0x0 | (0x11 << 2));
> -	parity_byte = dp_audio_calculate_parity(new_value);
> +	parity_byte = dp_catalog_calculate_parity(new_value);
>   	value |= ((new_value << HEADER_BYTE_3_BIT)
>   			| (parity_byte << PARITY_BYTE_3_BIT));
>   	drm_dbg_dp(audio->drm_dev,
> @@ -282,7 +210,7 @@ static void dp_audio_copy_management_sdp(struct dp_audio_private *audio)
>   			DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1);
>   
>   	new_value = 0x05;
> -	parity_byte = dp_audio_calculate_parity(new_value);
> +	parity_byte = dp_catalog_calculate_parity(new_value);
>   	value |= ((new_value << HEADER_BYTE_1_BIT)
>   			| (parity_byte << PARITY_BYTE_1_BIT));
>   	drm_dbg_dp(audio->drm_dev,
> @@ -296,7 +224,7 @@ static void dp_audio_copy_management_sdp(struct dp_audio_private *audio)
>   			DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2);
>   
>   	new_value = 0x0F;
> -	parity_byte = dp_audio_calculate_parity(new_value);
> +	parity_byte = dp_catalog_calculate_parity(new_value);
>   	value |= ((new_value << HEADER_BYTE_2_BIT)
>   			| (parity_byte << PARITY_BYTE_2_BIT));
>   	drm_dbg_dp(audio->drm_dev,
> @@ -310,7 +238,7 @@ static void dp_audio_copy_management_sdp(struct dp_audio_private *audio)
>   			DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3);
>   
>   	new_value = 0x0;
> -	parity_byte = dp_audio_calculate_parity(new_value);
> +	parity_byte = dp_catalog_calculate_parity(new_value);
>   	value |= ((new_value << HEADER_BYTE_3_BIT)
>   			| (parity_byte << PARITY_BYTE_3_BIT));
>   	drm_dbg_dp(audio->drm_dev,
> @@ -331,7 +259,7 @@ static void dp_audio_isrc_sdp(struct dp_audio_private *audio)
>   			DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1);
>   
>   	new_value = 0x06;
> -	parity_byte = dp_audio_calculate_parity(new_value);
> +	parity_byte = dp_catalog_calculate_parity(new_value);
>   	value |= ((new_value << HEADER_BYTE_1_BIT)
>   			| (parity_byte << PARITY_BYTE_1_BIT));
>   	drm_dbg_dp(audio->drm_dev,
> @@ -345,7 +273,7 @@ static void dp_audio_isrc_sdp(struct dp_audio_private *audio)
>   			DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2);
>   
>   	new_value = 0x0F;
> -	parity_byte = dp_audio_calculate_parity(new_value);
> +	parity_byte = dp_catalog_calculate_parity(new_value);
>   	value |= ((new_value << HEADER_BYTE_2_BIT)
>   			| (parity_byte << PARITY_BYTE_2_BIT));
>   	drm_dbg_dp(audio->drm_dev,
> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
> index 6cb5e2a243de2..563903605b3a7 100644
> --- a/drivers/gpu/drm/msm/dp/dp_catalog.h
> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
> @@ -45,6 +45,13 @@ enum dp_phy_aux_config_type {
>   	PHY_AUX_CFG_MAX,
>   };
>   
> +#define HEADER_BYTE_2_BIT	 0
> +#define PARITY_BYTE_2_BIT	 8
> +#define HEADER_BYTE_1_BIT	16
> +#define PARITY_BYTE_1_BIT	24
> +#define HEADER_BYTE_3_BIT	16
> +#define PARITY_BYTE_3_BIT	24
> +
>   enum dp_catalog_audio_sdp_type {
>   	DP_AUDIO_SDP_STREAM,
>   	DP_AUDIO_SDP_TIMESTAMP,
> @@ -73,6 +80,71 @@ struct dp_catalog {
>   	bool wide_bus_en;
>   };
>   
> +static inline u8 dp_catalog_get_g0_value(u8 data)
> +{
> +	u8 c[4];
> +	u8 g[4];
> +	u8 ret_data = 0;
> +	u8 i;
> +
> +	for (i = 0; i < 4; i++)
> +		c[i] = (data >> i) & 0x01;
> +
> +	g[0] = c[3];
> +	g[1] = c[0] ^ c[3];
> +	g[2] = c[1];
> +	g[3] = c[2];
> +
> +	for (i = 0; i < 4; i++)
> +		ret_data = ((g[i] & 0x01) << i) | ret_data;
> +
> +	return ret_data;
> +}
> +
> +static inline u8 dp_catalog_get_g1_value(u8 data)
> +{
> +	u8 c[4];
> +	u8 g[4];
> +	u8 ret_data = 0;
> +	u8 i;
> +
> +	for (i = 0; i < 4; i++)
> +		c[i] = (data >> i) & 0x01;
> +
> +	g[0] = c[0] ^ c[3];
> +	g[1] = c[0] ^ c[1] ^ c[3];
> +	g[2] = c[1] ^ c[2];
> +	g[3] = c[2] ^ c[3];
> +
> +	for (i = 0; i < 4; i++)
> +		ret_data = ((g[i] & 0x01) << i) | ret_data;
> +
> +	return ret_data;
> +}
> +
> +static inline u8 dp_catalog_calculate_parity(u32 data)
> +{
> +	u8 x0 = 0;
> +	u8 x1 = 0;
> +	u8 ci = 0;
> +	u8 iData = 0;
> +	u8 i = 0;
> +	u8 parity_byte;
> +	u8 num_byte = (data & 0xFF00) > 0 ? 8 : 2;
> +
> +	for (i = 0; i < num_byte; i++) {
> +		iData = (data >> i * 4) & 0xF;
> +
> +		ci = iData ^ x1;
> +		x1 = x0 ^ dp_catalog_get_g1_value(ci);
> +		x0 = dp_catalog_get_g0_value(ci);
> +	}
> +
> +	parity_byte = x1 | (x0 << 4);
> +
> +	return parity_byte;
> +}
> +
>   /* Debug module */
>   void dp_catalog_snapshot(struct dp_catalog *dp_catalog, struct msm_disp_state *disp_state);
>   

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 11/17] drm/msm/dp: add VSC SDP support for YUV420 over DP
  2024-01-25 19:38 ` [PATCH 11/17] drm/msm/dp: add VSC SDP support for YUV420 over DP Paloma Arellano
@ 2024-01-25 21:48   ` Dmitry Baryshkov
  2024-01-28  5:34     ` Paloma Arellano
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-25 21:48 UTC (permalink / raw)
  To: Paloma Arellano, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh

On 25/01/2024 21:38, Paloma Arellano wrote:
> Add support to pack and send the VSC SDP packet for DP. This therefore
> allows the transmision of format information to the sinks which is
> needed for YUV420 support over DP.
> 
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>   drivers/gpu/drm/msm/dp/dp_catalog.c | 147 ++++++++++++++++++++++++++++
>   drivers/gpu/drm/msm/dp/dp_catalog.h |   4 +
>   drivers/gpu/drm/msm/dp/dp_ctrl.c    |   4 +
>   drivers/gpu/drm/msm/dp/dp_panel.c   |  47 +++++++++
>   drivers/gpu/drm/msm/dp/dp_reg.h     |   3 +
>   5 files changed, 205 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
> index c025786170ba5..7e4c68be23e56 100644
> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
> @@ -29,6 +29,9 @@
>   
>   #define DP_INTF_CONFIG_DATABUS_WIDEN     BIT(4)
>   
> +#define DP_GENERIC0_6_YUV_8_BPC		BIT(0)
> +#define DP_GENERIC0_6_YUV_10_BPC	BIT(1)
> +
>   #define DP_INTERRUPT_STATUS1 \
>   	(DP_INTR_AUX_XFER_DONE| \
>   	DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \
> @@ -907,6 +910,150 @@ int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog)
>   	return 0;
>   }
>   
> +static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog *dp_catalog)
> +{
> +	struct dp_catalog_private *catalog;
> +	u32 header, parity, data;
> +	u8 bpc, off = 0;
> +	u8 buf[SZ_128];
> +
> +	if (!dp_catalog) {
> +		pr_err("invalid input\n");
> +		return;
> +	}
> +
> +	catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
> +
> +	/* HEADER BYTE 1 */
> +	header = dp_catalog->sdp.sdp_header.HB1;
> +	parity = dp_catalog_calculate_parity(header);
> +	data   = ((header << HEADER_BYTE_1_BIT) | (parity << PARITY_BYTE_1_BIT));
> +	dp_write_link(catalog, MMSS_DP_GENERIC0_0, data);
> +	memcpy(buf + off, &data, sizeof(data));
> +	off += sizeof(data);
> +
> +	/* HEADER BYTE 2 */
> +	header = dp_catalog->sdp.sdp_header.HB2;
> +	parity = dp_catalog_calculate_parity(header);
> +	data   = ((header << HEADER_BYTE_2_BIT) | (parity << PARITY_BYTE_2_BIT));
> +	dp_write_link(catalog, MMSS_DP_GENERIC0_1, data);
> +
> +	/* HEADER BYTE 3 */
> +	header = dp_catalog->sdp.sdp_header.HB3;
> +	parity = dp_catalog_calculate_parity(header);
> +	data   = ((header << HEADER_BYTE_3_BIT) | (parity << PARITY_BYTE_3_BIT));
> +	data |= dp_read_link(catalog, MMSS_DP_GENERIC0_1);
> +	dp_write_link(catalog, MMSS_DP_GENERIC0_1, data);
> +	memcpy(buf + off, &data, sizeof(data));
> +	off += sizeof(data);

This seems to be common with the dp_audio code. Please extract this 
header writing too.

> +
> +	data = 0;
> +	dp_write_link(catalog, MMSS_DP_GENERIC0_2, data);
> +	memcpy(buf + off, &data, sizeof(data));
> +	off += sizeof(data);

Generally this is not how these functions are expected to be written. 
Please take a look at drivers/video/hdmi.c. It should be split into:
- generic function that packs the C structure into a flat byte buffer,
- driver-specific function that formats and writes the buffer to the 
hardware.

> +	dp_write_link(catalog, MMSS_DP_GENERIC0_3, data);
> +	memcpy(buf + off, &data, sizeof(data));
> +	off += sizeof(data);
> +
> +	dp_write_link(catalog, MMSS_DP_GENERIC0_4, data);
> +	memcpy(buf + off, &data, sizeof(data));
> +	off += sizeof(data);
> +
> +	dp_write_link(catalog, MMSS_DP_GENERIC0_5, data);
> +	memcpy(buf + off, &data, sizeof(data));
> +	off += sizeof(data);
> +
> +	switch (dp_catalog->vsc_sdp_data.bpc) {
> +	case 10:
> +		bpc = DP_GENERIC0_6_YUV_10_BPC;
> +		break;
> +	case 8:
> +	default:
> +		bpc = DP_GENERIC0_6_YUV_8_BPC;
> +		break;
> +	}
> +
> +	/* VSC SDP payload as per table 2-117 of DP 1.4 specification */
> +	data = (dp_catalog->vsc_sdp_data.colorimetry & 0xF) |
> +	       ((dp_catalog->vsc_sdp_data.pixelformat & 0xF) << 4) |
> +	       (bpc << 8) |
> +	       ((dp_catalog->vsc_sdp_data.dynamic_range & 0x1) << 15) |
> +	       ((dp_catalog->vsc_sdp_data.content_type & 0x7) << 16);
> +
> +	dp_write_link(catalog, MMSS_DP_GENERIC0_6, data);
> +	memcpy(buf + off, &data, sizeof(data));
> +	off += sizeof(data);
> +
> +	data = 0;
> +	dp_write_link(catalog, MMSS_DP_GENERIC0_7, data);
> +	memcpy(buf + off, &data, sizeof(data));
> +	off += sizeof(data);
> +
> +	dp_write_link(catalog, MMSS_DP_GENERIC0_8, data);
> +	memcpy(buf + off, &data, sizeof(data));
> +	off += sizeof(data);
> +
> +	dp_write_link(catalog, MMSS_DP_GENERIC0_9, data);
> +	memcpy(buf + off, &data, sizeof(data));
> +	off += sizeof(data);
> +
> +	print_hex_dump(KERN_DEBUG, "[drm-dp] VSC: ", DUMP_PREFIX_NONE, 16, 4, buf, off, false);
> +}
> +
> +void dp_catalog_panel_config_vsc_sdp(struct dp_catalog *dp_catalog, bool en)
> +{
> +	struct dp_catalog_private *catalog;
> +	u32 cfg, cfg2, misc;
> +	u16 major = 0, minor = 0;
> +
> +	if (!dp_catalog) {
> +		pr_err("invalid input\n");
> +		return;
> +	}
> +
> +	catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
> +
> +	cfg = dp_read_link(catalog, MMSS_DP_SDP_CFG);
> +	cfg2 = dp_read_link(catalog, MMSS_DP_SDP_CFG2);
> +	misc = dp_read_link(catalog, REG_DP_MISC1_MISC0);
> +
> +	if (en) {
> +		cfg |= GEN0_SDP_EN;
> +		dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
> +
> +		cfg2 |= GENERIC0_SDPSIZE;

When I see a something_SIZE macro, I'd naturally expect it to be an 
actual size of some data. Please consider renaming to e.g. 
GENERIC0_SDPSIZE_VALID.

> +		dp_write_link(catalog, MMSS_DP_SDP_CFG2, cfg2);
> +
> +		dp_catalog_panel_setup_vsc_sdp(dp_catalog);
> +
> +		/* indicates presence of VSC (BIT(6) of MISC1) */
> +		misc |= DP_MISC1_VSC_SDP;
> +
> +		drm_dbg_dp(catalog->drm_dev, "vsc sdp enable=%d\n", en);
> +	} else {
> +		cfg &= ~GEN0_SDP_EN;
> +		dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
> +
> +		cfg2 &= ~GENERIC0_SDPSIZE;
> +		dp_write_link(catalog, MMSS_DP_SDP_CFG2, cfg2);
> +
> +		/* switch back to MSA */
> +		misc &= ~DP_MISC1_VSC_SDP;
> +
> +		drm_dbg_dp(catalog->drm_dev, "vsc sdp enable=%d\n", en);
> +	}
> +
> +	pr_debug("misc settings = 0x%x\n", misc);
> +	dp_write_link(catalog, REG_DP_MISC1_MISC0, misc);
> +
> +	dp_catalog_hw_revision(dp_catalog, &major, &minor);
> +	if (major == 1 && minor < 2) {
> +		dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x01);
> +		dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x00);
> +	}
> +}
> +
>   void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog,
>   				struct drm_display_mode *drm_mode)
>   {
> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
> index 94c377ef90c35..6b757249c0698 100644
> --- a/drivers/gpu/drm/msm/dp/dp_catalog.h
> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
> @@ -7,6 +7,7 @@
>   #define _DP_CATALOG_H_
>   
>   #include <drm/drm_modes.h>
> +#include <drm/display/drm_dp_helper.h>
>   
>   #include "dp_parser.h"
>   #include "disp/msm_disp_snapshot.h"
> @@ -76,6 +77,8 @@ struct dp_catalog {
>   	u32 dp_active;
>   	enum dp_catalog_audio_sdp_type sdp_type;
>   	enum dp_catalog_audio_header_type sdp_header;
> +	struct dp_sdp sdp;

I assume that the sdp field contains only transient data, which is not 
used after it gets written to the hardware. Please remove it from the 
struct allocate on a stack or via kzalloc.

> +	struct drm_dp_vsc_sdp vsc_sdp_data;
>   	u32 audio_data;
>   	bool wide_bus_en;
>   };
> @@ -196,6 +199,7 @@ u32 dp_catalog_ctrl_read_phy_pattern(struct dp_catalog *dp_catalog);
>   
>   /* DP Panel APIs */
>   int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog);
> +void dp_catalog_panel_config_vsc_sdp(struct dp_catalog *dp_catalog, bool en);
>   void dp_catalog_dump_regs(struct dp_catalog *dp_catalog);
>   void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog,
>   				struct drm_display_mode *drm_mode);
> diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
> index 209cf2a35642f..ddd92a63d5a67 100644
> --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
> +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
> @@ -1952,6 +1952,8 @@ int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl)
>   	dp_io = &ctrl->parser->io;
>   	phy = dp_io->phy;
>   
> +	dp_catalog_panel_config_vsc_sdp(ctrl->catalog, false);
> +
>   	/* set dongle to D3 (power off) mode */
>   	dp_link_psm_config(ctrl->link, &ctrl->panel->link_info, true);
>   
> @@ -2026,6 +2028,8 @@ int dp_ctrl_off(struct dp_ctrl *dp_ctrl)
>   	dp_io = &ctrl->parser->io;
>   	phy = dp_io->phy;
>   
> +	dp_catalog_panel_config_vsc_sdp(ctrl->catalog, false);
> +
>   	dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);
>   
>   	dp_catalog_ctrl_reset(ctrl->catalog);
> diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c
> index af7820b6d35ec..d6af9898b00d8 100644
> --- a/drivers/gpu/drm/msm/dp/dp_panel.c
> +++ b/drivers/gpu/drm/msm/dp/dp_panel.c
> @@ -307,6 +307,49 @@ bool dp_panel_vsc_sdp_supported(struct dp_panel *dp_panel)
>   	return panel->major >= 1 && panel->minor >= 3 && panel->vsc_supported;
>   }
>   
> +static int dp_panel_setup_vsc_sdp(struct dp_panel *dp_panel)
> +{
> +	struct dp_catalog *catalog;
> +	struct dp_panel_private *panel;
> +	struct dp_display_mode *dp_mode;
> +	int rc = 0;
> +
> +	if (!dp_panel) {
> +		pr_err("invalid input\n");
> +		rc = -EINVAL;
> +		return rc;
> +	}
> +
> +	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
> +	catalog = panel->catalog;
> +	dp_mode = &dp_panel->dp_mode;
> +
> +	memset(&catalog->sdp, 0, sizeof(catalog->sdp));
> +	memset(&catalog->vsc_sdp_data, 0, sizeof(catalog->vsc_sdp_data));
> +
> +	/* VSC SDP header as per table 2-118 of DP 1.4 specification */
> +	catalog->sdp.sdp_header.HB0 = 0x00;
> +	catalog->sdp.sdp_header.HB1 = 0x07;
> +	catalog->sdp.sdp_header.HB2 = 0x05;
> +	catalog->sdp.sdp_header.HB3 = 0x13;
> +
> +	/* VSC SDP Payload for DB16 */
> +	catalog->vsc_sdp_data.pixelformat = DP_PIXELFORMAT_YUV420;
> +	catalog->vsc_sdp_data.colorimetry = DP_COLORIMETRY_DEFAULT;
> +
> +	/* VSC SDP Payload for DB17 */
> +	catalog->vsc_sdp_data.dynamic_range = DP_DYNAMIC_RANGE_CTA;
> +
> +	/* VSC SDP Payload for DB18 */
> +	catalog->vsc_sdp_data.content_type = DP_CONTENT_TYPE_GRAPHICS;
> +
> +	catalog->vsc_sdp_data.bpc = dp_mode->bpp / 3;
> +
> +	dp_catalog_panel_config_vsc_sdp(catalog, true);
> +
> +	return rc;
> +}
> +
>   void dp_panel_dump_regs(struct dp_panel *dp_panel)
>   {
>   	struct dp_catalog *catalog;
> @@ -370,6 +413,10 @@ int dp_panel_timing_cfg(struct dp_panel *dp_panel)
>   	catalog->dp_active = data;
>   
>   	dp_catalog_panel_timing_cfg(catalog);
> +
> +	if (dp_panel->dp_mode.out_fmt_is_yuv_420)
> +		dp_panel_setup_vsc_sdp(dp_panel);
> +
>   	panel->panel_on = true;
>   
>   	return 0;
> diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h
> index ea85a691e72b5..756ddf85b1e81 100644
> --- a/drivers/gpu/drm/msm/dp/dp_reg.h
> +++ b/drivers/gpu/drm/msm/dp/dp_reg.h
> @@ -142,6 +142,7 @@
>   #define DP_MISC0_SYNCHRONOUS_CLK		(0x00000001)
>   #define DP_MISC0_COLORIMETRY_CFG_SHIFT		(0x00000001)
>   #define DP_MISC0_TEST_BITS_DEPTH_SHIFT		(0x00000005)
> +#define DP_MISC1_VSC_SDP			(0x00004000)
>   
>   #define REG_DP_VALID_BOUNDARY			(0x00000030)
>   #define REG_DP_VALID_BOUNDARY_2			(0x00000034)
> @@ -201,9 +202,11 @@
>   #define MMSS_DP_AUDIO_CTRL_RESET		(0x00000214)
>   
>   #define MMSS_DP_SDP_CFG				(0x00000228)
> +#define GEN0_SDP_EN				(0x00020000)
>   #define MMSS_DP_SDP_CFG2			(0x0000022C)
>   #define MMSS_DP_AUDIO_TIMESTAMP_0		(0x00000230)
>   #define MMSS_DP_AUDIO_TIMESTAMP_1		(0x00000234)
> +#define GENERIC0_SDPSIZE			(0x00010000)
>   
>   #define MMSS_DP_AUDIO_STREAM_0			(0x00000240)
>   #define MMSS_DP_AUDIO_STREAM_1			(0x00000244)

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 12/17] drm/msm/dpu: add support of new peripheral flush mechanism
  2024-01-25 19:38 ` [PATCH 12/17] drm/msm/dpu: add support of new peripheral flush mechanism Paloma Arellano
@ 2024-01-25 21:49   ` Dmitry Baryshkov
  2024-01-28  5:40     ` Paloma Arellano
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-25 21:49 UTC (permalink / raw)
  To: Paloma Arellano, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, Kuogee Hsieh

On 25/01/2024 21:38, Paloma Arellano wrote:
> From: Kuogee Hsieh <quic_khsieh@quicinc.com>
> 
> Introduce a peripheral flushing mechanism to decouple peripheral
> metadata flushing from timing engine related flush.
> 
> Signed-off-by: Kuogee Hsieh <quic_khsieh@quicinc.com>
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>   .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c    |  3 +++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c      | 17 +++++++++++++++++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h      | 10 ++++++++++
>   3 files changed, 30 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> index d0f56c5c4cce9..e284bf448bdda 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> @@ -437,6 +437,9 @@ static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc)
>   	if (ctl->ops.update_pending_flush_merge_3d && phys_enc->hw_pp->merge_3d)
>   		ctl->ops.update_pending_flush_merge_3d(ctl, phys_enc->hw_pp->merge_3d->idx);
>   
> +	if (ctl->ops.update_pending_flush_periph && phys_enc->hw_intf->cap->type == INTF_DP)
> +		ctl->ops.update_pending_flush_periph(ctl, phys_enc->hw_intf->idx);
> +
>   skip_flush:
>   	DPU_DEBUG_VIDENC(phys_enc,
>   		"update pending flush ctl %d intf %d\n",
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> index e76565c3e6a43..bf45afeb616d3 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> @@ -39,6 +39,7 @@
>   #define   CTL_WB_FLUSH                  0x108
>   #define   CTL_INTF_FLUSH                0x110
>   #define   CTL_CDM_FLUSH                0x114
> +#define   CTL_PERIPH_FLUSH              0x128
>   #define   CTL_INTF_MASTER               0x134
>   #define   CTL_DSPP_n_FLUSH(n)           ((0x13C) + ((n) * 4))
>   
> @@ -49,6 +50,7 @@
>   #define  MERGE_3D_IDX   23
>   #define  DSC_IDX        22
>   #define CDM_IDX         26
> +#define  PERIPH_IDX     30
>   #define  INTF_IDX       31
>   #define WB_IDX          16
>   #define  DSPP_IDX       29  /* From DPU hw rev 7.x.x */
> @@ -151,6 +153,10 @@ static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
>   				ctx->pending_dspp_flush_mask[dspp - DSPP_0]);
>   		}
>   
> +	if (ctx->pending_flush_mask & BIT(PERIPH_IDX))
> +		DPU_REG_WRITE(&ctx->hw, CTL_PERIPH_FLUSH,
> +			      ctx->pending_periph_flush_mask);
> +
>   	if (ctx->pending_flush_mask & BIT(DSC_IDX))
>   		DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH,
>   			      ctx->pending_dsc_flush_mask);
> @@ -311,6 +317,13 @@ static void dpu_hw_ctl_update_pending_flush_intf_v1(struct dpu_hw_ctl *ctx,
>   	ctx->pending_flush_mask |= BIT(INTF_IDX);
>   }
>   
> +static void dpu_hw_ctl_update_pending_flush_periph(struct dpu_hw_ctl *ctx,
> +		enum dpu_intf intf)

I assume this is _v1.
Also the argument is misaligned.

> +{
> +	ctx->pending_periph_flush_mask |= BIT(intf - INTF_0);
> +	ctx->pending_flush_mask |= BIT(PERIPH_IDX);
> +}
> +
>   static void dpu_hw_ctl_update_pending_flush_merge_3d_v1(struct dpu_hw_ctl *ctx,
>   		enum dpu_merge_3d merge_3d)
>   {
> @@ -680,6 +693,10 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
>   		ops->reset_intf_cfg = dpu_hw_ctl_reset_intf_cfg_v1;
>   		ops->update_pending_flush_intf =
>   			dpu_hw_ctl_update_pending_flush_intf_v1;
> +
> +		ops->update_pending_flush_periph =
> +			dpu_hw_ctl_update_pending_flush_periph;
> +
>   		ops->update_pending_flush_merge_3d =
>   			dpu_hw_ctl_update_pending_flush_merge_3d_v1;
>   		ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb_v1;

What about the pre-active platforms?

> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> index ff85b5ee0acf8..5d86c560b6d3f 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> @@ -122,6 +122,15 @@ struct dpu_hw_ctl_ops {
>   	void (*update_pending_flush_intf)(struct dpu_hw_ctl *ctx,
>   		enum dpu_intf blk);
>   
> +	/**
> +	 * OR in the given flushbits to the cached pending_(periph_)flush_mask
> +	 * No effect on hardware
> +	 * @ctx       : ctl path ctx pointer
> +	 * @blk       : interface block index
> +	 */
> +	void (*update_pending_flush_periph)(struct dpu_hw_ctl *ctx,
> +		enum dpu_intf blk);
> +
>   	/**
>   	 * OR in the given flushbits to the cached pending_(merge_3d_)flush_mask
>   	 * No effect on hardware
> @@ -264,6 +273,7 @@ struct dpu_hw_ctl {
>   	u32 pending_flush_mask;
>   	u32 pending_intf_flush_mask;
>   	u32 pending_wb_flush_mask;
> +	u32 pending_periph_flush_mask;
>   	u32 pending_merge_3d_flush_mask;
>   	u32 pending_dspp_flush_mask[DSPP_MAX - DSPP_0];
>   	u32 pending_dsc_flush_mask;

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 13/17] drm/msm/dp: enable SDP and SDE periph flush update
  2024-01-25 19:38 ` [PATCH 13/17] drm/msm/dp: enable SDP and SDE periph flush update Paloma Arellano
@ 2024-01-25 21:50   ` Dmitry Baryshkov
  2024-01-28  5:42     ` Paloma Arellano
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-25 21:50 UTC (permalink / raw)
  To: Paloma Arellano, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh

On 25/01/2024 21:38, Paloma Arellano wrote:
> DP controller can be setup to operate in either SDP update flush mode or
> peripheral flush mode based on the DP controller hardware version.
> 
> Starting in DP v1.2, the hardware documents require the use of
> peripheral flush mode for SDP packets such as PPS OR VSC SDP packets.
> 
> In-line with this guidance, lets program the DP controller to use
> peripheral flush mode starting DP v1.2
> 
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>   drivers/gpu/drm/msm/dp/dp_catalog.c | 18 ++++++++++++++++++
>   drivers/gpu/drm/msm/dp/dp_catalog.h |  1 +
>   drivers/gpu/drm/msm/dp/dp_ctrl.c    |  1 +
>   drivers/gpu/drm/msm/dp/dp_reg.h     |  2 ++
>   4 files changed, 22 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
> index 7e4c68be23e56..b43083b9c2df6 100644
> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
> @@ -446,6 +446,24 @@ void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog,
>   	dp_write_link(catalog, REG_DP_MISC1_MISC0, misc_val);
>   }
>   
> +void dp_catalog_setup_peripheral_flush(struct dp_catalog *dp_catalog)
> +{
> +	u32 mainlink_ctrl;
> +	u16 major = 0, minor = 0;
> +	struct dp_catalog_private *catalog = container_of(dp_catalog,
> +				struct dp_catalog_private, dp_catalog);
> +
> +	mainlink_ctrl = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
> +
> +	dp_catalog_hw_revision(dp_catalog, &major, &minor);
> +	if (major >= 1 && minor >= 2)

if (major > 1 || (major == 1 && minor >= 2))

As a check, which of the values should be written for maj.min = 2.1?

> +		mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE;
> +	else
> +		mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_UPDATE_SDP;
> +
> +	dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
> +}
> +
>   void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog,
>   					u32 rate, u32 stream_rate_khz,
>   					bool fixed_nvid, bool is_ycbcr_420)
> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
> index 6b757249c0698..1d57988aa6689 100644
> --- a/drivers/gpu/drm/msm/dp/dp_catalog.h
> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
> @@ -169,6 +169,7 @@ void dp_catalog_ctrl_config_ctrl(struct dp_catalog *dp_catalog, u32 config);
>   void dp_catalog_ctrl_lane_mapping(struct dp_catalog *dp_catalog);
>   void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog, bool enable);
>   void dp_catalog_ctrl_psr_mainlink_enable(struct dp_catalog *dp_catalog, bool enable);
> +void dp_catalog_setup_peripheral_flush(struct dp_catalog *dp_catalog);
>   void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, u32 cc, u32 tb);
>   void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 rate,
>   				u32 stream_rate_khz, bool fixed_nvid, bool is_ycbcr_420);
> diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
> index ddd92a63d5a67..c375b36f53ce1 100644
> --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
> +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
> @@ -170,6 +170,7 @@ static void dp_ctrl_configure_source_params(struct dp_ctrl_private *ctrl)
>   
>   	dp_catalog_ctrl_lane_mapping(ctrl->catalog);
>   	dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true);
> +	dp_catalog_setup_peripheral_flush(ctrl->catalog);
>   
>   	dp_ctrl_config_ctrl(ctrl);
>   
> diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h
> index 756ddf85b1e81..05a1009d2f678 100644
> --- a/drivers/gpu/drm/msm/dp/dp_reg.h
> +++ b/drivers/gpu/drm/msm/dp/dp_reg.h
> @@ -102,6 +102,8 @@
>   #define DP_MAINLINK_CTRL_ENABLE			(0x00000001)
>   #define DP_MAINLINK_CTRL_RESET			(0x00000002)
>   #define DP_MAINLINK_CTRL_SW_BYPASS_SCRAMBLER	(0x00000010)
> +#define DP_MAINLINK_FLUSH_MODE_UPDATE_SDP	(0x00800000)
> +#define DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE	(0x01800000)
>   #define DP_MAINLINK_FB_BOUNDARY_SEL		(0x02000000)
>   
>   #define REG_DP_STATE_CTRL			(0x00000004)

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 14/17] drm/msm/dpu: modify encoder programming for CDM over DP
  2024-01-25 19:38 ` [PATCH 14/17] drm/msm/dpu: modify encoder programming for CDM over DP Paloma Arellano
@ 2024-01-25 21:57   ` Dmitry Baryshkov
  2024-01-28  5:48     ` Paloma Arellano
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-25 21:57 UTC (permalink / raw)
  To: Paloma Arellano, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh

On 25/01/2024 21:38, Paloma Arellano wrote:
> Adjust the encoder format programming in the case of video mode for DP
> to accommodate CDM related changes.
> 
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 16 +++++++++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |  8 +++++
>   .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 35 ++++++++++++++++---
>   drivers/gpu/drm/msm/dp/dp_display.c           | 12 +++++++
>   drivers/gpu/drm/msm/msm_drv.h                 |  9 ++++-
>   5 files changed, 75 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index b0896814c1562..99ec53446ad21 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -222,6 +222,22 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = {
>   	15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10
>   };
>   
> +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc, const struct drm_display_mode *mode)
> +{
> +	const struct dpu_encoder_virt *dpu_enc;
> +	const struct msm_display_info *disp_info;
> +	struct msm_drm_private *priv;
> +
> +	dpu_enc = to_dpu_encoder_virt(drm_enc);
> +	disp_info = &dpu_enc->disp_info;
> +	priv = drm_enc->dev->dev_private;
> +
> +	if (disp_info->intf_type == INTF_DP &&
> +	    msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]], mode))

This should not require interacting with DP. If we got here, we must be 
sure that 4:2:0 is supported and can be configured.

> +		return DRM_FORMAT_YUV420;
> +
> +	return DRM_FORMAT_RGB888;
> +}
>   
>   bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc)
>   {
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> index 7b4afa71f1f96..62255d0aa4487 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> @@ -162,6 +162,14 @@ int dpu_encoder_get_vsync_count(struct drm_encoder *drm_enc);
>    */
>   bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc);
>   
> +/**
> + * dpu_encoder_get_drm_fmt - return DRM fourcc format
> + * @drm_enc:    Pointer to previously created drm encoder structure
> + * @mode:	Corresponding drm_display_mode for dpu encoder
> + */
> +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
> +			    const struct drm_display_mode *mode);
> +
>   /**
>    * dpu_encoder_get_crc_values_cnt - get number of physical encoders contained
>    *	in virtual encoder that can collect CRC values
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> index e284bf448bdda..a1dde0ff35dc8 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> @@ -234,6 +234,7 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
>   {
>   	struct drm_display_mode mode;
>   	struct dpu_hw_intf_timing_params timing_params = { 0 };
> +	struct dpu_hw_cdm *hw_cdm;
>   	const struct dpu_format *fmt = NULL;
>   	u32 fmt_fourcc = DRM_FORMAT_RGB888;
>   	unsigned long lock_flags;
> @@ -254,17 +255,26 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
>   	DPU_DEBUG_VIDENC(phys_enc, "enabling mode:\n");
>   	drm_mode_debug_printmodeline(&mode);
>   
> -	if (phys_enc->split_role != ENC_ROLE_SOLO) {
> +	hw_cdm = phys_enc->hw_cdm;
> +	if (hw_cdm) {
> +		intf_cfg.cdm = hw_cdm->idx;
> +		fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent, &mode);
> +	}
> +
> +	if (phys_enc->split_role != ENC_ROLE_SOLO ||
> +	    dpu_encoder_get_drm_fmt(phys_enc->parent, &mode) == DRM_FORMAT_YUV420) {
>   		mode.hdisplay >>= 1;
>   		mode.htotal >>= 1;
>   		mode.hsync_start >>= 1;
>   		mode.hsync_end >>= 1;
> +		mode.hskew >>= 1;

Separate patch.

>   
>   		DPU_DEBUG_VIDENC(phys_enc,
> -			"split_role %d, halve horizontal %d %d %d %d\n",
> +			"split_role %d, halve horizontal %d %d %d %d %d\n",
>   			phys_enc->split_role,
>   			mode.hdisplay, mode.htotal,
> -			mode.hsync_start, mode.hsync_end);
> +			mode.hsync_start, mode.hsync_end,
> +			mode.hskew);
>   	}
>   
>   	drm_mode_to_intf_timing_params(phys_enc, &mode, &timing_params);
> @@ -412,8 +422,15 @@ static int dpu_encoder_phys_vid_control_vblank_irq(
>   static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc)
>   {
>   	struct dpu_hw_ctl *ctl;
> +	struct dpu_hw_cdm *hw_cdm;
> +	const struct dpu_format *fmt = NULL;
> +	u32 fmt_fourcc = DRM_FORMAT_RGB888;
>   
>   	ctl = phys_enc->hw_ctl;
> +	hw_cdm = phys_enc->hw_cdm;
> +	if (hw_cdm)
> +		fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent, &phys_enc->cached_mode);
> +	fmt = dpu_get_dpu_format(fmt_fourcc);
>   
>   	DPU_DEBUG_VIDENC(phys_enc, "\n");
>   
> @@ -422,6 +439,8 @@ static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc)
>   
>   	dpu_encoder_helper_split_config(phys_enc, phys_enc->hw_intf->idx);
>   
> +	dpu_encoder_helper_phys_setup_cdm(phys_enc, fmt, CDM_CDWN_OUTPUT_HDMI);

If there is no CDM, why do we need to call this?

> +
>   	dpu_encoder_phys_vid_setup_timing_engine(phys_enc);
>   
>   	/*
> @@ -437,7 +456,15 @@ static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc)
>   	if (ctl->ops.update_pending_flush_merge_3d && phys_enc->hw_pp->merge_3d)
>   		ctl->ops.update_pending_flush_merge_3d(ctl, phys_enc->hw_pp->merge_3d->idx);
>   
> -	if (ctl->ops.update_pending_flush_periph && phys_enc->hw_intf->cap->type == INTF_DP)
> +	if (ctl->ops.update_pending_flush_cdm && phys_enc->hw_cdm)
> +		ctl->ops.update_pending_flush_cdm(ctl, hw_cdm->idx);
> +
> +	/*
> +	 * Peripheral flush must be updated whenever flushing SDP packets is needed.
> +	 * SDP packets are required for any YUV format (YUV420, YUV422, YUV444).
> +	 */
> +	if (ctl->ops.update_pending_flush_periph && phys_enc->hw_intf->cap->type == INTF_DP &&
> +	    phys_enc->hw_cdm)
>   		ctl->ops.update_pending_flush_periph(ctl, phys_enc->hw_intf->idx);

Should there be a flush if we are switching from YUV 420 to RGB mode?

Also, I'd say, we should move update_pending_flush_periph invocation to 
this patch.

>   
>   skip_flush:
> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
> index 6d764f5b08727..4329435518351 100644
> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> @@ -1399,6 +1399,18 @@ void __exit msm_dp_unregister(void)
>   	platform_driver_unregister(&dp_display_driver);
>   }
>   
> +bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
> +			       const struct drm_display_mode *mode)
> +{
> +	struct dp_display_private *dp;
> +	const struct drm_display_info *info;
> +
> +	dp = container_of(dp_display, struct dp_display_private, dp_display);
> +	info = &dp_display->connector->display_info;
> +
> +	return dp_panel_vsc_sdp_supported(dp->panel) && drm_mode_is_420_only(info, mode);

YUV 420 modes should be filtered out in mode_valid if VSC SDP is not 
supported.

> +}
> +
>   bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)
>   {
>   	struct dp_display_private *dp;
> diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
> index 16a7cbc0b7dd8..b9581bd934e9e 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -387,7 +387,8 @@ void __exit msm_dp_unregister(void);
>   int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
>   			 struct drm_encoder *encoder);
>   void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp *dp_display);
> -
> +bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
> +			       const struct drm_display_mode *mode);
>   bool msm_dp_wide_bus_available(const struct msm_dp *dp_display);
>   
>   #else
> @@ -409,6 +410,12 @@ static inline void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm
>   {
>   }
>   
> +static inline bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
> +					     const struct drm_display_mode *mode)
> +{
> +	return false;
> +}
> +
>   static inline bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)
>   {
>   	return false;

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 15/17] drm/msm/dpu: allow certain formats for CDM for DP
  2024-01-25 19:38 ` [PATCH 15/17] drm/msm/dpu: allow certain formats for CDM for DP Paloma Arellano
@ 2024-01-25 21:58   ` Dmitry Baryshkov
  2024-02-08 23:19     ` Paloma Arellano
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-25 21:58 UTC (permalink / raw)
  To: Paloma Arellano, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh

On 25/01/2024 21:38, Paloma Arellano wrote:
> CDM block supports formats other than H1V2 for DP. Since we are now
> adding support for CDM over DP, relax the checks to allow all other
> formats for DP other than H1V2.
> 
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
> index e9cdc7934a499..9016b3ade6bc3 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
> @@ -186,7 +186,7 @@ static int dpu_hw_cdm_enable(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cdm)
>   	dpu_hw_cdm_setup_cdwn(ctx, cdm);
>   
>   	if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
> -		if (fmt->chroma_sample != DPU_CHROMA_H1V2)
> +		if (fmt->chroma_sample == DPU_CHROMA_H1V2)
>   			return -EINVAL; /*unsupported format */

This means that the original check was incorrect. Please add 
corresponding Fixes tag and move to the top of the patchset.

>   		opmode = CDM_HDMI_PACK_OP_MODE_EN;
>   		opmode |= (fmt->chroma_sample << 1);

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 16/17] drm/msm/dpu: reserve CDM blocks for DP if mode is YUV420
  2024-01-25 19:38 ` [PATCH 16/17] drm/msm/dpu: reserve CDM blocks for DP if mode is YUV420 Paloma Arellano
@ 2024-01-25 22:01   ` Dmitry Baryshkov
  2024-01-28  5:48     ` Paloma Arellano
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-25 22:01 UTC (permalink / raw)
  To: Paloma Arellano, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh

On 25/01/2024 21:38, Paloma Arellano wrote:
> Reserve CDM blocks for DP if the mode format is YUV420. Currently this
> reservation only works for writeback and DP if the format is YUV420. But
> this can be easily extented to other YUV formats for DP.
> 
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 20 +++++++++++++-------
>   1 file changed, 13 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 99ec53446ad21..c7dcda3d54ae6 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -613,6 +613,7 @@ static int dpu_encoder_virt_atomic_check(
>   	struct dpu_kms *dpu_kms;
>   	struct drm_display_mode *adj_mode;
>   	struct msm_display_topology topology;
> +	struct msm_display_info *disp_info;
>   	struct dpu_global_state *global_state;
>   	struct drm_framebuffer *fb;
>   	struct drm_dsc_config *dsc;
> @@ -629,6 +630,7 @@ static int dpu_encoder_virt_atomic_check(
>   	DPU_DEBUG_ENC(dpu_enc, "\n");
>   
>   	priv = drm_enc->dev->dev_private;
> +	disp_info = &dpu_enc->disp_info;
>   	dpu_kms = to_dpu_kms(priv->kms);
>   	adj_mode = &crtc_state->adjusted_mode;
>   	global_state = dpu_kms_get_global_state(crtc_state->state);
> @@ -656,8 +658,8 @@ static int dpu_encoder_virt_atomic_check(
>   	topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode, crtc_state, dsc);
>   
>   	/*
> -	 * Use CDM only for writeback at the moment as other interfaces cannot handle it.
> -	 * if writeback itself cannot handle cdm for some reason it will fail in its atomic_check()
> +	 * Use CDM only for writeback or DP at the moment as other interfaces cannot handle it.
> +	 * If writeback itself cannot handle cdm for some reason it will fail in its atomic_check()
>   	 * earlier.
>   	 */
>   	if (dpu_enc->disp_info.intf_type == INTF_WB && conn_state->writeback_job) {
> @@ -665,12 +667,15 @@ static int dpu_encoder_virt_atomic_check(
>   
>   		if (fb && DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(fb))))
>   			topology.needs_cdm = true;
> -		if (topology.needs_cdm && !dpu_enc->cur_master->hw_cdm)
> -			crtc_state->mode_changed = true;
> -		else if (!topology.needs_cdm && dpu_enc->cur_master->hw_cdm)
> -			crtc_state->mode_changed = true;
> +	} else if (dpu_enc->disp_info.intf_type == INTF_DP) {

You can use disp_info directly here.

> +		if (msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]], adj_mode))
> +			topology.needs_cdm = true;
>   	}
>   
> +	if (topology.needs_cdm && !dpu_enc->cur_master->hw_cdm)
> +		crtc_state->mode_changed = true;
> +	else if (!topology.needs_cdm && dpu_enc->cur_master->hw_cdm)
> +		crtc_state->mode_changed = true;
>   	/*
>   	 * Release and Allocate resources on every modeset
>   	 * Dont allocate when active is false.
> @@ -1111,7 +1116,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>   
>   	dpu_enc->dsc_mask = dsc_mask;
>   
> -	if (dpu_enc->disp_info.intf_type == INTF_WB && conn_state->writeback_job) {
> +	if ((dpu_enc->disp_info.intf_type == INTF_WB && conn_state->writeback_job) ||
> +	    dpu_enc->disp_info.intf_type == INTF_DP) {
>   		struct dpu_hw_blk *hw_cdm = NULL;
>   
>   		dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 17/17] drm/msm/dp: allow YUV420 mode for DP connector when VSC SDP supported
  2024-01-25 19:38 ` [PATCH 17/17] drm/msm/dp: allow YUV420 mode for DP connector when VSC SDP supported Paloma Arellano
@ 2024-01-25 22:05   ` Dmitry Baryshkov
  2024-01-29  3:17     ` Abhinav Kumar
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-25 22:05 UTC (permalink / raw)
  To: Paloma Arellano, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh

On 25/01/2024 21:38, Paloma Arellano wrote:
> All the components of YUV420 over DP are added. Therefore, let's mark the
> connector property as true for DP connector when the DP type is not eDP
> and when VSC SDP is supported.
> 
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>   drivers/gpu/drm/msm/dp/dp_display.c | 5 ++++-
>   1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
> index 4329435518351..97edd607400b8 100644
> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> @@ -370,11 +370,14 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp)
>   
>   	dp_link_process_request(dp->link);
>   
> -	if (!dp->dp_display.is_edp)
> +	if (!dp->dp_display.is_edp) {
> +		if (dp_panel_vsc_sdp_supported(dp->panel))
> +			dp->dp_display.connector->ycbcr_420_allowed = true;

Please consider fixing a TODO in drm_bridge_connector_init().

>   		drm_dp_set_subconnector_property(dp->dp_display.connector,
>   						 connector_status_connected,
>   						 dp->panel->dpcd,
>   						 dp->panel->downstream_ports);
> +	}
>   
>   	edid = dp->panel->edid;
>   

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 10/17] drm/msm/dp: modify dp_catalog_hw_revision to show major and minor val
  2024-01-25 19:38 ` [PATCH 10/17] drm/msm/dp: modify dp_catalog_hw_revision to show major and minor val Paloma Arellano
@ 2024-01-25 22:07   ` Dmitry Baryshkov
  2024-01-28  5:30     ` Paloma Arellano
  2024-01-27 23:43   ` kernel test robot
  2024-01-28 14:02   ` kernel test robot
  2 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-25 22:07 UTC (permalink / raw)
  To: Paloma Arellano, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh

On 25/01/2024 21:38, Paloma Arellano wrote:
> Modify dp_catalog_hw_revision to make the major and minor version values
> known instead of outputting the entire hex value of the hardware version
> register in preparation of using it for VSC SDP programming.
> 
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>   drivers/gpu/drm/msm/dp/dp_catalog.c | 12 +++++++++---
>   drivers/gpu/drm/msm/dp/dp_catalog.h |  2 +-
>   2 files changed, 10 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
> index 5d84c089e520a..c025786170ba5 100644
> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
> @@ -24,6 +24,9 @@
>   #define DP_INTERRUPT_STATUS_ACK_SHIFT	1
>   #define DP_INTERRUPT_STATUS_MASK_SHIFT	2
>   
> +#define DP_HW_VERSION_MAJOR(reg)	FIELD_GET(GENMASK(31, 28), reg)
> +#define DP_HW_VERSION_MINOR(reg)	FIELD_GET(GENMASK(27, 16), reg)
> +
>   #define DP_INTF_CONFIG_DATABUS_WIDEN     BIT(4)
>   
>   #define DP_INTERRUPT_STATUS1 \
> @@ -531,15 +534,18 @@ int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog,
>    *
>    * @dp_catalog: DP catalog structure
>    *
> - * Return: DP controller hw revision
> + * Return: void
>    *
>    */
> -u32 dp_catalog_hw_revision(const struct dp_catalog *dp_catalog)
> +void dp_catalog_hw_revision(const struct dp_catalog *dp_catalog, u16 *major, u16 *minor)
>   {
>   	const struct dp_catalog_private *catalog = container_of(dp_catalog,
>   				struct dp_catalog_private, dp_catalog);
> +	u32 reg_dp_hw_version;
>   
> -	return dp_read_ahb(catalog, REG_DP_HW_VERSION);
> +	reg_dp_hw_version = dp_read_ahb(catalog, REG_DP_HW_VERSION);
> +	*major = DP_HW_VERSION_MAJOR(reg_dp_hw_version);
> +	*minor = DP_HW_VERSION_MINOR(reg_dp_hw_version);

After looking at the code, it might be easier to keep 
dp_catalog_hw_revision as is, add define for hw revision 1.2 and 
corepare to it directly.

>   }
>   
>   /**
> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
> index 563903605b3a7..94c377ef90c35 100644
> --- a/drivers/gpu/drm/msm/dp/dp_catalog.h
> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
> @@ -170,7 +170,7 @@ void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, u32 cc, u32 tb);
>   void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 rate,
>   				u32 stream_rate_khz, bool fixed_nvid, bool is_ycbcr_420);
>   int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog, u32 pattern);
> -u32 dp_catalog_hw_revision(const struct dp_catalog *dp_catalog);
> +void dp_catalog_hw_revision(const struct dp_catalog *dp_catalog, u16 *major, u16 *minor);
>   void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog);
>   bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog *dp_catalog);
>   void dp_catalog_ctrl_enable_irq(struct dp_catalog *dp_catalog, bool enable);

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 01/17] drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP
  2024-01-25 21:14   ` Dmitry Baryshkov
@ 2024-01-27  0:39     ` Paloma Arellano
  2024-01-29  3:06       ` Abhinav Kumar
  0 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-27  0:39 UTC (permalink / raw)
  To: Dmitry Baryshkov, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh


On 1/25/2024 1:14 PM, Dmitry Baryshkov wrote:
> On 25/01/2024 21:38, Paloma Arellano wrote:
>> Generalize dpu_encoder_helper_phys_setup_cdm to be compatible with DP.
>>
>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>> ---
>>   .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  4 +--
>>   .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 31 ++++++++++---------
>>   2 files changed, 18 insertions(+), 17 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>> index 993f263433314..37ac385727c3b 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>> @@ -153,6 +153,7 @@ enum dpu_intr_idx {
>>    * @hw_intf:        Hardware interface to the intf registers
>>    * @hw_wb:        Hardware interface to the wb registers
>>    * @hw_cdm:        Hardware interface to the CDM registers
>> + * @cdm_cfg:    CDM block config needed to store WB/DP block's CDM 
>> configuration
>
> Please realign the description.
Ack
>
>>    * @dpu_kms:        Pointer to the dpu_kms top level
>>    * @cached_mode:    DRM mode cached at mode_set time, acted on in 
>> enable
>>    * @vblank_ctl_lock:    Vblank ctl mutex lock to protect 
>> vblank_refcount
>> @@ -183,6 +184,7 @@ struct dpu_encoder_phys {
>>       struct dpu_hw_intf *hw_intf;
>>       struct dpu_hw_wb *hw_wb;
>>       struct dpu_hw_cdm *hw_cdm;
>> +    struct dpu_hw_cdm_cfg cdm_cfg;
>
> It might be slightly better to move it after all the pointers, so 
> after the dpu_kms.
Ack
>
>>       struct dpu_kms *dpu_kms;
>>       struct drm_display_mode cached_mode;
>>       struct mutex vblank_ctl_lock;
>> @@ -213,7 +215,6 @@ static inline int 
>> dpu_encoder_phys_inc_pending(struct dpu_encoder_phys *phys)
>>    * @wbirq_refcount:     Reference count of writeback interrupt
>>    * @wb_done_timeout_cnt: number of wb done irq timeout errors
>>    * @wb_cfg:  writeback block config to store fb related details
>> - * @cdm_cfg: cdm block config needed to store writeback block's CDM 
>> configuration
>>    * @wb_conn: backpointer to writeback connector
>>    * @wb_job: backpointer to current writeback job
>>    * @dest:   dpu buffer layout for current writeback output buffer
>> @@ -223,7 +224,6 @@ struct dpu_encoder_phys_wb {
>>       atomic_t wbirq_refcount;
>>       int wb_done_timeout_cnt;
>>       struct dpu_hw_wb_cfg wb_cfg;
>> -    struct dpu_hw_cdm_cfg cdm_cfg;
>>       struct drm_writeback_connector *wb_conn;
>>       struct drm_writeback_job *wb_job;
>>       struct dpu_hw_fmt_layout dest;
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>> index 4cd2d9e3131a4..072fc6950e496 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>> @@ -269,28 +269,21 @@ static void 
>> dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
>>    *                                     This API does not handle 
>> DPU_CHROMA_H1V2.
>>    * @phys_enc:Pointer to physical encoder
>>    */
>> -static void dpu_encoder_helper_phys_setup_cdm(struct 
>> dpu_encoder_phys *phys_enc)
>> +static void dpu_encoder_helper_phys_setup_cdm(struct 
>> dpu_encoder_phys *phys_enc,
>> +                          const struct dpu_format *dpu_fmt,
>> +                          u32 output_type)
>>   {
>>       struct dpu_hw_cdm *hw_cdm;
>>       struct dpu_hw_cdm_cfg *cdm_cfg;
>>       struct dpu_hw_pingpong *hw_pp;
>> -    struct dpu_encoder_phys_wb *wb_enc;
>> -    const struct msm_format *format;
>> -    const struct dpu_format *dpu_fmt;
>> -    struct drm_writeback_job *wb_job;
>>       int ret;
>>         if (!phys_enc)
>>           return;
>>   -    wb_enc = to_dpu_encoder_phys_wb(phys_enc);
>> -    cdm_cfg = &wb_enc->cdm_cfg;
>> +    cdm_cfg = &phys_enc->cdm_cfg;
>>       hw_pp = phys_enc->hw_pp;
>>       hw_cdm = phys_enc->hw_cdm;
>> -    wb_job = wb_enc->wb_job;
>> -
>> -    format = msm_framebuffer_format(wb_enc->wb_job->fb);
>> -    dpu_fmt = dpu_get_dpu_format_ext(format->pixel_format, 
>> wb_job->fb->modifier);
>>         if (!hw_cdm)
>>           return;
>> @@ -306,10 +299,10 @@ static void 
>> dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
>>         memset(cdm_cfg, 0, sizeof(struct dpu_hw_cdm_cfg));
>>   -    cdm_cfg->output_width = wb_job->fb->width;
>> -    cdm_cfg->output_height = wb_job->fb->height;
>> +    cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
>> +    cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
>
> This is a semantic change. Instead of passing the FB size, this passes 
> the mode dimensions. They are not guaranteed to be the same, 
> especially for the WB case.
>
>>       cdm_cfg->output_fmt = dpu_fmt;
>> -    cdm_cfg->output_type = CDM_CDWN_OUTPUT_WB;
>> +    cdm_cfg->output_type = output_type;
>>       cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
>>               CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
>>       cdm_cfg->csc_cfg = &dpu_csc10_rgb2yuv_601l;
>> @@ -462,6 +455,14 @@ static void dpu_encoder_phys_wb_setup(
>>       struct dpu_hw_wb *hw_wb = phys_enc->hw_wb;
>>       struct drm_display_mode mode = phys_enc->cached_mode;
>>       struct drm_framebuffer *fb = NULL;
>> +    struct dpu_encoder_phys_wb *wb_enc = 
>> to_dpu_encoder_phys_wb(phys_enc);
>> +    struct drm_writeback_job *wb_job;
>> +    const struct msm_format *format;
>> +    const struct dpu_format *dpu_fmt;
>> +
>> +    wb_job = wb_enc->wb_job;
>> +    format = msm_framebuffer_format(wb_enc->wb_job->fb);
>> +    dpu_fmt = dpu_get_dpu_format_ext(format->pixel_format, 
>> wb_job->fb->modifier);
>>         DPU_DEBUG("[mode_set:%d, \"%s\",%d,%d]\n",
>>               hw_wb->idx - WB_0, mode.name,
>> @@ -475,7 +476,7 @@ static void dpu_encoder_phys_wb_setup(
>>         dpu_encoder_phys_wb_setup_fb(phys_enc, fb);
>>   -    dpu_encoder_helper_phys_setup_cdm(phys_enc);
>> +    dpu_encoder_helper_phys_setup_cdm(phys_enc, dpu_fmt, 
>> CDM_CDWN_OUTPUT_WB);
>>         dpu_encoder_phys_wb_setup_ctl(phys_enc);
>>   }
>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 02/17] drm/msm/dpu: move dpu_encoder_helper_phys_setup_cdm to dpu_encoder
  2024-01-25 21:16   ` Dmitry Baryshkov
@ 2024-01-27  0:43     ` Paloma Arellano
  2024-01-27  2:26       ` Dmitry Baryshkov
  0 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-27  0:43 UTC (permalink / raw)
  To: Dmitry Baryshkov, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh


On 1/25/2024 1:16 PM, Dmitry Baryshkov wrote:
> On 25/01/2024 21:38, Paloma Arellano wrote:
>> Move dpu_encoder_helper_phys_setup_cdm to dpu_encoder in preparation for
>> implementing CDM compatibility for DP.
>
> Nit: s/CDM compatibility/YUV support/. It might make sense to spell it 
> out that YUV over DP requires CDM.
Ack
>
>>
>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 78 +++++++++++++++++
>>   .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  9 ++
>>   .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 84 -------------------
>>   3 files changed, 87 insertions(+), 84 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> index 83380bc92a00a..6cef98f046ea6 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> @@ -2114,6 +2114,84 @@ void dpu_encoder_helper_phys_cleanup(struct 
>> dpu_encoder_phys *phys_enc)
>>       ctl->ops.clear_pending_flush(ctl);
>>   }
>>   +void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys 
>> *phys_enc,
>> +                       const struct dpu_format *dpu_fmt,
>> +                       u32 output_type)
>
> My email client suggests that the parameters are not idented properly 
> anymore.
On my editor it appears to be aligned correctly. Running checkpatch.pl 
doesn't give any warnings either. So perhaps it's the email client.
>
>> +{
>> +    struct dpu_hw_cdm *hw_cdm;
>> +    struct dpu_hw_cdm_cfg *cdm_cfg;
>> +    struct dpu_hw_pingpong *hw_pp;
>> +    int ret;
>> +
>> +    if (!phys_enc)
>> +        return;
>> +
>> +    cdm_cfg = &phys_enc->cdm_cfg;
>> +    hw_pp = phys_enc->hw_pp;
>> +    hw_cdm = phys_enc->hw_cdm;
>> +
>> +    if (!hw_cdm)
>> +        return;
>> +
>> +    if (!DPU_FORMAT_IS_YUV(dpu_fmt)) {
>> +        DPU_DEBUG("[enc:%d] cdm_disable fmt:%x\n", 
>> DRMID(phys_enc->parent),
>> +              dpu_fmt->base.pixel_format);
>> +        if (hw_cdm->ops.bind_pingpong_blk)
>> +            hw_cdm->ops.bind_pingpong_blk(hw_cdm, PINGPONG_NONE);
>> +
>> +        return;
>> +    }
>> +
>> +    memset(cdm_cfg, 0, sizeof(struct dpu_hw_cdm_cfg));
>> +
>> +    cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
>> +    cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
>> +    cdm_cfg->output_fmt = dpu_fmt;
>> +    cdm_cfg->output_type = output_type;
>> +    cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
>> +            CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
>> +    cdm_cfg->csc_cfg = &dpu_csc10_rgb2yuv_601l;
>> +
>> +    /* enable 10 bit logic */
>> +    switch (cdm_cfg->output_fmt->chroma_sample) {
>> +    case DPU_CHROMA_RGB:
>> +        cdm_cfg->h_cdwn_type = CDM_CDWN_DISABLE;
>> +        cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
>> +        break;
>> +    case DPU_CHROMA_H2V1:
>> +        cdm_cfg->h_cdwn_type = CDM_CDWN_COSITE;
>> +        cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
>> +        break;
>> +    case DPU_CHROMA_420:
>> +        cdm_cfg->h_cdwn_type = CDM_CDWN_COSITE;
>> +        cdm_cfg->v_cdwn_type = CDM_CDWN_OFFSITE;
>> +        break;
>> +    case DPU_CHROMA_H1V2:
>> +    default:
>> +        DPU_ERROR("[enc:%d] unsupported chroma sampling type\n",
>> +              DRMID(phys_enc->parent));
>> +        cdm_cfg->h_cdwn_type = CDM_CDWN_DISABLE;
>> +        cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
>> +        break;
>> +    }
>> +
>> +    DPU_DEBUG("[enc:%d] cdm_enable:%d,%d,%X,%d,%d,%d,%d]\n",
>> +          DRMID(phys_enc->parent), cdm_cfg->output_width,
>> +          cdm_cfg->output_height, 
>> cdm_cfg->output_fmt->base.pixel_format,
>> +          cdm_cfg->output_type, cdm_cfg->output_bit_depth,
>> +          cdm_cfg->h_cdwn_type, cdm_cfg->v_cdwn_type);
>> +
>> +    if (hw_cdm->ops.enable) {
>> +        cdm_cfg->pp_id = hw_pp->idx;
>> +        ret = hw_cdm->ops.enable(hw_cdm, cdm_cfg);
>> +        if (ret < 0) {
>> +            DPU_ERROR("[enc:%d] failed to enable CDM; ret:%d\n",
>> +                  DRMID(phys_enc->parent), ret);
>> +            return;
>> +        }
>> +    }
>> +}
>> +
>>   #ifdef CONFIG_DEBUG_FS
>>   static int _dpu_encoder_status_show(struct seq_file *s, void *data)
>>   {
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>> index 37ac385727c3b..310944303a056 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>> @@ -381,6 +381,15 @@ int dpu_encoder_helper_wait_for_irq(struct 
>> dpu_encoder_phys *phys_enc,
>>    */
>>   void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys 
>> *phys_enc);
>>   +/**
>> + * dpu_encoder_helper_phys_setup_cdm - setup chroma down sampling block
>> + * @phys_enc: Pointer to physical encoder
>> + * @output_type: HDMI/WB
>> + */
>> +void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys 
>> *phys_enc,
>> +                       const struct dpu_format *dpu_fmt,
>> +                       u32 output_type);
>
> Again, indentation.
See comment above
>
>> +
>>   /**
>>    * dpu_encoder_vblank_callback - Notify virtual encoder of vblank 
>> IRQ reception
>>    * @drm_enc:    Pointer to drm encoder structure
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>> index 072fc6950e496..400580847bde7 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>> @@ -264,89 +264,6 @@ static void dpu_encoder_phys_wb_setup_ctl(struct 
>> dpu_encoder_phys *phys_enc)
>>       }
>>   }
>>   -/**
>> - * dpu_encoder_helper_phys_setup_cdm - setup chroma down sampling block
>> - *                                     This API does not handle 
>> DPU_CHROMA_H1V2.
>> - * @phys_enc:Pointer to physical encoder
>> - */
>> -static void dpu_encoder_helper_phys_setup_cdm(struct 
>> dpu_encoder_phys *phys_enc,
>> -                          const struct dpu_format *dpu_fmt,
>> -                          u32 output_type)
>> -{
>> -    struct dpu_hw_cdm *hw_cdm;
>> -    struct dpu_hw_cdm_cfg *cdm_cfg;
>> -    struct dpu_hw_pingpong *hw_pp;
>> -    int ret;
>> -
>> -    if (!phys_enc)
>> -        return;
>> -
>> -    cdm_cfg = &phys_enc->cdm_cfg;
>> -    hw_pp = phys_enc->hw_pp;
>> -    hw_cdm = phys_enc->hw_cdm;
>> -
>> -    if (!hw_cdm)
>> -        return;
>> -
>> -    if (!DPU_FORMAT_IS_YUV(dpu_fmt)) {
>> -        DPU_DEBUG("[enc:%d] cdm_disable fmt:%x\n", 
>> DRMID(phys_enc->parent),
>> -              dpu_fmt->base.pixel_format);
>> -        if (hw_cdm->ops.bind_pingpong_blk)
>> -            hw_cdm->ops.bind_pingpong_blk(hw_cdm, PINGPONG_NONE);
>> -
>> -        return;
>> -    }
>> -
>> -    memset(cdm_cfg, 0, sizeof(struct dpu_hw_cdm_cfg));
>> -
>> -    cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
>> -    cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
>> -    cdm_cfg->output_fmt = dpu_fmt;
>> -    cdm_cfg->output_type = output_type;
>> -    cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
>> -            CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
>> -    cdm_cfg->csc_cfg = &dpu_csc10_rgb2yuv_601l;
>> -
>> -    /* enable 10 bit logic */
>> -    switch (cdm_cfg->output_fmt->chroma_sample) {
>> -    case DPU_CHROMA_RGB:
>> -        cdm_cfg->h_cdwn_type = CDM_CDWN_DISABLE;
>> -        cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
>> -        break;
>> -    case DPU_CHROMA_H2V1:
>> -        cdm_cfg->h_cdwn_type = CDM_CDWN_COSITE;
>> -        cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
>> -        break;
>> -    case DPU_CHROMA_420:
>> -        cdm_cfg->h_cdwn_type = CDM_CDWN_COSITE;
>> -        cdm_cfg->v_cdwn_type = CDM_CDWN_OFFSITE;
>> -        break;
>> -    case DPU_CHROMA_H1V2:
>> -    default:
>> -        DPU_ERROR("[enc:%d] unsupported chroma sampling type\n",
>> -              DRMID(phys_enc->parent));
>> -        cdm_cfg->h_cdwn_type = CDM_CDWN_DISABLE;
>> -        cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE;
>> -        break;
>> -    }
>> -
>> -    DPU_DEBUG("[enc:%d] cdm_enable:%d,%d,%X,%d,%d,%d,%d]\n",
>> -          DRMID(phys_enc->parent), cdm_cfg->output_width,
>> -          cdm_cfg->output_height, 
>> cdm_cfg->output_fmt->base.pixel_format,
>> -          cdm_cfg->output_type, cdm_cfg->output_bit_depth,
>> -          cdm_cfg->h_cdwn_type, cdm_cfg->v_cdwn_type);
>> -
>> -    if (hw_cdm->ops.enable) {
>> -        cdm_cfg->pp_id = hw_pp->idx;
>> -        ret = hw_cdm->ops.enable(hw_cdm, cdm_cfg);
>> -        if (ret < 0) {
>> -            DPU_ERROR("[enc:%d] failed to enable CDM; ret:%d\n",
>> -                  DRMID(phys_enc->parent), ret);
>> -            return;
>> -        }
>> -    }
>> -}
>> -
>>   /**
>>    * dpu_encoder_phys_wb_atomic_check - verify and fixup given atomic 
>> states
>>    * @phys_enc:    Pointer to physical encoder
>> @@ -399,7 +316,6 @@ static int dpu_encoder_phys_wb_atomic_check(
>>       return 
>> drm_atomic_helper_check_wb_connector_state(conn_state->connector, 
>> conn_state->state);
>>   }
>>   -
>
> irrelevant, please drop.
Ack
>
>>   /**
>>    * _dpu_encoder_phys_wb_update_flush - flush hardware update
>>    * @phys_enc:    Pointer to physical encoder
>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 04/17] drm/msm/dp: store mode YUV420 information to be used by rest of DP
  2024-01-25 21:20   ` Dmitry Baryshkov
@ 2024-01-27  0:48     ` Paloma Arellano
  2024-01-27  2:29       ` Dmitry Baryshkov
  0 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-27  0:48 UTC (permalink / raw)
  To: Dmitry Baryshkov, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh


On 1/25/2024 1:20 PM, Dmitry Baryshkov wrote:
> On 25/01/2024 21:38, Paloma Arellano wrote:
>> Wide bus is not supported when the mode is YUV420 in DP. In preparation
>> for changing the DPU programming to reflect this, the value and
>> assignment location of wide_bus_en for the DP submodules must be
>> changed. Move it from boot time in dp_init_sub_modules() to run time in
>> dp_display_mode_set.
>>
>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/dp/dp_display.c | 17 +++++++++++++----
>>   drivers/gpu/drm/msm/dp/dp_panel.h   |  1 +
>>   2 files changed, 14 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
>> b/drivers/gpu/drm/msm/dp/dp_display.c
>> index 9df2a8b21021e..ddac55f45a722 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
>> @@ -784,10 +784,6 @@ static int dp_init_sub_modules(struct 
>> dp_display_private *dp)
>>           goto error_ctrl;
>>       }
>>   -    /* populate wide_bus_supported to different layers */
>> -    dp->ctrl->wide_bus_en = dp->wide_bus_supported;
>> -    dp->catalog->wide_bus_en = dp->wide_bus_supported;
>> -
>>       return rc;
>>     error_ctrl:
>> @@ -808,6 +804,7 @@ static int dp_display_set_mode(struct msm_dp 
>> *dp_display,
>>       drm_mode_copy(&dp->panel->dp_mode.drm_mode, &mode->drm_mode);
>>       dp->panel->dp_mode.bpp = mode->bpp;
>>       dp->panel->dp_mode.capabilities = mode->capabilities;
>> +    dp->panel->dp_mode.out_fmt_is_yuv_420 = mode->out_fmt_is_yuv_420;
>
> Why do we need it in dp_panel too?
Not sure if you saw in the other later patches, but I use the 
out_fmt_is_yuv_420 derived from dp_panel throughout dp_ctrl.c and dp_panel.c
>
>> dp_panel_init_panel_info(dp->panel);
>>       return 0;
>>   }
>> @@ -1402,6 +1399,9 @@ bool msm_dp_wide_bus_available(const struct 
>> msm_dp *dp_display)
>>         dp = container_of(dp_display, struct dp_display_private, 
>> dp_display);
>>   +    if (dp->dp_mode.out_fmt_is_yuv_420)
>> +        return false;
>> +
>>       return dp->wide_bus_supported;
>>   }
>>   @@ -1615,6 +1615,15 @@ void dp_bridge_mode_set(struct drm_bridge 
>> *drm_bridge,
>>         dp_display->dp_mode.h_active_low =
>>           !!(dp_display->dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC);
>> +
>> +    dp_display->dp_mode.out_fmt_is_yuv_420 =
>> + drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode);
>> +
>> +    /* populate wide_bus_support to different layers */
>> +    dp_display->ctrl->wide_bus_en =
>> +        dp_display->dp_mode.out_fmt_is_yuv_420 ? false : 
>> dp_display->wide_bus_supported;
>> +    dp_display->catalog->wide_bus_en =
>> +        dp_display->dp_mode.out_fmt_is_yuv_420 ? false : 
>> dp_display->wide_bus_supported;
>>   }
>>     void dp_bridge_hpd_enable(struct drm_bridge *bridge)
>> diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h 
>> b/drivers/gpu/drm/msm/dp/dp_panel.h
>> index a0dfc579c5f9f..6ec68be9f2366 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_panel.h
>> +++ b/drivers/gpu/drm/msm/dp/dp_panel.h
>> @@ -19,6 +19,7 @@ struct dp_display_mode {
>>       u32 bpp;
>>       u32 h_active_low;
>>       u32 v_active_low;
>> +    bool out_fmt_is_yuv_420;
>>   };
>>     struct dp_panel_in {
>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 05/17] drm/msm/dp: add an API to indicate if sink supports VSC SDP
  2024-01-25 21:23   ` Dmitry Baryshkov
@ 2024-01-27  0:58     ` Paloma Arellano
  2024-01-27  2:40       ` Dmitry Baryshkov
  0 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-27  0:58 UTC (permalink / raw)
  To: Dmitry Baryshkov, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh


On 1/25/2024 1:23 PM, Dmitry Baryshkov wrote:
> On 25/01/2024 21:38, Paloma Arellano wrote:
>> YUV420 format is supported only in the VSC SDP packet and not through
>> MSA. Hence add an API which indicates the sink support which can be used
>> by the rest of the DP programming.
>
> This API ideally should go to drm/display/drm_dp_helper.c
I'm not familiar how other vendors are checking if VSC SDP is supported. 
So in moving this API, I'm going to let the other vendors make the 
changes themselves.
>
>>
>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/dp/dp_display.c |  3 ++-
>>   drivers/gpu/drm/msm/dp/dp_panel.c   | 35 +++++++++++++++++++++++++----
>>   drivers/gpu/drm/msm/dp/dp_panel.h   |  1 +
>>   3 files changed, 34 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
>> b/drivers/gpu/drm/msm/dp/dp_display.c
>> index ddac55f45a722..f6b3b6ca242f8 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
>> @@ -1617,7 +1617,8 @@ void dp_bridge_mode_set(struct drm_bridge 
>> *drm_bridge,
>>           !!(dp_display->dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC);
>>         dp_display->dp_mode.out_fmt_is_yuv_420 =
>> - drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode);
>> + drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode) &&
>> +        dp_panel_vsc_sdp_supported(dp_display->panel);
>>         /* populate wide_bus_support to different layers */
>>       dp_display->ctrl->wide_bus_en =
>> diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c 
>> b/drivers/gpu/drm/msm/dp/dp_panel.c
>> index 127f6af995cd1..af7820b6d35ec 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_panel.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_panel.c
>> @@ -17,6 +17,9 @@ struct dp_panel_private {
>>       struct dp_link *link;
>>       struct dp_catalog *catalog;
>>       bool panel_on;
>> +    bool vsc_supported;
>> +    u8 major;
>> +    u8 minor;
>>   };
>>     static void dp_panel_read_psr_cap(struct dp_panel_private *panel)
>> @@ -43,9 +46,10 @@ static void dp_panel_read_psr_cap(struct 
>> dp_panel_private *panel)
>>   static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
>>   {
>>       int rc;
>> +    ssize_t rlen;
>>       struct dp_panel_private *panel;
>>       struct dp_link_info *link_info;
>> -    u8 *dpcd, major, minor;
>> +    u8 *dpcd, rx_feature;
>>         panel = container_of(dp_panel, struct dp_panel_private, 
>> dp_panel);
>>       dpcd = dp_panel->dpcd;
>> @@ -53,10 +57,19 @@ static int dp_panel_read_dpcd(struct dp_panel 
>> *dp_panel)
>>       if (rc)
>>           return rc;
>>   +    rlen = drm_dp_dpcd_read(panel->aux, 
>> DP_DPRX_FEATURE_ENUMERATION_LIST, &rx_feature, 1);
>> +    if (rlen != 1) {
>> +        panel->vsc_supported = false;
>> +        pr_debug("failed to read DP_DPRX_FEATURE_ENUMERATION_LIST\n");
>> +    } else {
>> +        panel->vsc_supported = !!(rx_feature & 
>> DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED);
>> +        pr_debug("vsc=%d\n", panel->vsc_supported);
>> +    }
>> +
>>       link_info = &dp_panel->link_info;
>>       link_info->revision = dpcd[DP_DPCD_REV];
>> -    major = (link_info->revision >> 4) & 0x0f;
>> -    minor = link_info->revision & 0x0f;
>> +    panel->major = (link_info->revision >> 4) & 0x0f;
>> +    panel->minor = link_info->revision & 0x0f;
>>         link_info->rate = drm_dp_max_link_rate(dpcd);
>>       link_info->num_lanes = drm_dp_max_lane_count(dpcd);
>> @@ -69,7 +82,7 @@ static int dp_panel_read_dpcd(struct dp_panel 
>> *dp_panel)
>>       if (link_info->rate > dp_panel->max_dp_link_rate)
>>           link_info->rate = dp_panel->max_dp_link_rate;
>>   -    drm_dbg_dp(panel->drm_dev, "version: %d.%d\n", major, minor);
>> +    drm_dbg_dp(panel->drm_dev, "version: %d.%d\n", panel->major, 
>> panel->minor);
>>       drm_dbg_dp(panel->drm_dev, "link_rate=%d\n", link_info->rate);
>>       drm_dbg_dp(panel->drm_dev, "lane_count=%d\n", 
>> link_info->num_lanes);
>>   @@ -280,6 +293,20 @@ void dp_panel_tpg_config(struct dp_panel 
>> *dp_panel, bool enable)
>>       dp_catalog_panel_tpg_enable(catalog, 
>> &panel->dp_panel.dp_mode.drm_mode);
>>   }
>>   +bool dp_panel_vsc_sdp_supported(struct dp_panel *dp_panel)
>> +{
>> +    struct dp_panel_private *panel;
>> +
>> +    if (!dp_panel) {
>> +        pr_err("invalid input\n");
>> +        return false;
>> +    }
>> +
>> +    panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
>> +
>> +    return panel->major >= 1 && panel->minor >= 3 && 
>> panel->vsc_supported;
>> +}
>> +
>>   void dp_panel_dump_regs(struct dp_panel *dp_panel)
>>   {
>>       struct dp_catalog *catalog;
>> diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h 
>> b/drivers/gpu/drm/msm/dp/dp_panel.h
>> index 6ec68be9f2366..590eca5ce304b 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_panel.h
>> +++ b/drivers/gpu/drm/msm/dp/dp_panel.h
>> @@ -66,6 +66,7 @@ int dp_panel_get_modes(struct dp_panel *dp_panel,
>>           struct drm_connector *connector);
>>   void dp_panel_handle_sink_request(struct dp_panel *dp_panel);
>>   void dp_panel_tpg_config(struct dp_panel *dp_panel, bool enable);
>> +bool dp_panel_vsc_sdp_supported(struct dp_panel *dp_panel);
>>     /**
>>    * is_link_rate_valid() - validates the link rate
>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 02/17] drm/msm/dpu: move dpu_encoder_helper_phys_setup_cdm to dpu_encoder
  2024-01-27  0:43     ` Paloma Arellano
@ 2024-01-27  2:26       ` Dmitry Baryshkov
  0 siblings, 0 replies; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-27  2:26 UTC (permalink / raw)
  To: Paloma Arellano
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh, freedreno

On Sat, 27 Jan 2024 at 02:44, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>
>
> On 1/25/2024 1:16 PM, Dmitry Baryshkov wrote:
> > On 25/01/2024 21:38, Paloma Arellano wrote:
> >> Move dpu_encoder_helper_phys_setup_cdm to dpu_encoder in preparation for
> >> implementing CDM compatibility for DP.
> >
> > Nit: s/CDM compatibility/YUV support/. It might make sense to spell it
> > out that YUV over DP requires CDM.
> Ack
> >
> >>
> >> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >> ---
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 78 +++++++++++++++++
> >>   .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  9 ++
> >>   .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 84 -------------------
> >>   3 files changed, 87 insertions(+), 84 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> index 83380bc92a00a..6cef98f046ea6 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> @@ -2114,6 +2114,84 @@ void dpu_encoder_helper_phys_cleanup(struct
> >> dpu_encoder_phys *phys_enc)
> >>       ctl->ops.clear_pending_flush(ctl);
> >>   }
> >>   +void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys
> >> *phys_enc,
> >> +                       const struct dpu_format *dpu_fmt,
> >> +                       u32 output_type)
> >
> > My email client suggests that the parameters are not idented properly
> > anymore.
> On my editor it appears to be aligned correctly. Running checkpatch.pl
> doesn't give any warnings either. So perhaps it's the email client.

Checked, you are correct here.

> >

[skipped]

> >>    * dpu_encoder_phys_wb_atomic_check - verify and fixup given atomic
> >> states
> >>    * @phys_enc:    Pointer to physical encoder
> >> @@ -399,7 +316,6 @@ static int dpu_encoder_phys_wb_atomic_check(
> >>       return
> >> drm_atomic_helper_check_wb_connector_state(conn_state->connector,
> >> conn_state->state);
> >>   }
> >>   -
> >
> > irrelevant, please drop.
> Ack

With this fixed:

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

> >
> >>   /**
> >>    * _dpu_encoder_phys_wb_update_flush - flush hardware update
> >>    * @phys_enc:    Pointer to physical encoder
> >



-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 04/17] drm/msm/dp: store mode YUV420 information to be used by rest of DP
  2024-01-27  0:48     ` Paloma Arellano
@ 2024-01-27  2:29       ` Dmitry Baryshkov
  0 siblings, 0 replies; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-27  2:29 UTC (permalink / raw)
  To: Paloma Arellano
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh, freedreno

On Sat, 27 Jan 2024 at 02:48, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>
>
> On 1/25/2024 1:20 PM, Dmitry Baryshkov wrote:
> > On 25/01/2024 21:38, Paloma Arellano wrote:
> >> Wide bus is not supported when the mode is YUV420 in DP. In preparation
> >> for changing the DPU programming to reflect this, the value and
> >> assignment location of wide_bus_en for the DP submodules must be
> >> changed. Move it from boot time in dp_init_sub_modules() to run time in
> >> dp_display_mode_set.
> >>
> >> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >> ---
> >>   drivers/gpu/drm/msm/dp/dp_display.c | 17 +++++++++++++----
> >>   drivers/gpu/drm/msm/dp/dp_panel.h   |  1 +
> >>   2 files changed, 14 insertions(+), 4 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
> >> b/drivers/gpu/drm/msm/dp/dp_display.c
> >> index 9df2a8b21021e..ddac55f45a722 100644
> >> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> >> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> >> @@ -784,10 +784,6 @@ static int dp_init_sub_modules(struct
> >> dp_display_private *dp)
> >>           goto error_ctrl;
> >>       }
> >>   -    /* populate wide_bus_supported to different layers */
> >> -    dp->ctrl->wide_bus_en = dp->wide_bus_supported;
> >> -    dp->catalog->wide_bus_en = dp->wide_bus_supported;
> >> -
> >>       return rc;
> >>     error_ctrl:
> >> @@ -808,6 +804,7 @@ static int dp_display_set_mode(struct msm_dp
> >> *dp_display,
> >>       drm_mode_copy(&dp->panel->dp_mode.drm_mode, &mode->drm_mode);
> >>       dp->panel->dp_mode.bpp = mode->bpp;
> >>       dp->panel->dp_mode.capabilities = mode->capabilities;
> >> +    dp->panel->dp_mode.out_fmt_is_yuv_420 = mode->out_fmt_is_yuv_420;
> >
> > Why do we need it in dp_panel too?
> Not sure if you saw in the other later patches, but I use the
> out_fmt_is_yuv_420 derived from dp_panel throughout dp_ctrl.c and dp_panel.c

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

> >
> >> dp_panel_init_panel_info(dp->panel);
> >>       return 0;
> >>   }


-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 05/17] drm/msm/dp: add an API to indicate if sink supports VSC SDP
  2024-01-27  0:58     ` Paloma Arellano
@ 2024-01-27  2:40       ` Dmitry Baryshkov
  2024-01-27  3:57         ` Abhinav Kumar
  2024-01-29 23:20         ` Paloma Arellano
  0 siblings, 2 replies; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-27  2:40 UTC (permalink / raw)
  To: Paloma Arellano
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh, freedreno

On Sat, 27 Jan 2024 at 02:58, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>
>
> On 1/25/2024 1:23 PM, Dmitry Baryshkov wrote:
> > On 25/01/2024 21:38, Paloma Arellano wrote:
> >> YUV420 format is supported only in the VSC SDP packet and not through
> >> MSA. Hence add an API which indicates the sink support which can be used
> >> by the rest of the DP programming.
> >
> > This API ideally should go to drm/display/drm_dp_helper.c
> I'm not familiar how other vendors are checking if VSC SDP is supported.
> So in moving this API, I'm going to let the other vendors make the
> changes themselves.

Let me show it for you:

bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp)
{
        u8 dprx = 0;

        if (drm_dp_dpcd_readb(&intel_dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST,
                              &dprx) != 1)
                return false;
        return dprx & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED;
}


> >
> >>
> >> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >> ---
> >>   drivers/gpu/drm/msm/dp/dp_display.c |  3 ++-
> >>   drivers/gpu/drm/msm/dp/dp_panel.c   | 35 +++++++++++++++++++++++++----
> >>   drivers/gpu/drm/msm/dp/dp_panel.h   |  1 +
> >>   3 files changed, 34 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
> >> b/drivers/gpu/drm/msm/dp/dp_display.c
> >> index ddac55f45a722..f6b3b6ca242f8 100644
> >> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> >> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> >> @@ -1617,7 +1617,8 @@ void dp_bridge_mode_set(struct drm_bridge
> >> *drm_bridge,
> >>           !!(dp_display->dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC);
> >>         dp_display->dp_mode.out_fmt_is_yuv_420 =
> >> - drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode);
> >> + drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode) &&
> >> +        dp_panel_vsc_sdp_supported(dp_display->panel);
> >>         /* populate wide_bus_support to different layers */
> >>       dp_display->ctrl->wide_bus_en =
> >> diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c
> >> b/drivers/gpu/drm/msm/dp/dp_panel.c
> >> index 127f6af995cd1..af7820b6d35ec 100644
> >> --- a/drivers/gpu/drm/msm/dp/dp_panel.c
> >> +++ b/drivers/gpu/drm/msm/dp/dp_panel.c
> >> @@ -17,6 +17,9 @@ struct dp_panel_private {
> >>       struct dp_link *link;
> >>       struct dp_catalog *catalog;
> >>       bool panel_on;
> >> +    bool vsc_supported;
> >> +    u8 major;
> >> +    u8 minor;
> >>   };
> >>     static void dp_panel_read_psr_cap(struct dp_panel_private *panel)
> >> @@ -43,9 +46,10 @@ static void dp_panel_read_psr_cap(struct
> >> dp_panel_private *panel)
> >>   static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
> >>   {
> >>       int rc;
> >> +    ssize_t rlen;
> >>       struct dp_panel_private *panel;
> >>       struct dp_link_info *link_info;
> >> -    u8 *dpcd, major, minor;
> >> +    u8 *dpcd, rx_feature;
> >>         panel = container_of(dp_panel, struct dp_panel_private,
> >> dp_panel);
> >>       dpcd = dp_panel->dpcd;
> >> @@ -53,10 +57,19 @@ static int dp_panel_read_dpcd(struct dp_panel
> >> *dp_panel)
> >>       if (rc)
> >>           return rc;
> >>   +    rlen = drm_dp_dpcd_read(panel->aux,
> >> DP_DPRX_FEATURE_ENUMERATION_LIST, &rx_feature, 1);
> >> +    if (rlen != 1) {
> >> +        panel->vsc_supported = false;
> >> +        pr_debug("failed to read DP_DPRX_FEATURE_ENUMERATION_LIST\n");
> >> +    } else {
> >> +        panel->vsc_supported = !!(rx_feature &
> >> DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED);
> >> +        pr_debug("vsc=%d\n", panel->vsc_supported);
> >> +    }
> >> +
> >>       link_info = &dp_panel->link_info;
> >>       link_info->revision = dpcd[DP_DPCD_REV];
> >> -    major = (link_info->revision >> 4) & 0x0f;
> >> -    minor = link_info->revision & 0x0f;
> >> +    panel->major = (link_info->revision >> 4) & 0x0f;
> >> +    panel->minor = link_info->revision & 0x0f;
> >>         link_info->rate = drm_dp_max_link_rate(dpcd);
> >>       link_info->num_lanes = drm_dp_max_lane_count(dpcd);
> >> @@ -69,7 +82,7 @@ static int dp_panel_read_dpcd(struct dp_panel
> >> *dp_panel)
> >>       if (link_info->rate > dp_panel->max_dp_link_rate)
> >>           link_info->rate = dp_panel->max_dp_link_rate;
> >>   -    drm_dbg_dp(panel->drm_dev, "version: %d.%d\n", major, minor);
> >> +    drm_dbg_dp(panel->drm_dev, "version: %d.%d\n", panel->major,
> >> panel->minor);
> >>       drm_dbg_dp(panel->drm_dev, "link_rate=%d\n", link_info->rate);
> >>       drm_dbg_dp(panel->drm_dev, "lane_count=%d\n",
> >> link_info->num_lanes);
> >>   @@ -280,6 +293,20 @@ void dp_panel_tpg_config(struct dp_panel
> >> *dp_panel, bool enable)
> >>       dp_catalog_panel_tpg_enable(catalog,
> >> &panel->dp_panel.dp_mode.drm_mode);
> >>   }
> >>   +bool dp_panel_vsc_sdp_supported(struct dp_panel *dp_panel)
> >> +{
> >> +    struct dp_panel_private *panel;
> >> +
> >> +    if (!dp_panel) {
> >> +        pr_err("invalid input\n");
> >> +        return false;
> >> +    }
> >> +
> >> +    panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
> >> +
> >> +    return panel->major >= 1 && panel->minor >= 3 &&
> >> panel->vsc_supported;

Anyway, this check is incorrect. Please compare the whole revision
against DP_DPCD_REV_13 instead of doing a maj/min comparison.

> >> +}
> >> +
> >>   void dp_panel_dump_regs(struct dp_panel *dp_panel)
> >>   {
> >>       struct dp_catalog *catalog;
> >> diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h
> >> b/drivers/gpu/drm/msm/dp/dp_panel.h
> >> index 6ec68be9f2366..590eca5ce304b 100644
> >> --- a/drivers/gpu/drm/msm/dp/dp_panel.h
> >> +++ b/drivers/gpu/drm/msm/dp/dp_panel.h
> >> @@ -66,6 +66,7 @@ int dp_panel_get_modes(struct dp_panel *dp_panel,
> >>           struct drm_connector *connector);
> >>   void dp_panel_handle_sink_request(struct dp_panel *dp_panel);
> >>   void dp_panel_tpg_config(struct dp_panel *dp_panel, bool enable);
> >> +bool dp_panel_vsc_sdp_supported(struct dp_panel *dp_panel);
> >>     /**
> >>    * is_link_rate_valid() - validates the link rate
> >



-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 05/17] drm/msm/dp: add an API to indicate if sink supports VSC SDP
  2024-01-27  2:40       ` Dmitry Baryshkov
@ 2024-01-27  3:57         ` Abhinav Kumar
  2024-01-27  5:31           ` Dmitry Baryshkov
  2024-01-29 23:20         ` Paloma Arellano
  1 sibling, 1 reply; 95+ messages in thread
From: Abhinav Kumar @ 2024-01-27  3:57 UTC (permalink / raw)
  To: Dmitry Baryshkov, Paloma Arellano
  Cc: neil.armstrong, linux-arm-msm, dri-devel, swboyd, seanpaul,
	marijn.suijten, quic_jesszhan, quic_khsieh, freedreno



On 1/26/2024 6:40 PM, Dmitry Baryshkov wrote:
> On Sat, 27 Jan 2024 at 02:58, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>>
>>
>> On 1/25/2024 1:23 PM, Dmitry Baryshkov wrote:
>>> On 25/01/2024 21:38, Paloma Arellano wrote:
>>>> YUV420 format is supported only in the VSC SDP packet and not through
>>>> MSA. Hence add an API which indicates the sink support which can be used
>>>> by the rest of the DP programming.
>>>
>>> This API ideally should go to drm/display/drm_dp_helper.c
>> I'm not familiar how other vendors are checking if VSC SDP is supported.
>> So in moving this API, I'm going to let the other vendors make the
>> changes themselves.
> 
> Let me show it for you:
> 
> bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp)
> {
>          u8 dprx = 0;
> 
>          if (drm_dp_dpcd_readb(&intel_dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST,
>                                &dprx) != 1)
>                  return false;
>          return dprx & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED;
> }
> 

Even AMD has similar logic:

6145 		stream->use_vsc_sdp_for_colorimetry = false;
6146 		if (aconnector->dc_sink->sink_signal == 
SIGNAL_TYPE_DISPLAY_PORT_MST) {
6147 			stream->use_vsc_sdp_for_colorimetry =
6148 				aconnector->dc_sink->is_vsc_sdp_colorimetry_supported;
6149 		} else {
6150 			if 
(stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED)
6151 				stream->use_vsc_sdp_for_colorimetry = true;
6152 		}

But it will be harder to untangle this compared to intel's code.

I am fine with adding an API to drm_dp_helper which indicates presence 
of VSC SDP but I would prefer leaving it to other vendors to use it in 
the way they would like and only keep msm usage in this series.



> 
>>>
>>>>
>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>>> ---
>>>>    drivers/gpu/drm/msm/dp/dp_display.c |  3 ++-
>>>>    drivers/gpu/drm/msm/dp/dp_panel.c   | 35 +++++++++++++++++++++++++----
>>>>    drivers/gpu/drm/msm/dp/dp_panel.h   |  1 +
>>>>    3 files changed, 34 insertions(+), 5 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
>>>> b/drivers/gpu/drm/msm/dp/dp_display.c
>>>> index ddac55f45a722..f6b3b6ca242f8 100644
>>>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
>>>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
>>>> @@ -1617,7 +1617,8 @@ void dp_bridge_mode_set(struct drm_bridge
>>>> *drm_bridge,
>>>>            !!(dp_display->dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC);
>>>>          dp_display->dp_mode.out_fmt_is_yuv_420 =
>>>> - drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode);
>>>> + drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode) &&
>>>> +        dp_panel_vsc_sdp_supported(dp_display->panel);
>>>>          /* populate wide_bus_support to different layers */
>>>>        dp_display->ctrl->wide_bus_en =
>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c
>>>> b/drivers/gpu/drm/msm/dp/dp_panel.c
>>>> index 127f6af995cd1..af7820b6d35ec 100644
>>>> --- a/drivers/gpu/drm/msm/dp/dp_panel.c
>>>> +++ b/drivers/gpu/drm/msm/dp/dp_panel.c
>>>> @@ -17,6 +17,9 @@ struct dp_panel_private {
>>>>        struct dp_link *link;
>>>>        struct dp_catalog *catalog;
>>>>        bool panel_on;
>>>> +    bool vsc_supported;
>>>> +    u8 major;
>>>> +    u8 minor;
>>>>    };
>>>>      static void dp_panel_read_psr_cap(struct dp_panel_private *panel)
>>>> @@ -43,9 +46,10 @@ static void dp_panel_read_psr_cap(struct
>>>> dp_panel_private *panel)
>>>>    static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
>>>>    {
>>>>        int rc;
>>>> +    ssize_t rlen;
>>>>        struct dp_panel_private *panel;
>>>>        struct dp_link_info *link_info;
>>>> -    u8 *dpcd, major, minor;
>>>> +    u8 *dpcd, rx_feature;
>>>>          panel = container_of(dp_panel, struct dp_panel_private,
>>>> dp_panel);
>>>>        dpcd = dp_panel->dpcd;
>>>> @@ -53,10 +57,19 @@ static int dp_panel_read_dpcd(struct dp_panel
>>>> *dp_panel)
>>>>        if (rc)
>>>>            return rc;
>>>>    +    rlen = drm_dp_dpcd_read(panel->aux,
>>>> DP_DPRX_FEATURE_ENUMERATION_LIST, &rx_feature, 1);
>>>> +    if (rlen != 1) {
>>>> +        panel->vsc_supported = false;
>>>> +        pr_debug("failed to read DP_DPRX_FEATURE_ENUMERATION_LIST\n");
>>>> +    } else {
>>>> +        panel->vsc_supported = !!(rx_feature &
>>>> DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED);
>>>> +        pr_debug("vsc=%d\n", panel->vsc_supported);
>>>> +    }
>>>> +
>>>>        link_info = &dp_panel->link_info;
>>>>        link_info->revision = dpcd[DP_DPCD_REV];
>>>> -    major = (link_info->revision >> 4) & 0x0f;
>>>> -    minor = link_info->revision & 0x0f;
>>>> +    panel->major = (link_info->revision >> 4) & 0x0f;
>>>> +    panel->minor = link_info->revision & 0x0f;
>>>>          link_info->rate = drm_dp_max_link_rate(dpcd);
>>>>        link_info->num_lanes = drm_dp_max_lane_count(dpcd);
>>>> @@ -69,7 +82,7 @@ static int dp_panel_read_dpcd(struct dp_panel
>>>> *dp_panel)
>>>>        if (link_info->rate > dp_panel->max_dp_link_rate)
>>>>            link_info->rate = dp_panel->max_dp_link_rate;
>>>>    -    drm_dbg_dp(panel->drm_dev, "version: %d.%d\n", major, minor);
>>>> +    drm_dbg_dp(panel->drm_dev, "version: %d.%d\n", panel->major,
>>>> panel->minor);
>>>>        drm_dbg_dp(panel->drm_dev, "link_rate=%d\n", link_info->rate);
>>>>        drm_dbg_dp(panel->drm_dev, "lane_count=%d\n",
>>>> link_info->num_lanes);
>>>>    @@ -280,6 +293,20 @@ void dp_panel_tpg_config(struct dp_panel
>>>> *dp_panel, bool enable)
>>>>        dp_catalog_panel_tpg_enable(catalog,
>>>> &panel->dp_panel.dp_mode.drm_mode);
>>>>    }
>>>>    +bool dp_panel_vsc_sdp_supported(struct dp_panel *dp_panel)
>>>> +{
>>>> +    struct dp_panel_private *panel;
>>>> +
>>>> +    if (!dp_panel) {
>>>> +        pr_err("invalid input\n");
>>>> +        return false;
>>>> +    }
>>>> +
>>>> +    panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
>>>> +
>>>> +    return panel->major >= 1 && panel->minor >= 3 &&
>>>> panel->vsc_supported;
> 
> Anyway, this check is incorrect. Please compare the whole revision
> against DP_DPCD_REV_13 instead of doing a maj/min comparison.
> 
>>>> +}
>>>> +
>>>>    void dp_panel_dump_regs(struct dp_panel *dp_panel)
>>>>    {
>>>>        struct dp_catalog *catalog;
>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h
>>>> b/drivers/gpu/drm/msm/dp/dp_panel.h
>>>> index 6ec68be9f2366..590eca5ce304b 100644
>>>> --- a/drivers/gpu/drm/msm/dp/dp_panel.h
>>>> +++ b/drivers/gpu/drm/msm/dp/dp_panel.h
>>>> @@ -66,6 +66,7 @@ int dp_panel_get_modes(struct dp_panel *dp_panel,
>>>>            struct drm_connector *connector);
>>>>    void dp_panel_handle_sink_request(struct dp_panel *dp_panel);
>>>>    void dp_panel_tpg_config(struct dp_panel *dp_panel, bool enable);
>>>> +bool dp_panel_vsc_sdp_supported(struct dp_panel *dp_panel);
>>>>      /**
>>>>     * is_link_rate_valid() - validates the link rate
>>>
> 
> 
> 

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 05/17] drm/msm/dp: add an API to indicate if sink supports VSC SDP
  2024-01-27  3:57         ` Abhinav Kumar
@ 2024-01-27  5:31           ` Dmitry Baryshkov
  0 siblings, 0 replies; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-27  5:31 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno

On Sat, 27 Jan 2024 at 05:57, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 1/26/2024 6:40 PM, Dmitry Baryshkov wrote:
> > On Sat, 27 Jan 2024 at 02:58, Paloma Arellano <quic_parellan@quicinc.com> wrote:
> >>
> >>
> >> On 1/25/2024 1:23 PM, Dmitry Baryshkov wrote:
> >>> On 25/01/2024 21:38, Paloma Arellano wrote:
> >>>> YUV420 format is supported only in the VSC SDP packet and not through
> >>>> MSA. Hence add an API which indicates the sink support which can be used
> >>>> by the rest of the DP programming.
> >>>
> >>> This API ideally should go to drm/display/drm_dp_helper.c
> >> I'm not familiar how other vendors are checking if VSC SDP is supported.
> >> So in moving this API, I'm going to let the other vendors make the
> >> changes themselves.
> >
> > Let me show it for you:
> >
> > bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp)
> > {
> >          u8 dprx = 0;
> >
> >          if (drm_dp_dpcd_readb(&intel_dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST,
> >                                &dprx) != 1)
> >                  return false;
> >          return dprx & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED;
> > }
> >
>
> Even AMD has similar logic:
>
> 6145            stream->use_vsc_sdp_for_colorimetry = false;
> 6146            if (aconnector->dc_sink->sink_signal ==
> SIGNAL_TYPE_DISPLAY_PORT_MST) {
> 6147                    stream->use_vsc_sdp_for_colorimetry =
> 6148                            aconnector->dc_sink->is_vsc_sdp_colorimetry_supported;
> 6149            } else {
> 6150                    if
> (stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED)
> 6151                            stream->use_vsc_sdp_for_colorimetry = true;
> 6152            }
>
> But it will be harder to untangle this compared to intel's code.
>
> I am fine with adding an API to drm_dp_helper which indicates presence
> of VSC SDP but I would prefer leaving it to other vendors to use it in
> the way they would like and only keep msm usage in this series.

SGTM

>
>
>
> >
> >>>
> >>>>
> >>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >>>> ---
> >>>>    drivers/gpu/drm/msm/dp/dp_display.c |  3 ++-
> >>>>    drivers/gpu/drm/msm/dp/dp_panel.c   | 35 +++++++++++++++++++++++++----
> >>>>    drivers/gpu/drm/msm/dp/dp_panel.h   |  1 +
> >>>>    3 files changed, 34 insertions(+), 5 deletions(-)
> >>>>
> >>>> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
> >>>> b/drivers/gpu/drm/msm/dp/dp_display.c
> >>>> index ddac55f45a722..f6b3b6ca242f8 100644
> >>>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> >>>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> >>>> @@ -1617,7 +1617,8 @@ void dp_bridge_mode_set(struct drm_bridge
> >>>> *drm_bridge,
> >>>>            !!(dp_display->dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC);
> >>>>          dp_display->dp_mode.out_fmt_is_yuv_420 =
> >>>> - drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode);
> >>>> + drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode) &&
> >>>> +        dp_panel_vsc_sdp_supported(dp_display->panel);
> >>>>          /* populate wide_bus_support to different layers */
> >>>>        dp_display->ctrl->wide_bus_en =
> >>>> diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c
> >>>> b/drivers/gpu/drm/msm/dp/dp_panel.c
> >>>> index 127f6af995cd1..af7820b6d35ec 100644
> >>>> --- a/drivers/gpu/drm/msm/dp/dp_panel.c
> >>>> +++ b/drivers/gpu/drm/msm/dp/dp_panel.c
> >>>> @@ -17,6 +17,9 @@ struct dp_panel_private {
> >>>>        struct dp_link *link;
> >>>>        struct dp_catalog *catalog;
> >>>>        bool panel_on;
> >>>> +    bool vsc_supported;
> >>>> +    u8 major;
> >>>> +    u8 minor;
> >>>>    };
> >>>>      static void dp_panel_read_psr_cap(struct dp_panel_private *panel)
> >>>> @@ -43,9 +46,10 @@ static void dp_panel_read_psr_cap(struct
> >>>> dp_panel_private *panel)
> >>>>    static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
> >>>>    {
> >>>>        int rc;
> >>>> +    ssize_t rlen;
> >>>>        struct dp_panel_private *panel;
> >>>>        struct dp_link_info *link_info;
> >>>> -    u8 *dpcd, major, minor;
> >>>> +    u8 *dpcd, rx_feature;
> >>>>          panel = container_of(dp_panel, struct dp_panel_private,
> >>>> dp_panel);
> >>>>        dpcd = dp_panel->dpcd;
> >>>> @@ -53,10 +57,19 @@ static int dp_panel_read_dpcd(struct dp_panel
> >>>> *dp_panel)
> >>>>        if (rc)
> >>>>            return rc;
> >>>>    +    rlen = drm_dp_dpcd_read(panel->aux,
> >>>> DP_DPRX_FEATURE_ENUMERATION_LIST, &rx_feature, 1);
> >>>> +    if (rlen != 1) {
> >>>> +        panel->vsc_supported = false;
> >>>> +        pr_debug("failed to read DP_DPRX_FEATURE_ENUMERATION_LIST\n");
> >>>> +    } else {
> >>>> +        panel->vsc_supported = !!(rx_feature &
> >>>> DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED);
> >>>> +        pr_debug("vsc=%d\n", panel->vsc_supported);
> >>>> +    }
> >>>> +
> >>>>        link_info = &dp_panel->link_info;
> >>>>        link_info->revision = dpcd[DP_DPCD_REV];
> >>>> -    major = (link_info->revision >> 4) & 0x0f;
> >>>> -    minor = link_info->revision & 0x0f;
> >>>> +    panel->major = (link_info->revision >> 4) & 0x0f;
> >>>> +    panel->minor = link_info->revision & 0x0f;
> >>>>          link_info->rate = drm_dp_max_link_rate(dpcd);
> >>>>        link_info->num_lanes = drm_dp_max_lane_count(dpcd);
> >>>> @@ -69,7 +82,7 @@ static int dp_panel_read_dpcd(struct dp_panel
> >>>> *dp_panel)
> >>>>        if (link_info->rate > dp_panel->max_dp_link_rate)
> >>>>            link_info->rate = dp_panel->max_dp_link_rate;
> >>>>    -    drm_dbg_dp(panel->drm_dev, "version: %d.%d\n", major, minor);
> >>>> +    drm_dbg_dp(panel->drm_dev, "version: %d.%d\n", panel->major,
> >>>> panel->minor);
> >>>>        drm_dbg_dp(panel->drm_dev, "link_rate=%d\n", link_info->rate);
> >>>>        drm_dbg_dp(panel->drm_dev, "lane_count=%d\n",
> >>>> link_info->num_lanes);
> >>>>    @@ -280,6 +293,20 @@ void dp_panel_tpg_config(struct dp_panel
> >>>> *dp_panel, bool enable)
> >>>>        dp_catalog_panel_tpg_enable(catalog,
> >>>> &panel->dp_panel.dp_mode.drm_mode);
> >>>>    }
> >>>>    +bool dp_panel_vsc_sdp_supported(struct dp_panel *dp_panel)
> >>>> +{
> >>>> +    struct dp_panel_private *panel;
> >>>> +
> >>>> +    if (!dp_panel) {
> >>>> +        pr_err("invalid input\n");
> >>>> +        return false;
> >>>> +    }
> >>>> +
> >>>> +    panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
> >>>> +
> >>>> +    return panel->major >= 1 && panel->minor >= 3 &&
> >>>> panel->vsc_supported;
> >
> > Anyway, this check is incorrect. Please compare the whole revision
> > against DP_DPCD_REV_13 instead of doing a maj/min comparison.
> >
> >>>> +}
> >>>> +
> >>>>    void dp_panel_dump_regs(struct dp_panel *dp_panel)
> >>>>    {
> >>>>        struct dp_catalog *catalog;
> >>>> diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h
> >>>> b/drivers/gpu/drm/msm/dp/dp_panel.h
> >>>> index 6ec68be9f2366..590eca5ce304b 100644
> >>>> --- a/drivers/gpu/drm/msm/dp/dp_panel.h
> >>>> +++ b/drivers/gpu/drm/msm/dp/dp_panel.h
> >>>> @@ -66,6 +66,7 @@ int dp_panel_get_modes(struct dp_panel *dp_panel,
> >>>>            struct drm_connector *connector);
> >>>>    void dp_panel_handle_sink_request(struct dp_panel *dp_panel);
> >>>>    void dp_panel_tpg_config(struct dp_panel *dp_panel, bool enable);
> >>>> +bool dp_panel_vsc_sdp_supported(struct dp_panel *dp_panel);
> >>>>      /**
> >>>>     * is_link_rate_valid() - validates the link rate
> >>>
> >
> >
> >



-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/17] drm/msm/dpu: disallow widebus en in INTF_CONFIG2 when DP is YUV420
  2024-01-25 21:26   ` Dmitry Baryshkov
@ 2024-01-27  5:42     ` Dmitry Baryshkov
  2024-01-28  5:16     ` Paloma Arellano
  1 sibling, 0 replies; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-27  5:42 UTC (permalink / raw)
  To: Paloma Arellano, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh

On Thu, 25 Jan 2024 at 23:26, Dmitry Baryshkov
<dmitry.baryshkov@linaro.org> wrote:
>
> On 25/01/2024 21:38, Paloma Arellano wrote:
> > INTF_CONFIG2 register cannot have widebus enabled when DP format is
> > YUV420. Therefore, program the INTF to send 1 ppc.
>
> I think this is handled in the DP driver, where we disallow wide bus for
> YUV 4:2:0 modes.

Maybe this needs some explanation from my side:
I think it will be better to have separate conditionals for setting
HCTL_EN and for DATABUS_WIDEN.


>
> >
> > Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> > ---
> >   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 4 +++-
> >   1 file changed, 3 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> > index 6bba531d6dc41..bfb93f02fe7c1 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> > @@ -168,7 +168,9 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
> >        * video timing. It is recommended to enable it for all cases, except
> >        * if compression is enabled in 1 pixel per clock mode
> >        */
> > -     if (p->wide_bus_en)
> > +     if (dp_intf && fmt->base.pixel_format == DRM_FORMAT_YUV420)
> > +             intf_cfg2 |= INTF_CFG2_DATA_HCTL_EN;
> > +     else if (p->wide_bus_en)
> >               intf_cfg2 |= INTF_CFG2_DATABUS_WIDEN | INTF_CFG2_DATA_HCTL_EN;
> >
> >       data_width = p->width;
>
> --
> With best wishes
> Dmitry
>


--
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 10/17] drm/msm/dp: modify dp_catalog_hw_revision to show major and minor val
  2024-01-25 19:38 ` [PATCH 10/17] drm/msm/dp: modify dp_catalog_hw_revision to show major and minor val Paloma Arellano
  2024-01-25 22:07   ` Dmitry Baryshkov
@ 2024-01-27 23:43   ` kernel test robot
  2024-01-28 14:02   ` kernel test robot
  2 siblings, 0 replies; 95+ messages in thread
From: kernel test robot @ 2024-01-27 23:43 UTC (permalink / raw)
  To: Paloma Arellano, freedreno
  Cc: neil.armstrong, quic_jesszhan, linux-arm-msm, Paloma Arellano,
	quic_abhinavk, dri-devel, swboyd, seanpaul, oe-kbuild-all,
	dmitry.baryshkov, marijn.suijten, quic_khsieh

Hi Paloma,

kernel test robot noticed the following build warnings:

[auto build test WARNING on v6.8-rc1]
[also build test WARNING on linus/master next-20240125]
[cannot apply to drm-misc/drm-misc-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Paloma-Arellano/drm-msm-dpu-allow-dpu_encoder_helper_phys_setup_cdm-to-work-for-DP/20240126-034233
base:   v6.8-rc1
patch link:    https://lore.kernel.org/r/20240125193834.7065-11-quic_parellan%40quicinc.com
patch subject: [PATCH 10/17] drm/msm/dp: modify dp_catalog_hw_revision to show major and minor val
config: arm64-defconfig (https://download.01.org/0day-ci/archive/20240128/202401280752.AmrDI7Ox-lkp@intel.com/config)
compiler: aarch64-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240128/202401280752.AmrDI7Ox-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202401280752.AmrDI7Ox-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> drivers/gpu/drm/msm/dp/dp_catalog.c:541: warning: Function parameter or struct member 'major' not described in 'dp_catalog_hw_revision'
>> drivers/gpu/drm/msm/dp/dp_catalog.c:541: warning: Function parameter or struct member 'minor' not described in 'dp_catalog_hw_revision'


vim +541 drivers/gpu/drm/msm/dp/dp_catalog.c

c943b4948b5848 Chandan Uddaraju 2020-08-27  531  
757a2f36ab095f Kuogee Hsieh     2022-02-25  532  /**
757a2f36ab095f Kuogee Hsieh     2022-02-25  533   * dp_catalog_hw_revision() - retrieve DP hw revision
757a2f36ab095f Kuogee Hsieh     2022-02-25  534   *
757a2f36ab095f Kuogee Hsieh     2022-02-25  535   * @dp_catalog: DP catalog structure
757a2f36ab095f Kuogee Hsieh     2022-02-25  536   *
5febc52d5716d6 Paloma Arellano  2024-01-25  537   * Return: void
757a2f36ab095f Kuogee Hsieh     2022-02-25  538   *
757a2f36ab095f Kuogee Hsieh     2022-02-25  539   */
5febc52d5716d6 Paloma Arellano  2024-01-25  540  void dp_catalog_hw_revision(const struct dp_catalog *dp_catalog, u16 *major, u16 *minor)
757a2f36ab095f Kuogee Hsieh     2022-02-25 @541  {
757a2f36ab095f Kuogee Hsieh     2022-02-25  542  	const struct dp_catalog_private *catalog = container_of(dp_catalog,
757a2f36ab095f Kuogee Hsieh     2022-02-25  543  				struct dp_catalog_private, dp_catalog);
5febc52d5716d6 Paloma Arellano  2024-01-25  544  	u32 reg_dp_hw_version;
757a2f36ab095f Kuogee Hsieh     2022-02-25  545  
5febc52d5716d6 Paloma Arellano  2024-01-25  546  	reg_dp_hw_version = dp_read_ahb(catalog, REG_DP_HW_VERSION);
5febc52d5716d6 Paloma Arellano  2024-01-25  547  	*major = DP_HW_VERSION_MAJOR(reg_dp_hw_version);
5febc52d5716d6 Paloma Arellano  2024-01-25  548  	*minor = DP_HW_VERSION_MINOR(reg_dp_hw_version);
757a2f36ab095f Kuogee Hsieh     2022-02-25  549  }
757a2f36ab095f Kuogee Hsieh     2022-02-25  550  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/17] drm/msm/dpu: disallow widebus en in INTF_CONFIG2 when DP is YUV420
  2024-01-25 21:26   ` Dmitry Baryshkov
  2024-01-27  5:42     ` Dmitry Baryshkov
@ 2024-01-28  5:16     ` Paloma Arellano
  2024-01-28  5:33       ` Dmitry Baryshkov
  1 sibling, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-28  5:16 UTC (permalink / raw)
  To: Dmitry Baryshkov, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh


On 1/25/2024 1:26 PM, Dmitry Baryshkov wrote:
> On 25/01/2024 21:38, Paloma Arellano wrote:
>> INTF_CONFIG2 register cannot have widebus enabled when DP format is
>> YUV420. Therefore, program the INTF to send 1 ppc.
>
> I think this is handled in the DP driver, where we disallow wide bus 
> for YUV 4:2:0 modes.
Yes we do disallow wide bus for YUV420 modes, but we still need to 
program the INTF_CFG2_DATA_HCTL_EN. Therefore, it is necessary to add 
this check.
>
>>
>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 4 +++-
>>   1 file changed, 3 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>> index 6bba531d6dc41..bfb93f02fe7c1 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>> @@ -168,7 +168,9 @@ static void 
>> dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
>>        * video timing. It is recommended to enable it for all cases, 
>> except
>>        * if compression is enabled in 1 pixel per clock mode
>>        */
>> -    if (p->wide_bus_en)
>> +    if (dp_intf && fmt->base.pixel_format == DRM_FORMAT_YUV420)
>> +        intf_cfg2 |= INTF_CFG2_DATA_HCTL_EN;
>> +    else if (p->wide_bus_en)
>>           intf_cfg2 |= INTF_CFG2_DATABUS_WIDEN | INTF_CFG2_DATA_HCTL_EN;
>>         data_width = p->width;
>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 08/17] drm/msm/dp: change YUV420 related programming for DP
  2024-01-25 21:29   ` Dmitry Baryshkov
@ 2024-01-28  5:18     ` Paloma Arellano
  0 siblings, 0 replies; 95+ messages in thread
From: Paloma Arellano @ 2024-01-28  5:18 UTC (permalink / raw)
  To: Dmitry Baryshkov, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh


On 1/25/2024 1:29 PM, Dmitry Baryshkov wrote:
> On 25/01/2024 21:38, Paloma Arellano wrote:
>> Change all relevant DP controller related programming for YUV420 cases.
>> Namely, change the pixel clock math to consider YUV420, program the
>> configuration control to indicate YUV420, as well as modify the MVID
>> programming to consider YUV420.
>
> Too many items for a single commit.
Ack. In the next series, I'll keep the clock math and MVID related code 
in one patch. And configuration control code in another.
>
>>
>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/dp/dp_catalog.c |  5 ++++-
>>   drivers/gpu/drm/msm/dp/dp_catalog.h |  2 +-
>>   drivers/gpu/drm/msm/dp/dp_ctrl.c    | 12 +++++++++---
>>   drivers/gpu/drm/msm/dp/dp_display.c |  8 +++++++-
>>   drivers/gpu/drm/msm/msm_kms.h       |  3 +++
>>   5 files changed, 24 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
>> b/drivers/gpu/drm/msm/dp/dp_catalog.c
>> index 5142aeb705a44..5d84c089e520a 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
>> @@ -442,7 +442,7 @@ void dp_catalog_ctrl_config_misc(struct 
>> dp_catalog *dp_catalog,
>>     void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog,
>>                       u32 rate, u32 stream_rate_khz,
>> -                    bool fixed_nvid)
>> +                    bool fixed_nvid, bool is_ycbcr_420)
>>   {
>>       u32 pixel_m, pixel_n;
>>       u32 mvid, nvid, pixel_div = 0, dispcc_input_rate;
>> @@ -485,6 +485,9 @@ void dp_catalog_ctrl_config_msa(struct dp_catalog 
>> *dp_catalog,
>>           nvid = temp;
>>       }
>>   +    if (is_ycbcr_420)
>> +        mvid /= 2;
>> +
>>       if (link_rate_hbr2 == rate)
>>           nvid *= 2;
>>   diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h 
>> b/drivers/gpu/drm/msm/dp/dp_catalog.h
>> index 38786e855b51a..6cb5e2a243de2 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.h
>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
>> @@ -96,7 +96,7 @@ void dp_catalog_ctrl_mainlink_ctrl(struct 
>> dp_catalog *dp_catalog, bool enable);
>>   void dp_catalog_ctrl_psr_mainlink_enable(struct dp_catalog 
>> *dp_catalog, bool enable);
>>   void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, u32 
>> cc, u32 tb);
>>   void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 
>> rate,
>> -                u32 stream_rate_khz, bool fixed_nvid);
>> +                u32 stream_rate_khz, bool fixed_nvid, bool 
>> is_ycbcr_420);
>>   int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog 
>> *dp_catalog, u32 pattern);
>>   u32 dp_catalog_hw_revision(const struct dp_catalog *dp_catalog);
>>   void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog);
>> diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c 
>> b/drivers/gpu/drm/msm/dp/dp_ctrl.c
>> index 77a8d9366ed7b..209cf2a35642f 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
>> @@ -128,6 +128,9 @@ static void dp_ctrl_config_ctrl(struct 
>> dp_ctrl_private *ctrl)
>>       /* Default-> LSCLK DIV: 1/4 LCLK  */
>>       config |= (2 << DP_CONFIGURATION_CTRL_LSCLK_DIV_SHIFT);
>>   +    if (ctrl->panel->dp_mode.out_fmt_is_yuv_420)
>> +        config |= DP_CONFIGURATION_CTRL_RGB_YUV; /* YUV420 */
>> +
>
> This definitely is not related to clock rate calculations.
This is related to the configuration control register.
>
>>       /* Scrambler reset enable */
>>       if (drm_dp_alternate_scrambler_reset_cap(dpcd))
>>           config |= DP_CONFIGURATION_CTRL_ASSR;
>> @@ -957,7 +960,7 @@ static void dp_ctrl_calc_tu_parameters(struct 
>> dp_ctrl_private *ctrl,
>>       in.hporch = drm_mode->htotal - drm_mode->hdisplay;
>>       in.nlanes = ctrl->link->link_params.num_lanes;
>>       in.bpp = ctrl->panel->dp_mode.bpp;
>> -    in.pixel_enc = 444;
>> +    in.pixel_enc = ctrl->panel->dp_mode.out_fmt_is_yuv_420 ? 420 : 444;
>>       in.dsc_en = 0;
>>       in.async_en = 0;
>>       in.fec_en = 0;
>> @@ -1763,6 +1766,8 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl)
>>           ctrl->link->link_params.rate = rate;
>>           ctrl->link->link_params.num_lanes =
>>               ctrl->panel->link_info.num_lanes;
>> +        if (ctrl->panel->dp_mode.out_fmt_is_yuv_420)
>> +            pixel_rate >>= 1;
>>       }
>>         drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, 
>> pixel_rate=%lu\n",
>> @@ -1878,7 +1883,7 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, 
>> bool force_link_train)
>>         pixel_rate = pixel_rate_orig = 
>> ctrl->panel->dp_mode.drm_mode.clock;
>>   -    if (dp_ctrl->wide_bus_en)
>> +    if (dp_ctrl->wide_bus_en || 
>> ctrl->panel->dp_mode.out_fmt_is_yuv_420)
>>           pixel_rate >>= 1;
>>         drm_dbg_dp(ctrl->drm_dev, "rate=%d, num_lanes=%d, 
>> pixel_rate=%lu\n",
>> @@ -1917,7 +1922,8 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, 
>> bool force_link_train)
>>         dp_catalog_ctrl_config_msa(ctrl->catalog,
>>           ctrl->link->link_params.rate,
>> -        pixel_rate_orig, dp_ctrl_use_fixed_nvid(ctrl));
>> +        pixel_rate_orig, dp_ctrl_use_fixed_nvid(ctrl),
>> +        ctrl->panel->dp_mode.out_fmt_is_yuv_420);
>>         dp_ctrl_setup_tr_unit(ctrl);
>>   diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
>> b/drivers/gpu/drm/msm/dp/dp_display.c
>> index f6b3b6ca242f8..6d764f5b08727 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
>> @@ -916,9 +916,10 @@ enum drm_mode_status dp_bridge_mode_valid(struct 
>> drm_bridge *bridge,
>>       const u32 num_components = 3, default_bpp = 24;
>>       struct dp_display_private *dp_display;
>>       struct dp_link_info *link_info;
>> -    u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0;
>>       struct msm_dp *dp;
>>       int mode_pclk_khz = mode->clock;
>> +    int rate_ratio = RGB_24BPP_TMDS_CHAR_RATE_RATIO;
>> +    u32 mode_rate_khz = 0, supported_rate_khz = 0, mode_bpp = 0;
>>         dp = to_dp_bridge(bridge)->dp_display;
>>   @@ -933,6 +934,11 @@ enum drm_mode_status 
>> dp_bridge_mode_valid(struct drm_bridge *bridge,
>>       dp_display = container_of(dp, struct dp_display_private, 
>> dp_display);
>>       link_info = &dp_display->panel->link_info;
>>   +    if (drm_mode_is_420_only(&dp->connector->display_info, mode))
>> +        rate_ratio = YUV420_24BPP_TMDS_CHAR_RATE_RATIO;
>> +
>> +    mode_pclk_khz /= rate_ratio;
>
> I think it will be more obvious and simple to write:
>
> if (drm_mode_is_420...)
>     mode_pclk_khz /= 2;
Ack
>
>
>> +
>>       mode_bpp = dp->connector->display_info.bpc * num_components;
>>       if (!mode_bpp)
>>           mode_bpp = default_bpp;
>> diff --git a/drivers/gpu/drm/msm/msm_kms.h 
>> b/drivers/gpu/drm/msm/msm_kms.h
>> index 44aa435d68ce2..66e8151951807 100644
>> --- a/drivers/gpu/drm/msm/msm_kms.h
>> +++ b/drivers/gpu/drm/msm/msm_kms.h
>> @@ -15,6 +15,9 @@
>>     #define MAX_PLANE    4
>>   +#define RGB_24BPP_TMDS_CHAR_RATE_RATIO        1
>> +#define YUV420_24BPP_TMDS_CHAR_RATE_RATIO    2
>> +
>>   /* As there are different display controller blocks depending on the
>>    * snapdragon version, the kms support is split out and the 
>> appropriate
>>    * implementation is loaded at runtime.  The kms module is responsible
>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 09/17] drm/msm/dp: move parity calculation to dp_catalog
  2024-01-25 21:32   ` Dmitry Baryshkov
@ 2024-01-28  5:18     ` Paloma Arellano
  0 siblings, 0 replies; 95+ messages in thread
From: Paloma Arellano @ 2024-01-28  5:18 UTC (permalink / raw)
  To: Dmitry Baryshkov, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh


On 1/25/2024 1:32 PM, Dmitry Baryshkov wrote:
> On 25/01/2024 21:38, Paloma Arellano wrote:
>> Parity calculation is necessary for VSC SDP implementation, therefore
>> move it to dp_catalog so it usable by both SDP programming and
>> dp_audio.c
>>
>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/dp/dp_audio.c   | 100 ++++------------------------
>>   drivers/gpu/drm/msm/dp/dp_catalog.h |  72 ++++++++++++++++++++
>>   2 files changed, 86 insertions(+), 86 deletions(-)
>
> There is nothing catalog-uish in the parity calculation. Just add 
> dp_utils.c. Another options is to push it to the drm/display/
>
> LGTM otherwise.
Ack. Will move to dp_utils.c
>
>>
>> diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c 
>> b/drivers/gpu/drm/msm/dp/dp_audio.c
>> index 4a2e479723a85..7aa785018155a 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_audio.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_audio.c
>> @@ -16,13 +16,6 @@
>>   #include "dp_panel.h"
>>   #include "dp_display.h"
>>   -#define HEADER_BYTE_2_BIT     0
>> -#define PARITY_BYTE_2_BIT     8
>> -#define HEADER_BYTE_1_BIT    16
>> -#define PARITY_BYTE_1_BIT    24
>> -#define HEADER_BYTE_3_BIT    16
>> -#define PARITY_BYTE_3_BIT    24
>> -
>>   struct dp_audio_private {
>>       struct platform_device *audio_pdev;
>>       struct platform_device *pdev;
>> @@ -36,71 +29,6 @@ struct dp_audio_private {
>>       struct dp_audio dp_audio;
>>   };
>>   -static u8 dp_audio_get_g0_value(u8 data)
>> -{
>> -    u8 c[4];
>> -    u8 g[4];
>> -    u8 ret_data = 0;
>> -    u8 i;
>> -
>> -    for (i = 0; i < 4; i++)
>> -        c[i] = (data >> i) & 0x01;
>> -
>> -    g[0] = c[3];
>> -    g[1] = c[0] ^ c[3];
>> -    g[2] = c[1];
>> -    g[3] = c[2];
>> -
>> -    for (i = 0; i < 4; i++)
>> -        ret_data = ((g[i] & 0x01) << i) | ret_data;
>> -
>> -    return ret_data;
>> -}
>> -
>> -static u8 dp_audio_get_g1_value(u8 data)
>> -{
>> -    u8 c[4];
>> -    u8 g[4];
>> -    u8 ret_data = 0;
>> -    u8 i;
>> -
>> -    for (i = 0; i < 4; i++)
>> -        c[i] = (data >> i) & 0x01;
>> -
>> -    g[0] = c[0] ^ c[3];
>> -    g[1] = c[0] ^ c[1] ^ c[3];
>> -    g[2] = c[1] ^ c[2];
>> -    g[3] = c[2] ^ c[3];
>> -
>> -    for (i = 0; i < 4; i++)
>> -        ret_data = ((g[i] & 0x01) << i) | ret_data;
>> -
>> -    return ret_data;
>> -}
>> -
>> -static u8 dp_audio_calculate_parity(u32 data)
>> -{
>> -    u8 x0 = 0;
>> -    u8 x1 = 0;
>> -    u8 ci = 0;
>> -    u8 iData = 0;
>> -    u8 i = 0;
>> -    u8 parity_byte;
>> -    u8 num_byte = (data & 0xFF00) > 0 ? 8 : 2;
>> -
>> -    for (i = 0; i < num_byte; i++) {
>> -        iData = (data >> i*4) & 0xF;
>> -
>> -        ci = iData ^ x1;
>> -        x1 = x0 ^ dp_audio_get_g1_value(ci);
>> -        x0 = dp_audio_get_g0_value(ci);
>> -    }
>> -
>> -    parity_byte = x1 | (x0 << 4);
>> -
>> -    return parity_byte;
>> -}
>> -
>>   static u32 dp_audio_get_header(struct dp_catalog *catalog,
>>           enum dp_catalog_audio_sdp_type sdp,
>>           enum dp_catalog_audio_header_type header)
>> @@ -134,7 +62,7 @@ static void dp_audio_stream_sdp(struct 
>> dp_audio_private *audio)
>>               DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_1);
>>         new_value = 0x02;
>> -    parity_byte = dp_audio_calculate_parity(new_value);
>> +    parity_byte = dp_catalog_calculate_parity(new_value);
>>       value |= ((new_value << HEADER_BYTE_1_BIT)
>>               | (parity_byte << PARITY_BYTE_1_BIT));
>>       drm_dbg_dp(audio->drm_dev,
>> @@ -147,7 +75,7 @@ static void dp_audio_stream_sdp(struct 
>> dp_audio_private *audio)
>>       value = dp_audio_get_header(catalog,
>>               DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_2);
>>       new_value = value;
>> -    parity_byte = dp_audio_calculate_parity(new_value);
>> +    parity_byte = dp_catalog_calculate_parity(new_value);
>>       value |= ((new_value << HEADER_BYTE_2_BIT)
>>               | (parity_byte << PARITY_BYTE_2_BIT));
>>       drm_dbg_dp(audio->drm_dev,
>> @@ -162,7 +90,7 @@ static void dp_audio_stream_sdp(struct 
>> dp_audio_private *audio)
>>               DP_AUDIO_SDP_STREAM, DP_AUDIO_SDP_HEADER_3);
>>         new_value = audio->channels - 1;
>> -    parity_byte = dp_audio_calculate_parity(new_value);
>> +    parity_byte = dp_catalog_calculate_parity(new_value);
>>       value |= ((new_value << HEADER_BYTE_3_BIT)
>>               | (parity_byte << PARITY_BYTE_3_BIT));
>>       drm_dbg_dp(audio->drm_dev,
>> @@ -184,7 +112,7 @@ static void dp_audio_timestamp_sdp(struct 
>> dp_audio_private *audio)
>>               DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_1);
>>         new_value = 0x1;
>> -    parity_byte = dp_audio_calculate_parity(new_value);
>> +    parity_byte = dp_catalog_calculate_parity(new_value);
>>       value |= ((new_value << HEADER_BYTE_1_BIT)
>>               | (parity_byte << PARITY_BYTE_1_BIT));
>>       drm_dbg_dp(audio->drm_dev,
>> @@ -198,7 +126,7 @@ static void dp_audio_timestamp_sdp(struct 
>> dp_audio_private *audio)
>>               DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_2);
>>         new_value = 0x17;
>> -    parity_byte = dp_audio_calculate_parity(new_value);
>> +    parity_byte = dp_catalog_calculate_parity(new_value);
>>       value |= ((new_value << HEADER_BYTE_2_BIT)
>>               | (parity_byte << PARITY_BYTE_2_BIT));
>>       drm_dbg_dp(audio->drm_dev,
>> @@ -212,7 +140,7 @@ static void dp_audio_timestamp_sdp(struct 
>> dp_audio_private *audio)
>>               DP_AUDIO_SDP_TIMESTAMP, DP_AUDIO_SDP_HEADER_3);
>>         new_value = (0x0 | (0x11 << 2));
>> -    parity_byte = dp_audio_calculate_parity(new_value);
>> +    parity_byte = dp_catalog_calculate_parity(new_value);
>>       value |= ((new_value << HEADER_BYTE_3_BIT)
>>               | (parity_byte << PARITY_BYTE_3_BIT));
>>       drm_dbg_dp(audio->drm_dev,
>> @@ -233,7 +161,7 @@ static void dp_audio_infoframe_sdp(struct 
>> dp_audio_private *audio)
>>               DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_1);
>>         new_value = 0x84;
>> -    parity_byte = dp_audio_calculate_parity(new_value);
>> +    parity_byte = dp_catalog_calculate_parity(new_value);
>>       value |= ((new_value << HEADER_BYTE_1_BIT)
>>               | (parity_byte << PARITY_BYTE_1_BIT));
>>       drm_dbg_dp(audio->drm_dev,
>> @@ -247,7 +175,7 @@ static void dp_audio_infoframe_sdp(struct 
>> dp_audio_private *audio)
>>               DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_2);
>>         new_value = 0x1b;
>> -    parity_byte = dp_audio_calculate_parity(new_value);
>> +    parity_byte = dp_catalog_calculate_parity(new_value);
>>       value |= ((new_value << HEADER_BYTE_2_BIT)
>>               | (parity_byte << PARITY_BYTE_2_BIT));
>>       drm_dbg_dp(audio->drm_dev,
>> @@ -261,7 +189,7 @@ static void dp_audio_infoframe_sdp(struct 
>> dp_audio_private *audio)
>>               DP_AUDIO_SDP_INFOFRAME, DP_AUDIO_SDP_HEADER_3);
>>         new_value = (0x0 | (0x11 << 2));
>> -    parity_byte = dp_audio_calculate_parity(new_value);
>> +    parity_byte = dp_catalog_calculate_parity(new_value);
>>       value |= ((new_value << HEADER_BYTE_3_BIT)
>>               | (parity_byte << PARITY_BYTE_3_BIT));
>>       drm_dbg_dp(audio->drm_dev,
>> @@ -282,7 +210,7 @@ static void dp_audio_copy_management_sdp(struct 
>> dp_audio_private *audio)
>>               DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_1);
>>         new_value = 0x05;
>> -    parity_byte = dp_audio_calculate_parity(new_value);
>> +    parity_byte = dp_catalog_calculate_parity(new_value);
>>       value |= ((new_value << HEADER_BYTE_1_BIT)
>>               | (parity_byte << PARITY_BYTE_1_BIT));
>>       drm_dbg_dp(audio->drm_dev,
>> @@ -296,7 +224,7 @@ static void dp_audio_copy_management_sdp(struct 
>> dp_audio_private *audio)
>>               DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_2);
>>         new_value = 0x0F;
>> -    parity_byte = dp_audio_calculate_parity(new_value);
>> +    parity_byte = dp_catalog_calculate_parity(new_value);
>>       value |= ((new_value << HEADER_BYTE_2_BIT)
>>               | (parity_byte << PARITY_BYTE_2_BIT));
>>       drm_dbg_dp(audio->drm_dev,
>> @@ -310,7 +238,7 @@ static void dp_audio_copy_management_sdp(struct 
>> dp_audio_private *audio)
>>               DP_AUDIO_SDP_COPYMANAGEMENT, DP_AUDIO_SDP_HEADER_3);
>>         new_value = 0x0;
>> -    parity_byte = dp_audio_calculate_parity(new_value);
>> +    parity_byte = dp_catalog_calculate_parity(new_value);
>>       value |= ((new_value << HEADER_BYTE_3_BIT)
>>               | (parity_byte << PARITY_BYTE_3_BIT));
>>       drm_dbg_dp(audio->drm_dev,
>> @@ -331,7 +259,7 @@ static void dp_audio_isrc_sdp(struct 
>> dp_audio_private *audio)
>>               DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_1);
>>         new_value = 0x06;
>> -    parity_byte = dp_audio_calculate_parity(new_value);
>> +    parity_byte = dp_catalog_calculate_parity(new_value);
>>       value |= ((new_value << HEADER_BYTE_1_BIT)
>>               | (parity_byte << PARITY_BYTE_1_BIT));
>>       drm_dbg_dp(audio->drm_dev,
>> @@ -345,7 +273,7 @@ static void dp_audio_isrc_sdp(struct 
>> dp_audio_private *audio)
>>               DP_AUDIO_SDP_ISRC, DP_AUDIO_SDP_HEADER_2);
>>         new_value = 0x0F;
>> -    parity_byte = dp_audio_calculate_parity(new_value);
>> +    parity_byte = dp_catalog_calculate_parity(new_value);
>>       value |= ((new_value << HEADER_BYTE_2_BIT)
>>               | (parity_byte << PARITY_BYTE_2_BIT));
>>       drm_dbg_dp(audio->drm_dev,
>> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h 
>> b/drivers/gpu/drm/msm/dp/dp_catalog.h
>> index 6cb5e2a243de2..563903605b3a7 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.h
>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
>> @@ -45,6 +45,13 @@ enum dp_phy_aux_config_type {
>>       PHY_AUX_CFG_MAX,
>>   };
>>   +#define HEADER_BYTE_2_BIT     0
>> +#define PARITY_BYTE_2_BIT     8
>> +#define HEADER_BYTE_1_BIT    16
>> +#define PARITY_BYTE_1_BIT    24
>> +#define HEADER_BYTE_3_BIT    16
>> +#define PARITY_BYTE_3_BIT    24
>> +
>>   enum dp_catalog_audio_sdp_type {
>>       DP_AUDIO_SDP_STREAM,
>>       DP_AUDIO_SDP_TIMESTAMP,
>> @@ -73,6 +80,71 @@ struct dp_catalog {
>>       bool wide_bus_en;
>>   };
>>   +static inline u8 dp_catalog_get_g0_value(u8 data)
>> +{
>> +    u8 c[4];
>> +    u8 g[4];
>> +    u8 ret_data = 0;
>> +    u8 i;
>> +
>> +    for (i = 0; i < 4; i++)
>> +        c[i] = (data >> i) & 0x01;
>> +
>> +    g[0] = c[3];
>> +    g[1] = c[0] ^ c[3];
>> +    g[2] = c[1];
>> +    g[3] = c[2];
>> +
>> +    for (i = 0; i < 4; i++)
>> +        ret_data = ((g[i] & 0x01) << i) | ret_data;
>> +
>> +    return ret_data;
>> +}
>> +
>> +static inline u8 dp_catalog_get_g1_value(u8 data)
>> +{
>> +    u8 c[4];
>> +    u8 g[4];
>> +    u8 ret_data = 0;
>> +    u8 i;
>> +
>> +    for (i = 0; i < 4; i++)
>> +        c[i] = (data >> i) & 0x01;
>> +
>> +    g[0] = c[0] ^ c[3];
>> +    g[1] = c[0] ^ c[1] ^ c[3];
>> +    g[2] = c[1] ^ c[2];
>> +    g[3] = c[2] ^ c[3];
>> +
>> +    for (i = 0; i < 4; i++)
>> +        ret_data = ((g[i] & 0x01) << i) | ret_data;
>> +
>> +    return ret_data;
>> +}
>> +
>> +static inline u8 dp_catalog_calculate_parity(u32 data)
>> +{
>> +    u8 x0 = 0;
>> +    u8 x1 = 0;
>> +    u8 ci = 0;
>> +    u8 iData = 0;
>> +    u8 i = 0;
>> +    u8 parity_byte;
>> +    u8 num_byte = (data & 0xFF00) > 0 ? 8 : 2;
>> +
>> +    for (i = 0; i < num_byte; i++) {
>> +        iData = (data >> i * 4) & 0xF;
>> +
>> +        ci = iData ^ x1;
>> +        x1 = x0 ^ dp_catalog_get_g1_value(ci);
>> +        x0 = dp_catalog_get_g0_value(ci);
>> +    }
>> +
>> +    parity_byte = x1 | (x0 << 4);
>> +
>> +    return parity_byte;
>> +}
>> +
>>   /* Debug module */
>>   void dp_catalog_snapshot(struct dp_catalog *dp_catalog, struct 
>> msm_disp_state *disp_state);
>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 10/17] drm/msm/dp: modify dp_catalog_hw_revision to show major and minor val
  2024-01-25 22:07   ` Dmitry Baryshkov
@ 2024-01-28  5:30     ` Paloma Arellano
  2024-01-28  5:35       ` Dmitry Baryshkov
  0 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-28  5:30 UTC (permalink / raw)
  To: Dmitry Baryshkov, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh


On 1/25/2024 2:07 PM, Dmitry Baryshkov wrote:
> On 25/01/2024 21:38, Paloma Arellano wrote:
>> Modify dp_catalog_hw_revision to make the major and minor version values
>> known instead of outputting the entire hex value of the hardware version
>> register in preparation of using it for VSC SDP programming.
>>
>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/dp/dp_catalog.c | 12 +++++++++---
>>   drivers/gpu/drm/msm/dp/dp_catalog.h |  2 +-
>>   2 files changed, 10 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
>> b/drivers/gpu/drm/msm/dp/dp_catalog.c
>> index 5d84c089e520a..c025786170ba5 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
>> @@ -24,6 +24,9 @@
>>   #define DP_INTERRUPT_STATUS_ACK_SHIFT    1
>>   #define DP_INTERRUPT_STATUS_MASK_SHIFT    2
>>   +#define DP_HW_VERSION_MAJOR(reg)    FIELD_GET(GENMASK(31, 28), reg)
>> +#define DP_HW_VERSION_MINOR(reg)    FIELD_GET(GENMASK(27, 16), reg)
>> +
>>   #define DP_INTF_CONFIG_DATABUS_WIDEN     BIT(4)
>>     #define DP_INTERRUPT_STATUS1 \
>> @@ -531,15 +534,18 @@ int 
>> dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog,
>>    *
>>    * @dp_catalog: DP catalog structure
>>    *
>> - * Return: DP controller hw revision
>> + * Return: void
>>    *
>>    */
>> -u32 dp_catalog_hw_revision(const struct dp_catalog *dp_catalog)
>> +void dp_catalog_hw_revision(const struct dp_catalog *dp_catalog, u16 
>> *major, u16 *minor)
>>   {
>>       const struct dp_catalog_private *catalog = 
>> container_of(dp_catalog,
>>                   struct dp_catalog_private, dp_catalog);
>> +    u32 reg_dp_hw_version;
>>   -    return dp_read_ahb(catalog, REG_DP_HW_VERSION);
>> +    reg_dp_hw_version = dp_read_ahb(catalog, REG_DP_HW_VERSION);
>> +    *major = DP_HW_VERSION_MAJOR(reg_dp_hw_version);
>> +    *minor = DP_HW_VERSION_MINOR(reg_dp_hw_version);
>
> After looking at the code, it might be easier to keep 
> dp_catalog_hw_revision as is, add define for hw revision 1.2 and 
> corepare to it directly.
I thought having a  define value of the version would be harder to 
follow than what's here currently. Since having it compare to the 
version value looks a little difficult to read versus having an explicit 
major and minor value version to compare to. For example having (major 
 >= 1 && minor >= 2) versus having something like (hw_version >= 
DPU_HW_VERSION_1_2)
>
>>   }
>>     /**
>> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h 
>> b/drivers/gpu/drm/msm/dp/dp_catalog.h
>> index 563903605b3a7..94c377ef90c35 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.h
>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
>> @@ -170,7 +170,7 @@ void dp_catalog_ctrl_config_misc(struct 
>> dp_catalog *dp_catalog, u32 cc, u32 tb);
>>   void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 
>> rate,
>>                   u32 stream_rate_khz, bool fixed_nvid, bool 
>> is_ycbcr_420);
>>   int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog 
>> *dp_catalog, u32 pattern);
>> -u32 dp_catalog_hw_revision(const struct dp_catalog *dp_catalog);
>> +void dp_catalog_hw_revision(const struct dp_catalog *dp_catalog, u16 
>> *major, u16 *minor);
>>   void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog);
>>   bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog *dp_catalog);
>>   void dp_catalog_ctrl_enable_irq(struct dp_catalog *dp_catalog, bool 
>> enable);
>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/17] drm/msm/dpu: disallow widebus en in INTF_CONFIG2 when DP is YUV420
  2024-01-28  5:16     ` Paloma Arellano
@ 2024-01-28  5:33       ` Dmitry Baryshkov
  2024-01-29 23:51         ` Abhinav Kumar
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-28  5:33 UTC (permalink / raw)
  To: Paloma Arellano
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh, freedreno

On Sun, 28 Jan 2024 at 07:16, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>
>
> On 1/25/2024 1:26 PM, Dmitry Baryshkov wrote:
> > On 25/01/2024 21:38, Paloma Arellano wrote:
> >> INTF_CONFIG2 register cannot have widebus enabled when DP format is
> >> YUV420. Therefore, program the INTF to send 1 ppc.
> >
> > I think this is handled in the DP driver, where we disallow wide bus
> > for YUV 4:2:0 modes.
> Yes we do disallow wide bus for YUV420 modes, but we still need to
> program the INTF_CFG2_DATA_HCTL_EN. Therefore, it is necessary to add
> this check.

As I wrote in my second email, I'd prefer to have one if which guards
HCTL_EN and another one for WIDEN

> >
> >>
> >> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >> ---
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 4 +++-
> >>   1 file changed, 3 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> >> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> >> index 6bba531d6dc41..bfb93f02fe7c1 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> >> @@ -168,7 +168,9 @@ static void
> >> dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
> >>        * video timing. It is recommended to enable it for all cases,
> >> except
> >>        * if compression is enabled in 1 pixel per clock mode
> >>        */
> >> -    if (p->wide_bus_en)
> >> +    if (dp_intf && fmt->base.pixel_format == DRM_FORMAT_YUV420)
> >> +        intf_cfg2 |= INTF_CFG2_DATA_HCTL_EN;
> >> +    else if (p->wide_bus_en)
> >>           intf_cfg2 |= INTF_CFG2_DATABUS_WIDEN | INTF_CFG2_DATA_HCTL_EN;
> >>         data_width = p->width;
> >



-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 11/17] drm/msm/dp: add VSC SDP support for YUV420 over DP
  2024-01-25 21:48   ` Dmitry Baryshkov
@ 2024-01-28  5:34     ` Paloma Arellano
  2024-01-28  5:39       ` Dmitry Baryshkov
  0 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-28  5:34 UTC (permalink / raw)
  To: Dmitry Baryshkov, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh


On 1/25/2024 1:48 PM, Dmitry Baryshkov wrote:
> On 25/01/2024 21:38, Paloma Arellano wrote:
>> Add support to pack and send the VSC SDP packet for DP. This therefore
>> allows the transmision of format information to the sinks which is
>> needed for YUV420 support over DP.
>>
>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/dp/dp_catalog.c | 147 ++++++++++++++++++++++++++++
>>   drivers/gpu/drm/msm/dp/dp_catalog.h |   4 +
>>   drivers/gpu/drm/msm/dp/dp_ctrl.c    |   4 +
>>   drivers/gpu/drm/msm/dp/dp_panel.c   |  47 +++++++++
>>   drivers/gpu/drm/msm/dp/dp_reg.h     |   3 +
>>   5 files changed, 205 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
>> b/drivers/gpu/drm/msm/dp/dp_catalog.c
>> index c025786170ba5..7e4c68be23e56 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
>> @@ -29,6 +29,9 @@
>>     #define DP_INTF_CONFIG_DATABUS_WIDEN     BIT(4)
>>   +#define DP_GENERIC0_6_YUV_8_BPC        BIT(0)
>> +#define DP_GENERIC0_6_YUV_10_BPC    BIT(1)
>> +
>>   #define DP_INTERRUPT_STATUS1 \
>>       (DP_INTR_AUX_XFER_DONE| \
>>       DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \
>> @@ -907,6 +910,150 @@ int dp_catalog_panel_timing_cfg(struct 
>> dp_catalog *dp_catalog)
>>       return 0;
>>   }
>>   +static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog 
>> *dp_catalog)
>> +{
>> +    struct dp_catalog_private *catalog;
>> +    u32 header, parity, data;
>> +    u8 bpc, off = 0;
>> +    u8 buf[SZ_128];
>> +
>> +    if (!dp_catalog) {
>> +        pr_err("invalid input\n");
>> +        return;
>> +    }
>> +
>> +    catalog = container_of(dp_catalog, struct dp_catalog_private, 
>> dp_catalog);
>> +
>> +    /* HEADER BYTE 1 */
>> +    header = dp_catalog->sdp.sdp_header.HB1;
>> +    parity = dp_catalog_calculate_parity(header);
>> +    data   = ((header << HEADER_BYTE_1_BIT) | (parity << 
>> PARITY_BYTE_1_BIT));
>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_0, data);
>> +    memcpy(buf + off, &data, sizeof(data));
>> +    off += sizeof(data);
>> +
>> +    /* HEADER BYTE 2 */
>> +    header = dp_catalog->sdp.sdp_header.HB2;
>> +    parity = dp_catalog_calculate_parity(header);
>> +    data   = ((header << HEADER_BYTE_2_BIT) | (parity << 
>> PARITY_BYTE_2_BIT));
>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_1, data);
>> +
>> +    /* HEADER BYTE 3 */
>> +    header = dp_catalog->sdp.sdp_header.HB3;
>> +    parity = dp_catalog_calculate_parity(header);
>> +    data   = ((header << HEADER_BYTE_3_BIT) | (parity << 
>> PARITY_BYTE_3_BIT));
>> +    data |= dp_read_link(catalog, MMSS_DP_GENERIC0_1);
>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_1, data);
>> +    memcpy(buf + off, &data, sizeof(data));
>> +    off += sizeof(data);
>
> This seems to be common with the dp_audio code. Please extract this 
> header writing too.
These are two different sdp's. audio and vsc, are different with 
different registers being written to and different amount of registers 
being set. Can you please clarify since in audio we only need 3 
registers to write to, and in vsc we need 10.
>
>> +
>> +    data = 0;
>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_2, data);
>> +    memcpy(buf + off, &data, sizeof(data));
>> +    off += sizeof(data);
>
> Generally this is not how these functions are expected to be written. 
> Please take a look at drivers/video/hdmi.c. It should be split into:
> - generic function that packs the C structure into a flat byte buffer,
> - driver-specific function that formats and writes the buffer to the 
> hardware.
>
>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_3, data);
>> +    memcpy(buf + off, &data, sizeof(data));
>> +    off += sizeof(data);
>> +
>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_4, data);
>> +    memcpy(buf + off, &data, sizeof(data));
>> +    off += sizeof(data);
>> +
>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_5, data);
>> +    memcpy(buf + off, &data, sizeof(data));
>> +    off += sizeof(data);
>> +
>> +    switch (dp_catalog->vsc_sdp_data.bpc) {
>> +    case 10:
>> +        bpc = DP_GENERIC0_6_YUV_10_BPC;
>> +        break;
>> +    case 8:
>> +    default:
>> +        bpc = DP_GENERIC0_6_YUV_8_BPC;
>> +        break;
>> +    }
>> +
>> +    /* VSC SDP payload as per table 2-117 of DP 1.4 specification */
>> +    data = (dp_catalog->vsc_sdp_data.colorimetry & 0xF) |
>> +           ((dp_catalog->vsc_sdp_data.pixelformat & 0xF) << 4) |
>> +           (bpc << 8) |
>> +           ((dp_catalog->vsc_sdp_data.dynamic_range & 0x1) << 15) |
>> +           ((dp_catalog->vsc_sdp_data.content_type & 0x7) << 16);
>> +
>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_6, data);
>> +    memcpy(buf + off, &data, sizeof(data));
>> +    off += sizeof(data);
>> +
>> +    data = 0;
>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_7, data);
>> +    memcpy(buf + off, &data, sizeof(data));
>> +    off += sizeof(data);
>> +
>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_8, data);
>> +    memcpy(buf + off, &data, sizeof(data));
>> +    off += sizeof(data);
>> +
>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_9, data);
>> +    memcpy(buf + off, &data, sizeof(data));
>> +    off += sizeof(data);
>> +
>> +    print_hex_dump(KERN_DEBUG, "[drm-dp] VSC: ", DUMP_PREFIX_NONE, 
>> 16, 4, buf, off, false);
>> +}
>> +
>> +void dp_catalog_panel_config_vsc_sdp(struct dp_catalog *dp_catalog, 
>> bool en)
>> +{
>> +    struct dp_catalog_private *catalog;
>> +    u32 cfg, cfg2, misc;
>> +    u16 major = 0, minor = 0;
>> +
>> +    if (!dp_catalog) {
>> +        pr_err("invalid input\n");
>> +        return;
>> +    }
>> +
>> +    catalog = container_of(dp_catalog, struct dp_catalog_private, 
>> dp_catalog);
>> +
>> +    cfg = dp_read_link(catalog, MMSS_DP_SDP_CFG);
>> +    cfg2 = dp_read_link(catalog, MMSS_DP_SDP_CFG2);
>> +    misc = dp_read_link(catalog, REG_DP_MISC1_MISC0);
>> +
>> +    if (en) {
>> +        cfg |= GEN0_SDP_EN;
>> +        dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
>> +
>> +        cfg2 |= GENERIC0_SDPSIZE;
>
> When I see a something_SIZE macro, I'd naturally expect it to be an 
> actual size of some data. Please consider renaming to e.g. 
> GENERIC0_SDPSIZE_VALID.
Ack
>
>> +        dp_write_link(catalog, MMSS_DP_SDP_CFG2, cfg2);
>> +
>> +        dp_catalog_panel_setup_vsc_sdp(dp_catalog);
>> +
>> +        /* indicates presence of VSC (BIT(6) of MISC1) */
>> +        misc |= DP_MISC1_VSC_SDP;
>> +
>> +        drm_dbg_dp(catalog->drm_dev, "vsc sdp enable=%d\n", en);
>> +    } else {
>> +        cfg &= ~GEN0_SDP_EN;
>> +        dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
>> +
>> +        cfg2 &= ~GENERIC0_SDPSIZE;
>> +        dp_write_link(catalog, MMSS_DP_SDP_CFG2, cfg2);
>> +
>> +        /* switch back to MSA */
>> +        misc &= ~DP_MISC1_VSC_SDP;
>> +
>> +        drm_dbg_dp(catalog->drm_dev, "vsc sdp enable=%d\n", en);
>> +    }
>> +
>> +    pr_debug("misc settings = 0x%x\n", misc);
>> +    dp_write_link(catalog, REG_DP_MISC1_MISC0, misc);
>> +
>> +    dp_catalog_hw_revision(dp_catalog, &major, &minor);
>> +    if (major == 1 && minor < 2) {
>> +        dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x01);
>> +        dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x00);
>> +    }
>> +}
>> +
>>   void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog,
>>                   struct drm_display_mode *drm_mode)
>>   {
>> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h 
>> b/drivers/gpu/drm/msm/dp/dp_catalog.h
>> index 94c377ef90c35..6b757249c0698 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.h
>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
>> @@ -7,6 +7,7 @@
>>   #define _DP_CATALOG_H_
>>     #include <drm/drm_modes.h>
>> +#include <drm/display/drm_dp_helper.h>
>>     #include "dp_parser.h"
>>   #include "disp/msm_disp_snapshot.h"
>> @@ -76,6 +77,8 @@ struct dp_catalog {
>>       u32 dp_active;
>>       enum dp_catalog_audio_sdp_type sdp_type;
>>       enum dp_catalog_audio_header_type sdp_header;
>> +    struct dp_sdp sdp;
>
> I assume that the sdp field contains only transient data, which is not 
> used after it gets written to the hardware. Please remove it from the 
> struct allocate on a stack or via kzalloc.
Ack
>
>> +    struct drm_dp_vsc_sdp vsc_sdp_data;
>>       u32 audio_data;
>>       bool wide_bus_en;
>>   };
>> @@ -196,6 +199,7 @@ u32 dp_catalog_ctrl_read_phy_pattern(struct 
>> dp_catalog *dp_catalog);
>>     /* DP Panel APIs */
>>   int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog);
>> +void dp_catalog_panel_config_vsc_sdp(struct dp_catalog *dp_catalog, 
>> bool en);
>>   void dp_catalog_dump_regs(struct dp_catalog *dp_catalog);
>>   void dp_catalog_panel_tpg_enable(struct dp_catalog *dp_catalog,
>>                   struct drm_display_mode *drm_mode);
>> diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c 
>> b/drivers/gpu/drm/msm/dp/dp_ctrl.c
>> index 209cf2a35642f..ddd92a63d5a67 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
>> @@ -1952,6 +1952,8 @@ int dp_ctrl_off_link_stream(struct dp_ctrl 
>> *dp_ctrl)
>>       dp_io = &ctrl->parser->io;
>>       phy = dp_io->phy;
>>   +    dp_catalog_panel_config_vsc_sdp(ctrl->catalog, false);
>> +
>>       /* set dongle to D3 (power off) mode */
>>       dp_link_psm_config(ctrl->link, &ctrl->panel->link_info, true);
>>   @@ -2026,6 +2028,8 @@ int dp_ctrl_off(struct dp_ctrl *dp_ctrl)
>>       dp_io = &ctrl->parser->io;
>>       phy = dp_io->phy;
>>   +    dp_catalog_panel_config_vsc_sdp(ctrl->catalog, false);
>> +
>>       dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, false);
>>         dp_catalog_ctrl_reset(ctrl->catalog);
>> diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c 
>> b/drivers/gpu/drm/msm/dp/dp_panel.c
>> index af7820b6d35ec..d6af9898b00d8 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_panel.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_panel.c
>> @@ -307,6 +307,49 @@ bool dp_panel_vsc_sdp_supported(struct dp_panel 
>> *dp_panel)
>>       return panel->major >= 1 && panel->minor >= 3 && 
>> panel->vsc_supported;
>>   }
>>   +static int dp_panel_setup_vsc_sdp(struct dp_panel *dp_panel)
>> +{
>> +    struct dp_catalog *catalog;
>> +    struct dp_panel_private *panel;
>> +    struct dp_display_mode *dp_mode;
>> +    int rc = 0;
>> +
>> +    if (!dp_panel) {
>> +        pr_err("invalid input\n");
>> +        rc = -EINVAL;
>> +        return rc;
>> +    }
>> +
>> +    panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
>> +    catalog = panel->catalog;
>> +    dp_mode = &dp_panel->dp_mode;
>> +
>> +    memset(&catalog->sdp, 0, sizeof(catalog->sdp));
>> +    memset(&catalog->vsc_sdp_data, 0, sizeof(catalog->vsc_sdp_data));
>> +
>> +    /* VSC SDP header as per table 2-118 of DP 1.4 specification */
>> +    catalog->sdp.sdp_header.HB0 = 0x00;
>> +    catalog->sdp.sdp_header.HB1 = 0x07;
>> +    catalog->sdp.sdp_header.HB2 = 0x05;
>> +    catalog->sdp.sdp_header.HB3 = 0x13;
>> +
>> +    /* VSC SDP Payload for DB16 */
>> +    catalog->vsc_sdp_data.pixelformat = DP_PIXELFORMAT_YUV420;
>> +    catalog->vsc_sdp_data.colorimetry = DP_COLORIMETRY_DEFAULT;
>> +
>> +    /* VSC SDP Payload for DB17 */
>> +    catalog->vsc_sdp_data.dynamic_range = DP_DYNAMIC_RANGE_CTA;
>> +
>> +    /* VSC SDP Payload for DB18 */
>> +    catalog->vsc_sdp_data.content_type = DP_CONTENT_TYPE_GRAPHICS;
>> +
>> +    catalog->vsc_sdp_data.bpc = dp_mode->bpp / 3;
>> +
>> +    dp_catalog_panel_config_vsc_sdp(catalog, true);
>> +
>> +    return rc;
>> +}
>> +
>>   void dp_panel_dump_regs(struct dp_panel *dp_panel)
>>   {
>>       struct dp_catalog *catalog;
>> @@ -370,6 +413,10 @@ int dp_panel_timing_cfg(struct dp_panel *dp_panel)
>>       catalog->dp_active = data;
>>         dp_catalog_panel_timing_cfg(catalog);
>> +
>> +    if (dp_panel->dp_mode.out_fmt_is_yuv_420)
>> +        dp_panel_setup_vsc_sdp(dp_panel);
>> +
>>       panel->panel_on = true;
>>         return 0;
>> diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h 
>> b/drivers/gpu/drm/msm/dp/dp_reg.h
>> index ea85a691e72b5..756ddf85b1e81 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_reg.h
>> +++ b/drivers/gpu/drm/msm/dp/dp_reg.h
>> @@ -142,6 +142,7 @@
>>   #define DP_MISC0_SYNCHRONOUS_CLK        (0x00000001)
>>   #define DP_MISC0_COLORIMETRY_CFG_SHIFT        (0x00000001)
>>   #define DP_MISC0_TEST_BITS_DEPTH_SHIFT        (0x00000005)
>> +#define DP_MISC1_VSC_SDP            (0x00004000)
>>     #define REG_DP_VALID_BOUNDARY            (0x00000030)
>>   #define REG_DP_VALID_BOUNDARY_2            (0x00000034)
>> @@ -201,9 +202,11 @@
>>   #define MMSS_DP_AUDIO_CTRL_RESET        (0x00000214)
>>     #define MMSS_DP_SDP_CFG                (0x00000228)
>> +#define GEN0_SDP_EN                (0x00020000)
>>   #define MMSS_DP_SDP_CFG2            (0x0000022C)
>>   #define MMSS_DP_AUDIO_TIMESTAMP_0        (0x00000230)
>>   #define MMSS_DP_AUDIO_TIMESTAMP_1        (0x00000234)
>> +#define GENERIC0_SDPSIZE            (0x00010000)
>>     #define MMSS_DP_AUDIO_STREAM_0            (0x00000240)
>>   #define MMSS_DP_AUDIO_STREAM_1            (0x00000244)
>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 10/17] drm/msm/dp: modify dp_catalog_hw_revision to show major and minor val
  2024-01-28  5:30     ` Paloma Arellano
@ 2024-01-28  5:35       ` Dmitry Baryshkov
  0 siblings, 0 replies; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-28  5:35 UTC (permalink / raw)
  To: Paloma Arellano
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh, freedreno

On Sun, 28 Jan 2024 at 07:31, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>
>
> On 1/25/2024 2:07 PM, Dmitry Baryshkov wrote:
> > On 25/01/2024 21:38, Paloma Arellano wrote:
> >> Modify dp_catalog_hw_revision to make the major and minor version values
> >> known instead of outputting the entire hex value of the hardware version
> >> register in preparation of using it for VSC SDP programming.
> >>
> >> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >> ---
> >>   drivers/gpu/drm/msm/dp/dp_catalog.c | 12 +++++++++---
> >>   drivers/gpu/drm/msm/dp/dp_catalog.h |  2 +-
> >>   2 files changed, 10 insertions(+), 4 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c
> >> b/drivers/gpu/drm/msm/dp/dp_catalog.c
> >> index 5d84c089e520a..c025786170ba5 100644
> >> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
> >> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
> >> @@ -24,6 +24,9 @@
> >>   #define DP_INTERRUPT_STATUS_ACK_SHIFT    1
> >>   #define DP_INTERRUPT_STATUS_MASK_SHIFT    2
> >>   +#define DP_HW_VERSION_MAJOR(reg)    FIELD_GET(GENMASK(31, 28), reg)
> >> +#define DP_HW_VERSION_MINOR(reg)    FIELD_GET(GENMASK(27, 16), reg)
> >> +
> >>   #define DP_INTF_CONFIG_DATABUS_WIDEN     BIT(4)
> >>     #define DP_INTERRUPT_STATUS1 \
> >> @@ -531,15 +534,18 @@ int
> >> dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog *dp_catalog,
> >>    *
> >>    * @dp_catalog: DP catalog structure
> >>    *
> >> - * Return: DP controller hw revision
> >> + * Return: void
> >>    *
> >>    */
> >> -u32 dp_catalog_hw_revision(const struct dp_catalog *dp_catalog)
> >> +void dp_catalog_hw_revision(const struct dp_catalog *dp_catalog, u16
> >> *major, u16 *minor)
> >>   {
> >>       const struct dp_catalog_private *catalog =
> >> container_of(dp_catalog,
> >>                   struct dp_catalog_private, dp_catalog);
> >> +    u32 reg_dp_hw_version;
> >>   -    return dp_read_ahb(catalog, REG_DP_HW_VERSION);
> >> +    reg_dp_hw_version = dp_read_ahb(catalog, REG_DP_HW_VERSION);
> >> +    *major = DP_HW_VERSION_MAJOR(reg_dp_hw_version);
> >> +    *minor = DP_HW_VERSION_MINOR(reg_dp_hw_version);
> >
> > After looking at the code, it might be easier to keep
> > dp_catalog_hw_revision as is, add define for hw revision 1.2 and
> > corepare to it directly.
> I thought having a  define value of the version would be harder to
> follow than what's here currently. Since having it compare to the
> version value looks a little difficult to read versus having an explicit
> major and minor value version to compare to. For example having (major
>  >= 1 && minor >= 2) versus having something like (hw_version >=
> DPU_HW_VERSION_1_2)

The problem is that major + minor are harder to follow and harder to
implement. You got them wrong, btw. For example 2.1 is greater or
equal than 1.2, but it doesn't pass your test. So, I think, a single
define is easier and less error prone.

> >
> >>   }
> >>     /**
> >> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h
> >> b/drivers/gpu/drm/msm/dp/dp_catalog.h
> >> index 563903605b3a7..94c377ef90c35 100644
> >> --- a/drivers/gpu/drm/msm/dp/dp_catalog.h
> >> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
> >> @@ -170,7 +170,7 @@ void dp_catalog_ctrl_config_misc(struct
> >> dp_catalog *dp_catalog, u32 cc, u32 tb);
> >>   void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32
> >> rate,
> >>                   u32 stream_rate_khz, bool fixed_nvid, bool
> >> is_ycbcr_420);
> >>   int dp_catalog_ctrl_set_pattern_state_bit(struct dp_catalog
> >> *dp_catalog, u32 pattern);
> >> -u32 dp_catalog_hw_revision(const struct dp_catalog *dp_catalog);
> >> +void dp_catalog_hw_revision(const struct dp_catalog *dp_catalog, u16
> >> *major, u16 *minor);
> >>   void dp_catalog_ctrl_reset(struct dp_catalog *dp_catalog);
> >>   bool dp_catalog_ctrl_mainlink_ready(struct dp_catalog *dp_catalog);
> >>   void dp_catalog_ctrl_enable_irq(struct dp_catalog *dp_catalog, bool
> >> enable);
> >



-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 11/17] drm/msm/dp: add VSC SDP support for YUV420 over DP
  2024-01-28  5:34     ` Paloma Arellano
@ 2024-01-28  5:39       ` Dmitry Baryshkov
  2024-02-01  1:56         ` Abhinav Kumar
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-28  5:39 UTC (permalink / raw)
  To: Paloma Arellano
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh, freedreno

On Sun, 28 Jan 2024 at 07:34, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>
>
> On 1/25/2024 1:48 PM, Dmitry Baryshkov wrote:
> > On 25/01/2024 21:38, Paloma Arellano wrote:
> >> Add support to pack and send the VSC SDP packet for DP. This therefore
> >> allows the transmision of format information to the sinks which is
> >> needed for YUV420 support over DP.
> >>
> >> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >> ---
> >>   drivers/gpu/drm/msm/dp/dp_catalog.c | 147 ++++++++++++++++++++++++++++
> >>   drivers/gpu/drm/msm/dp/dp_catalog.h |   4 +
> >>   drivers/gpu/drm/msm/dp/dp_ctrl.c    |   4 +
> >>   drivers/gpu/drm/msm/dp/dp_panel.c   |  47 +++++++++
> >>   drivers/gpu/drm/msm/dp/dp_reg.h     |   3 +
> >>   5 files changed, 205 insertions(+)
> >>
> >> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c
> >> b/drivers/gpu/drm/msm/dp/dp_catalog.c
> >> index c025786170ba5..7e4c68be23e56 100644
> >> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
> >> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
> >> @@ -29,6 +29,9 @@
> >>     #define DP_INTF_CONFIG_DATABUS_WIDEN     BIT(4)
> >>   +#define DP_GENERIC0_6_YUV_8_BPC        BIT(0)
> >> +#define DP_GENERIC0_6_YUV_10_BPC    BIT(1)
> >> +
> >>   #define DP_INTERRUPT_STATUS1 \
> >>       (DP_INTR_AUX_XFER_DONE| \
> >>       DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \
> >> @@ -907,6 +910,150 @@ int dp_catalog_panel_timing_cfg(struct
> >> dp_catalog *dp_catalog)
> >>       return 0;
> >>   }
> >>   +static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog
> >> *dp_catalog)
> >> +{
> >> +    struct dp_catalog_private *catalog;
> >> +    u32 header, parity, data;
> >> +    u8 bpc, off = 0;
> >> +    u8 buf[SZ_128];
> >> +
> >> +    if (!dp_catalog) {
> >> +        pr_err("invalid input\n");
> >> +        return;
> >> +    }
> >> +
> >> +    catalog = container_of(dp_catalog, struct dp_catalog_private,
> >> dp_catalog);
> >> +
> >> +    /* HEADER BYTE 1 */
> >> +    header = dp_catalog->sdp.sdp_header.HB1;
> >> +    parity = dp_catalog_calculate_parity(header);
> >> +    data   = ((header << HEADER_BYTE_1_BIT) | (parity <<
> >> PARITY_BYTE_1_BIT));
> >> +    dp_write_link(catalog, MMSS_DP_GENERIC0_0, data);
> >> +    memcpy(buf + off, &data, sizeof(data));
> >> +    off += sizeof(data);
> >> +
> >> +    /* HEADER BYTE 2 */
> >> +    header = dp_catalog->sdp.sdp_header.HB2;
> >> +    parity = dp_catalog_calculate_parity(header);
> >> +    data   = ((header << HEADER_BYTE_2_BIT) | (parity <<
> >> PARITY_BYTE_2_BIT));
> >> +    dp_write_link(catalog, MMSS_DP_GENERIC0_1, data);
> >> +
> >> +    /* HEADER BYTE 3 */
> >> +    header = dp_catalog->sdp.sdp_header.HB3;
> >> +    parity = dp_catalog_calculate_parity(header);
> >> +    data   = ((header << HEADER_BYTE_3_BIT) | (parity <<
> >> PARITY_BYTE_3_BIT));
> >> +    data |= dp_read_link(catalog, MMSS_DP_GENERIC0_1);
> >> +    dp_write_link(catalog, MMSS_DP_GENERIC0_1, data);
> >> +    memcpy(buf + off, &data, sizeof(data));
> >> +    off += sizeof(data);
> >
> > This seems to be common with the dp_audio code. Please extract this
> > header writing too.
> These are two different sdp's. audio and vsc, are different with
> different registers being written to and different amount of registers
> being set. Can you please clarify since in audio we only need 3
> registers to write to, and in vsc we need 10.

Bitmagic with the header is the same. Then the rest of the data is
written one dword per register, if I'm not mistaken.

> >
> >> +
> >> +    data = 0;
> >> +    dp_write_link(catalog, MMSS_DP_GENERIC0_2, data);
> >> +    memcpy(buf + off, &data, sizeof(data));
> >> +    off += sizeof(data);
> >
> > Generally this is not how these functions are expected to be written.
> > Please take a look at drivers/video/hdmi.c. It should be split into:
> > - generic function that packs the C structure into a flat byte buffer,
> > - driver-specific function that formats and writes the buffer to the
> > hardware.
> >
> >> +    dp_write_link(catalog, MMSS_DP_GENERIC0_3, data);
> >> +    memcpy(buf + off, &data, sizeof(data));
> >> +    off += sizeof(data);
> >> +
> >> +    dp_write_link(catalog, MMSS_DP_GENERIC0_4, data);
> >> +    memcpy(buf + off, &data, sizeof(data));
> >> +    off += sizeof(data);
> >> +
> >> +    dp_write_link(catalog, MMSS_DP_GENERIC0_5, data);
> >> +    memcpy(buf + off, &data, sizeof(data));
> >> +    off += sizeof(data);
> >> +
> >> +    switch (dp_catalog->vsc_sdp_data.bpc) {
> >> +    case 10:
> >> +        bpc = DP_GENERIC0_6_YUV_10_BPC;
> >> +        break;
> >> +    case 8:
> >> +    default:
> >> +        bpc = DP_GENERIC0_6_YUV_8_BPC;
> >> +        break;
> >> +    }
> >> +
> >> +    /* VSC SDP payload as per table 2-117 of DP 1.4 specification */
> >> +    data = (dp_catalog->vsc_sdp_data.colorimetry & 0xF) |
> >> +           ((dp_catalog->vsc_sdp_data.pixelformat & 0xF) << 4) |
> >> +           (bpc << 8) |
> >> +           ((dp_catalog->vsc_sdp_data.dynamic_range & 0x1) << 15) |
> >> +           ((dp_catalog->vsc_sdp_data.content_type & 0x7) << 16);
> >> +
> >> +    dp_write_link(catalog, MMSS_DP_GENERIC0_6, data);
> >> +    memcpy(buf + off, &data, sizeof(data));
> >> +    off += sizeof(data);
> >> +
> >> +    data = 0;
> >> +    dp_write_link(catalog, MMSS_DP_GENERIC0_7, data);
> >> +    memcpy(buf + off, &data, sizeof(data));
> >> +    off += sizeof(data);
> >> +
> >> +    dp_write_link(catalog, MMSS_DP_GENERIC0_8, data);
> >> +    memcpy(buf + off, &data, sizeof(data));
> >> +    off += sizeof(data);


-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 12/17] drm/msm/dpu: add support of new peripheral flush mechanism
  2024-01-25 21:49   ` Dmitry Baryshkov
@ 2024-01-28  5:40     ` Paloma Arellano
  2024-01-28  5:42       ` Dmitry Baryshkov
  0 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-28  5:40 UTC (permalink / raw)
  To: Dmitry Baryshkov, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, Kuogee Hsieh


On 1/25/2024 1:49 PM, Dmitry Baryshkov wrote:
> On 25/01/2024 21:38, Paloma Arellano wrote:
>> From: Kuogee Hsieh <quic_khsieh@quicinc.com>
>>
>> Introduce a peripheral flushing mechanism to decouple peripheral
>> metadata flushing from timing engine related flush.
>>
>> Signed-off-by: Kuogee Hsieh <quic_khsieh@quicinc.com>
>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>> ---
>>   .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c    |  3 +++
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c      | 17 +++++++++++++++++
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h      | 10 ++++++++++
>>   3 files changed, 30 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>> index d0f56c5c4cce9..e284bf448bdda 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>> @@ -437,6 +437,9 @@ static void dpu_encoder_phys_vid_enable(struct 
>> dpu_encoder_phys *phys_enc)
>>       if (ctl->ops.update_pending_flush_merge_3d && 
>> phys_enc->hw_pp->merge_3d)
>>           ctl->ops.update_pending_flush_merge_3d(ctl, 
>> phys_enc->hw_pp->merge_3d->idx);
>>   +    if (ctl->ops.update_pending_flush_periph && 
>> phys_enc->hw_intf->cap->type == INTF_DP)
>> +        ctl->ops.update_pending_flush_periph(ctl, 
>> phys_enc->hw_intf->idx);
>> +
>>   skip_flush:
>>       DPU_DEBUG_VIDENC(phys_enc,
>>           "update pending flush ctl %d intf %d\n",
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
>> index e76565c3e6a43..bf45afeb616d3 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
>> @@ -39,6 +39,7 @@
>>   #define   CTL_WB_FLUSH                  0x108
>>   #define   CTL_INTF_FLUSH                0x110
>>   #define   CTL_CDM_FLUSH                0x114
>> +#define   CTL_PERIPH_FLUSH              0x128
>>   #define   CTL_INTF_MASTER               0x134
>>   #define   CTL_DSPP_n_FLUSH(n)           ((0x13C) + ((n) * 4))
>>   @@ -49,6 +50,7 @@
>>   #define  MERGE_3D_IDX   23
>>   #define  DSC_IDX        22
>>   #define CDM_IDX         26
>> +#define  PERIPH_IDX     30
>>   #define  INTF_IDX       31
>>   #define WB_IDX          16
>>   #define  DSPP_IDX       29  /* From DPU hw rev 7.x.x */
>> @@ -151,6 +153,10 @@ static inline void 
>> dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
>>                   ctx->pending_dspp_flush_mask[dspp - DSPP_0]);
>>           }
>>   +    if (ctx->pending_flush_mask & BIT(PERIPH_IDX))
>> +        DPU_REG_WRITE(&ctx->hw, CTL_PERIPH_FLUSH,
>> +                  ctx->pending_periph_flush_mask);
>> +
>>       if (ctx->pending_flush_mask & BIT(DSC_IDX))
>>           DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH,
>>                     ctx->pending_dsc_flush_mask);
>> @@ -311,6 +317,13 @@ static void 
>> dpu_hw_ctl_update_pending_flush_intf_v1(struct dpu_hw_ctl *ctx,
>>       ctx->pending_flush_mask |= BIT(INTF_IDX);
>>   }
>>   +static void dpu_hw_ctl_update_pending_flush_periph(struct 
>> dpu_hw_ctl *ctx,
>> +        enum dpu_intf intf)
>
> I assume this is _v1.
> Also the argument is misaligned.
Ack.
>
>> +{
>> +    ctx->pending_periph_flush_mask |= BIT(intf - INTF_0);
>> +    ctx->pending_flush_mask |= BIT(PERIPH_IDX);
>> +}
>> +
>>   static void dpu_hw_ctl_update_pending_flush_merge_3d_v1(struct 
>> dpu_hw_ctl *ctx,
>>           enum dpu_merge_3d merge_3d)
>>   {
>> @@ -680,6 +693,10 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops 
>> *ops,
>>           ops->reset_intf_cfg = dpu_hw_ctl_reset_intf_cfg_v1;
>>           ops->update_pending_flush_intf =
>>               dpu_hw_ctl_update_pending_flush_intf_v1;
>> +
>> +        ops->update_pending_flush_periph =
>> +            dpu_hw_ctl_update_pending_flush_periph;
>> +
>>           ops->update_pending_flush_merge_3d =
>>               dpu_hw_ctl_update_pending_flush_merge_3d_v1;
>>           ops->update_pending_flush_wb = 
>> dpu_hw_ctl_update_pending_flush_wb_v1;
>
> What about the pre-active platforms?
Pre-active does not need a peripheral flush.
>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
>> index ff85b5ee0acf8..5d86c560b6d3f 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
>> @@ -122,6 +122,15 @@ struct dpu_hw_ctl_ops {
>>       void (*update_pending_flush_intf)(struct dpu_hw_ctl *ctx,
>>           enum dpu_intf blk);
>>   +    /**
>> +     * OR in the given flushbits to the cached 
>> pending_(periph_)flush_mask
>> +     * No effect on hardware
>> +     * @ctx       : ctl path ctx pointer
>> +     * @blk       : interface block index
>> +     */
>> +    void (*update_pending_flush_periph)(struct dpu_hw_ctl *ctx,
>> +        enum dpu_intf blk);
>> +
>>       /**
>>        * OR in the given flushbits to the cached 
>> pending_(merge_3d_)flush_mask
>>        * No effect on hardware
>> @@ -264,6 +273,7 @@ struct dpu_hw_ctl {
>>       u32 pending_flush_mask;
>>       u32 pending_intf_flush_mask;
>>       u32 pending_wb_flush_mask;
>> +    u32 pending_periph_flush_mask;
>>       u32 pending_merge_3d_flush_mask;
>>       u32 pending_dspp_flush_mask[DSPP_MAX - DSPP_0];
>>       u32 pending_dsc_flush_mask;
>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 12/17] drm/msm/dpu: add support of new peripheral flush mechanism
  2024-01-28  5:40     ` Paloma Arellano
@ 2024-01-28  5:42       ` Dmitry Baryshkov
  2024-02-08 23:09         ` Paloma Arellano
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-28  5:42 UTC (permalink / raw)
  To: Paloma Arellano
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel,
	Kuogee Hsieh, seanpaul, marijn.suijten, quic_jesszhan, swboyd,
	freedreno

On Sun, 28 Jan 2024 at 07:41, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>
>
> On 1/25/2024 1:49 PM, Dmitry Baryshkov wrote:
> > On 25/01/2024 21:38, Paloma Arellano wrote:
> >> From: Kuogee Hsieh <quic_khsieh@quicinc.com>
> >>
> >> Introduce a peripheral flushing mechanism to decouple peripheral
> >> metadata flushing from timing engine related flush.
> >>
> >> Signed-off-by: Kuogee Hsieh <quic_khsieh@quicinc.com>
> >> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >> ---
> >>   .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c    |  3 +++
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c      | 17 +++++++++++++++++
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h      | 10 ++++++++++
> >>   3 files changed, 30 insertions(+)
> >>
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >> index d0f56c5c4cce9..e284bf448bdda 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >> @@ -437,6 +437,9 @@ static void dpu_encoder_phys_vid_enable(struct
> >> dpu_encoder_phys *phys_enc)
> >>       if (ctl->ops.update_pending_flush_merge_3d &&
> >> phys_enc->hw_pp->merge_3d)
> >>           ctl->ops.update_pending_flush_merge_3d(ctl,
> >> phys_enc->hw_pp->merge_3d->idx);
> >>   +    if (ctl->ops.update_pending_flush_periph &&
> >> phys_enc->hw_intf->cap->type == INTF_DP)
> >> +        ctl->ops.update_pending_flush_periph(ctl,
> >> phys_enc->hw_intf->idx);
> >> +
> >>   skip_flush:
> >>       DPU_DEBUG_VIDENC(phys_enc,
> >>           "update pending flush ctl %d intf %d\n",
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> >> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> >> index e76565c3e6a43..bf45afeb616d3 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> >> @@ -39,6 +39,7 @@
> >>   #define   CTL_WB_FLUSH                  0x108
> >>   #define   CTL_INTF_FLUSH                0x110
> >>   #define   CTL_CDM_FLUSH                0x114
> >> +#define   CTL_PERIPH_FLUSH              0x128
> >>   #define   CTL_INTF_MASTER               0x134
> >>   #define   CTL_DSPP_n_FLUSH(n)           ((0x13C) + ((n) * 4))
> >>   @@ -49,6 +50,7 @@
> >>   #define  MERGE_3D_IDX   23
> >>   #define  DSC_IDX        22
> >>   #define CDM_IDX         26
> >> +#define  PERIPH_IDX     30
> >>   #define  INTF_IDX       31
> >>   #define WB_IDX          16
> >>   #define  DSPP_IDX       29  /* From DPU hw rev 7.x.x */
> >> @@ -151,6 +153,10 @@ static inline void
> >> dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
> >>                   ctx->pending_dspp_flush_mask[dspp - DSPP_0]);
> >>           }
> >>   +    if (ctx->pending_flush_mask & BIT(PERIPH_IDX))
> >> +        DPU_REG_WRITE(&ctx->hw, CTL_PERIPH_FLUSH,
> >> +                  ctx->pending_periph_flush_mask);
> >> +
> >>       if (ctx->pending_flush_mask & BIT(DSC_IDX))
> >>           DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH,
> >>                     ctx->pending_dsc_flush_mask);
> >> @@ -311,6 +317,13 @@ static void
> >> dpu_hw_ctl_update_pending_flush_intf_v1(struct dpu_hw_ctl *ctx,
> >>       ctx->pending_flush_mask |= BIT(INTF_IDX);
> >>   }
> >>   +static void dpu_hw_ctl_update_pending_flush_periph(struct
> >> dpu_hw_ctl *ctx,
> >> +        enum dpu_intf intf)
> >
> > I assume this is _v1.
> > Also the argument is misaligned.
> Ack.
> >
> >> +{
> >> +    ctx->pending_periph_flush_mask |= BIT(intf - INTF_0);
> >> +    ctx->pending_flush_mask |= BIT(PERIPH_IDX);
> >> +}
> >> +
> >>   static void dpu_hw_ctl_update_pending_flush_merge_3d_v1(struct
> >> dpu_hw_ctl *ctx,
> >>           enum dpu_merge_3d merge_3d)
> >>   {
> >> @@ -680,6 +693,10 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops
> >> *ops,
> >>           ops->reset_intf_cfg = dpu_hw_ctl_reset_intf_cfg_v1;
> >>           ops->update_pending_flush_intf =
> >>               dpu_hw_ctl_update_pending_flush_intf_v1;
> >> +
> >> +        ops->update_pending_flush_periph =
> >> +            dpu_hw_ctl_update_pending_flush_periph;
> >> +
> >>           ops->update_pending_flush_merge_3d =
> >>               dpu_hw_ctl_update_pending_flush_merge_3d_v1;
> >>           ops->update_pending_flush_wb =
> >> dpu_hw_ctl_update_pending_flush_wb_v1;
> >
> > What about the pre-active platforms?
> Pre-active does not need a peripheral flush.

Ack.

> >
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> >> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> >> index ff85b5ee0acf8..5d86c560b6d3f 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> >> @@ -122,6 +122,15 @@ struct dpu_hw_ctl_ops {
> >>       void (*update_pending_flush_intf)(struct dpu_hw_ctl *ctx,
> >>           enum dpu_intf blk);
> >>   +    /**
> >> +     * OR in the given flushbits to the cached
> >> pending_(periph_)flush_mask
> >> +     * No effect on hardware
> >> +     * @ctx       : ctl path ctx pointer
> >> +     * @blk       : interface block index
> >> +     */
> >> +    void (*update_pending_flush_periph)(struct dpu_hw_ctl *ctx,
> >> +        enum dpu_intf blk);
> >> +
> >>       /**
> >>        * OR in the given flushbits to the cached
> >> pending_(merge_3d_)flush_mask
> >>        * No effect on hardware
> >> @@ -264,6 +273,7 @@ struct dpu_hw_ctl {
> >>       u32 pending_flush_mask;
> >>       u32 pending_intf_flush_mask;
> >>       u32 pending_wb_flush_mask;
> >> +    u32 pending_periph_flush_mask;
> >>       u32 pending_merge_3d_flush_mask;
> >>       u32 pending_dspp_flush_mask[DSPP_MAX - DSPP_0];
> >>       u32 pending_dsc_flush_mask;
> >



-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 13/17] drm/msm/dp: enable SDP and SDE periph flush update
  2024-01-25 21:50   ` Dmitry Baryshkov
@ 2024-01-28  5:42     ` Paloma Arellano
  0 siblings, 0 replies; 95+ messages in thread
From: Paloma Arellano @ 2024-01-28  5:42 UTC (permalink / raw)
  To: Dmitry Baryshkov, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh


On 1/25/2024 1:50 PM, Dmitry Baryshkov wrote:
> On 25/01/2024 21:38, Paloma Arellano wrote:
>> DP controller can be setup to operate in either SDP update flush mode or
>> peripheral flush mode based on the DP controller hardware version.
>>
>> Starting in DP v1.2, the hardware documents require the use of
>> peripheral flush mode for SDP packets such as PPS OR VSC SDP packets.
>>
>> In-line with this guidance, lets program the DP controller to use
>> peripheral flush mode starting DP v1.2
>>
>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/dp/dp_catalog.c | 18 ++++++++++++++++++
>>   drivers/gpu/drm/msm/dp/dp_catalog.h |  1 +
>>   drivers/gpu/drm/msm/dp/dp_ctrl.c    |  1 +
>>   drivers/gpu/drm/msm/dp/dp_reg.h     |  2 ++
>>   4 files changed, 22 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c 
>> b/drivers/gpu/drm/msm/dp/dp_catalog.c
>> index 7e4c68be23e56..b43083b9c2df6 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
>> @@ -446,6 +446,24 @@ void dp_catalog_ctrl_config_misc(struct 
>> dp_catalog *dp_catalog,
>>       dp_write_link(catalog, REG_DP_MISC1_MISC0, misc_val);
>>   }
>>   +void dp_catalog_setup_peripheral_flush(struct dp_catalog *dp_catalog)
>> +{
>> +    u32 mainlink_ctrl;
>> +    u16 major = 0, minor = 0;
>> +    struct dp_catalog_private *catalog = container_of(dp_catalog,
>> +                struct dp_catalog_private, dp_catalog);
>> +
>> +    mainlink_ctrl = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
>> +
>> +    dp_catalog_hw_revision(dp_catalog, &major, &minor);
>> +    if (major >= 1 && minor >= 2)
>
> if (major > 1 || (major == 1 && minor >= 2))
>
> As a check, which of the values should be written for maj.min = 2.1?
Ack. My mistake
>
>> +        mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE;
>> +    else
>> +        mainlink_ctrl |= DP_MAINLINK_FLUSH_MODE_UPDATE_SDP;
>> +
>> +    dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
>> +}
>> +
>>   void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog,
>>                       u32 rate, u32 stream_rate_khz,
>>                       bool fixed_nvid, bool is_ycbcr_420)
>> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h 
>> b/drivers/gpu/drm/msm/dp/dp_catalog.h
>> index 6b757249c0698..1d57988aa6689 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.h
>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
>> @@ -169,6 +169,7 @@ void dp_catalog_ctrl_config_ctrl(struct 
>> dp_catalog *dp_catalog, u32 config);
>>   void dp_catalog_ctrl_lane_mapping(struct dp_catalog *dp_catalog);
>>   void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog, 
>> bool enable);
>>   void dp_catalog_ctrl_psr_mainlink_enable(struct dp_catalog 
>> *dp_catalog, bool enable);
>> +void dp_catalog_setup_peripheral_flush(struct dp_catalog *dp_catalog);
>>   void dp_catalog_ctrl_config_misc(struct dp_catalog *dp_catalog, u32 
>> cc, u32 tb);
>>   void dp_catalog_ctrl_config_msa(struct dp_catalog *dp_catalog, u32 
>> rate,
>>                   u32 stream_rate_khz, bool fixed_nvid, bool 
>> is_ycbcr_420);
>> diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c 
>> b/drivers/gpu/drm/msm/dp/dp_ctrl.c
>> index ddd92a63d5a67..c375b36f53ce1 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
>> @@ -170,6 +170,7 @@ static void 
>> dp_ctrl_configure_source_params(struct dp_ctrl_private *ctrl)
>>         dp_catalog_ctrl_lane_mapping(ctrl->catalog);
>>       dp_catalog_ctrl_mainlink_ctrl(ctrl->catalog, true);
>> +    dp_catalog_setup_peripheral_flush(ctrl->catalog);
>>         dp_ctrl_config_ctrl(ctrl);
>>   diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h 
>> b/drivers/gpu/drm/msm/dp/dp_reg.h
>> index 756ddf85b1e81..05a1009d2f678 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_reg.h
>> +++ b/drivers/gpu/drm/msm/dp/dp_reg.h
>> @@ -102,6 +102,8 @@
>>   #define DP_MAINLINK_CTRL_ENABLE            (0x00000001)
>>   #define DP_MAINLINK_CTRL_RESET            (0x00000002)
>>   #define DP_MAINLINK_CTRL_SW_BYPASS_SCRAMBLER    (0x00000010)
>> +#define DP_MAINLINK_FLUSH_MODE_UPDATE_SDP    (0x00800000)
>> +#define DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE (0x01800000)
>>   #define DP_MAINLINK_FB_BOUNDARY_SEL        (0x02000000)
>>     #define REG_DP_STATE_CTRL            (0x00000004)
>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 14/17] drm/msm/dpu: modify encoder programming for CDM over DP
  2024-01-25 21:57   ` Dmitry Baryshkov
@ 2024-01-28  5:48     ` Paloma Arellano
  2024-01-28  5:55       ` Dmitry Baryshkov
  0 siblings, 1 reply; 95+ messages in thread
From: Paloma Arellano @ 2024-01-28  5:48 UTC (permalink / raw)
  To: Dmitry Baryshkov, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh


On 1/25/2024 1:57 PM, Dmitry Baryshkov wrote:
> On 25/01/2024 21:38, Paloma Arellano wrote:
>> Adjust the encoder format programming in the case of video mode for DP
>> to accommodate CDM related changes.
>>
>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 16 +++++++++
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |  8 +++++
>>   .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 35 ++++++++++++++++---
>>   drivers/gpu/drm/msm/dp/dp_display.c           | 12 +++++++
>>   drivers/gpu/drm/msm/msm_drv.h                 |  9 ++++-
>>   5 files changed, 75 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> index b0896814c1562..99ec53446ad21 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> @@ -222,6 +222,22 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = {
>>       15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10
>>   };
>>   +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc, 
>> const struct drm_display_mode *mode)
>> +{
>> +    const struct dpu_encoder_virt *dpu_enc;
>> +    const struct msm_display_info *disp_info;
>> +    struct msm_drm_private *priv;
>> +
>> +    dpu_enc = to_dpu_encoder_virt(drm_enc);
>> +    disp_info = &dpu_enc->disp_info;
>> +    priv = drm_enc->dev->dev_private;
>> +
>> +    if (disp_info->intf_type == INTF_DP &&
>> + msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]], 
>> mode))
>
> This should not require interacting with DP. If we got here, we must 
> be sure that 4:2:0 is supported and can be configured.
Ack. Will drop this function and only check for if the mode is YUV420.
>
>> +        return DRM_FORMAT_YUV420;
>> +
>> +    return DRM_FORMAT_RGB888;
>> +}
>>     bool dpu_encoder_is_widebus_enabled(const struct drm_encoder 
>> *drm_enc)
>>   {
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>> index 7b4afa71f1f96..62255d0aa4487 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>> @@ -162,6 +162,14 @@ int dpu_encoder_get_vsync_count(struct 
>> drm_encoder *drm_enc);
>>    */
>>   bool dpu_encoder_is_widebus_enabled(const struct drm_encoder 
>> *drm_enc);
>>   +/**
>> + * dpu_encoder_get_drm_fmt - return DRM fourcc format
>> + * @drm_enc:    Pointer to previously created drm encoder structure
>> + * @mode:    Corresponding drm_display_mode for dpu encoder
>> + */
>> +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
>> +                const struct drm_display_mode *mode);
>> +
>>   /**
>>    * dpu_encoder_get_crc_values_cnt - get number of physical encoders 
>> contained
>>    *    in virtual encoder that can collect CRC values
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>> index e284bf448bdda..a1dde0ff35dc8 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>> @@ -234,6 +234,7 @@ static void 
>> dpu_encoder_phys_vid_setup_timing_engine(
>>   {
>>       struct drm_display_mode mode;
>>       struct dpu_hw_intf_timing_params timing_params = { 0 };
>> +    struct dpu_hw_cdm *hw_cdm;
>>       const struct dpu_format *fmt = NULL;
>>       u32 fmt_fourcc = DRM_FORMAT_RGB888;
>>       unsigned long lock_flags;
>> @@ -254,17 +255,26 @@ static void 
>> dpu_encoder_phys_vid_setup_timing_engine(
>>       DPU_DEBUG_VIDENC(phys_enc, "enabling mode:\n");
>>       drm_mode_debug_printmodeline(&mode);
>>   -    if (phys_enc->split_role != ENC_ROLE_SOLO) {
>> +    hw_cdm = phys_enc->hw_cdm;
>> +    if (hw_cdm) {
>> +        intf_cfg.cdm = hw_cdm->idx;
>> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent, &mode);
>> +    }
>> +
>> +    if (phys_enc->split_role != ENC_ROLE_SOLO ||
>> +        dpu_encoder_get_drm_fmt(phys_enc->parent, &mode) == 
>> DRM_FORMAT_YUV420) {
>>           mode.hdisplay >>= 1;
>>           mode.htotal >>= 1;
>>           mode.hsync_start >>= 1;
>>           mode.hsync_end >>= 1;
>> +        mode.hskew >>= 1;
>
> Separate patch.
Ack.
>
>>             DPU_DEBUG_VIDENC(phys_enc,
>> -            "split_role %d, halve horizontal %d %d %d %d\n",
>> +            "split_role %d, halve horizontal %d %d %d %d %d\n",
>>               phys_enc->split_role,
>>               mode.hdisplay, mode.htotal,
>> -            mode.hsync_start, mode.hsync_end);
>> +            mode.hsync_start, mode.hsync_end,
>> +            mode.hskew);
>>       }
>>         drm_mode_to_intf_timing_params(phys_enc, &mode, &timing_params);
>> @@ -412,8 +422,15 @@ static int dpu_encoder_phys_vid_control_vblank_irq(
>>   static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys 
>> *phys_enc)
>>   {
>>       struct dpu_hw_ctl *ctl;
>> +    struct dpu_hw_cdm *hw_cdm;
>> +    const struct dpu_format *fmt = NULL;
>> +    u32 fmt_fourcc = DRM_FORMAT_RGB888;
>>         ctl = phys_enc->hw_ctl;
>> +    hw_cdm = phys_enc->hw_cdm;
>> +    if (hw_cdm)
>> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent, 
>> &phys_enc->cached_mode);
>> +    fmt = dpu_get_dpu_format(fmt_fourcc);
>>         DPU_DEBUG_VIDENC(phys_enc, "\n");
>>   @@ -422,6 +439,8 @@ static void dpu_encoder_phys_vid_enable(struct 
>> dpu_encoder_phys *phys_enc)
>>         dpu_encoder_helper_split_config(phys_enc, 
>> phys_enc->hw_intf->idx);
>>   +    dpu_encoder_helper_phys_setup_cdm(phys_enc, fmt, 
>> CDM_CDWN_OUTPUT_HDMI);
>
> If there is no CDM, why do we need to call this?
Inside of dpu_encoder_helper_phys_setup_cdm(), there's a check to see if 
there is a hw_cdm. If there is not, then it immediately exits the function.
>
>> +
>>       dpu_encoder_phys_vid_setup_timing_engine(phys_enc);
>>         /*
>> @@ -437,7 +456,15 @@ static void dpu_encoder_phys_vid_enable(struct 
>> dpu_encoder_phys *phys_enc)
>>       if (ctl->ops.update_pending_flush_merge_3d && 
>> phys_enc->hw_pp->merge_3d)
>>           ctl->ops.update_pending_flush_merge_3d(ctl, 
>> phys_enc->hw_pp->merge_3d->idx);
>>   -    if (ctl->ops.update_pending_flush_periph && 
>> phys_enc->hw_intf->cap->type == INTF_DP)
>> +    if (ctl->ops.update_pending_flush_cdm && phys_enc->hw_cdm)
>> +        ctl->ops.update_pending_flush_cdm(ctl, hw_cdm->idx);
>> +
>> +    /*
>> +     * Peripheral flush must be updated whenever flushing SDP 
>> packets is needed.
>> +     * SDP packets are required for any YUV format (YUV420, YUV422, 
>> YUV444).
>> +     */
>> +    if (ctl->ops.update_pending_flush_periph && 
>> phys_enc->hw_intf->cap->type == INTF_DP &&
>> +        phys_enc->hw_cdm)
>>           ctl->ops.update_pending_flush_periph(ctl, 
>> phys_enc->hw_intf->idx);
>
> Should there be a flush if we are switching from YUV 420 to RGB mode?
We only need to flush for the sdp packet, but for msa we do not need to 
flush.
>
> Also, I'd say, we should move update_pending_flush_periph invocation 
> to this patch.
Ack
>
>>     skip_flush:
>> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
>> b/drivers/gpu/drm/msm/dp/dp_display.c
>> index 6d764f5b08727..4329435518351 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
>> @@ -1399,6 +1399,18 @@ void __exit msm_dp_unregister(void)
>>       platform_driver_unregister(&dp_display_driver);
>>   }
>>   +bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
>> +                   const struct drm_display_mode *mode)
>> +{
>> +    struct dp_display_private *dp;
>> +    const struct drm_display_info *info;
>> +
>> +    dp = container_of(dp_display, struct dp_display_private, 
>> dp_display);
>> +    info = &dp_display->connector->display_info;
>> +
>> +    return dp_panel_vsc_sdp_supported(dp->panel) && 
>> drm_mode_is_420_only(info, mode);
>
> YUV 420 modes should be filtered out in mode_valid if VSC SDP is not 
> supported.
Ack. Will change
>
>> +}
>> +
>>   bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)
>>   {
>>       struct dp_display_private *dp;
>> diff --git a/drivers/gpu/drm/msm/msm_drv.h 
>> b/drivers/gpu/drm/msm/msm_drv.h
>> index 16a7cbc0b7dd8..b9581bd934e9e 100644
>> --- a/drivers/gpu/drm/msm/msm_drv.h
>> +++ b/drivers/gpu/drm/msm/msm_drv.h
>> @@ -387,7 +387,8 @@ void __exit msm_dp_unregister(void);
>>   int msm_dp_modeset_init(struct msm_dp *dp_display, struct 
>> drm_device *dev,
>>                struct drm_encoder *encoder);
>>   void msm_dp_snapshot(struct msm_disp_state *disp_state, struct 
>> msm_dp *dp_display);
>> -
>> +bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
>> +                   const struct drm_display_mode *mode);
>>   bool msm_dp_wide_bus_available(const struct msm_dp *dp_display);
>>     #else
>> @@ -409,6 +410,12 @@ static inline void msm_dp_snapshot(struct 
>> msm_disp_state *disp_state, struct msm
>>   {
>>   }
>>   +static inline bool msm_dp_is_yuv_420_enabled(const struct msm_dp 
>> *dp_display,
>> +                         const struct drm_display_mode *mode)
>> +{
>> +    return false;
>> +}
>> +
>>   static inline bool msm_dp_wide_bus_available(const struct msm_dp 
>> *dp_display)
>>   {
>>       return false;
>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 16/17] drm/msm/dpu: reserve CDM blocks for DP if mode is YUV420
  2024-01-25 22:01   ` Dmitry Baryshkov
@ 2024-01-28  5:48     ` Paloma Arellano
  0 siblings, 0 replies; 95+ messages in thread
From: Paloma Arellano @ 2024-01-28  5:48 UTC (permalink / raw)
  To: Dmitry Baryshkov, freedreno
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh


On 1/25/2024 2:01 PM, Dmitry Baryshkov wrote:
> On 25/01/2024 21:38, Paloma Arellano wrote:
>> Reserve CDM blocks for DP if the mode format is YUV420. Currently this
>> reservation only works for writeback and DP if the format is YUV420. But
>> this can be easily extented to other YUV formats for DP.
>>
>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 20 +++++++++++++-------
>>   1 file changed, 13 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> index 99ec53446ad21..c7dcda3d54ae6 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> @@ -613,6 +613,7 @@ static int dpu_encoder_virt_atomic_check(
>>       struct dpu_kms *dpu_kms;
>>       struct drm_display_mode *adj_mode;
>>       struct msm_display_topology topology;
>> +    struct msm_display_info *disp_info;
>>       struct dpu_global_state *global_state;
>>       struct drm_framebuffer *fb;
>>       struct drm_dsc_config *dsc;
>> @@ -629,6 +630,7 @@ static int dpu_encoder_virt_atomic_check(
>>       DPU_DEBUG_ENC(dpu_enc, "\n");
>>         priv = drm_enc->dev->dev_private;
>> +    disp_info = &dpu_enc->disp_info;
>>       dpu_kms = to_dpu_kms(priv->kms);
>>       adj_mode = &crtc_state->adjusted_mode;
>>       global_state = dpu_kms_get_global_state(crtc_state->state);
>> @@ -656,8 +658,8 @@ static int dpu_encoder_virt_atomic_check(
>>       topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode, 
>> crtc_state, dsc);
>>         /*
>> -     * Use CDM only for writeback at the moment as other interfaces 
>> cannot handle it.
>> -     * if writeback itself cannot handle cdm for some reason it will 
>> fail in its atomic_check()
>> +     * Use CDM only for writeback or DP at the moment as other 
>> interfaces cannot handle it.
>> +     * If writeback itself cannot handle cdm for some reason it will 
>> fail in its atomic_check()
>>        * earlier.
>>        */
>>       if (dpu_enc->disp_info.intf_type == INTF_WB && 
>> conn_state->writeback_job) {
>> @@ -665,12 +667,15 @@ static int dpu_encoder_virt_atomic_check(
>>             if (fb && 
>> DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(fb))))
>>               topology.needs_cdm = true;
>> -        if (topology.needs_cdm && !dpu_enc->cur_master->hw_cdm)
>> -            crtc_state->mode_changed = true;
>> -        else if (!topology.needs_cdm && dpu_enc->cur_master->hw_cdm)
>> -            crtc_state->mode_changed = true;
>> +    } else if (dpu_enc->disp_info.intf_type == INTF_DP) {
>
> You can use disp_info directly here.
Ack
>
>> +        if 
>> (msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]], 
>> adj_mode))
>> +            topology.needs_cdm = true;
>>       }
>>   +    if (topology.needs_cdm && !dpu_enc->cur_master->hw_cdm)
>> +        crtc_state->mode_changed = true;
>> +    else if (!topology.needs_cdm && dpu_enc->cur_master->hw_cdm)
>> +        crtc_state->mode_changed = true;
>>       /*
>>        * Release and Allocate resources on every modeset
>>        * Dont allocate when active is false.
>> @@ -1111,7 +1116,8 @@ static void 
>> dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>>         dpu_enc->dsc_mask = dsc_mask;
>>   -    if (dpu_enc->disp_info.intf_type == INTF_WB && 
>> conn_state->writeback_job) {
>> +    if ((dpu_enc->disp_info.intf_type == INTF_WB && 
>> conn_state->writeback_job) ||
>> +        dpu_enc->disp_info.intf_type == INTF_DP) {
>>           struct dpu_hw_blk *hw_cdm = NULL;
>>             dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 14/17] drm/msm/dpu: modify encoder programming for CDM over DP
  2024-01-28  5:48     ` Paloma Arellano
@ 2024-01-28  5:55       ` Dmitry Baryshkov
  2024-01-29  2:58         ` Abhinav Kumar
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-28  5:55 UTC (permalink / raw)
  To: Paloma Arellano
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh, freedreno

On Sun, 28 Jan 2024 at 07:48, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>
>
> On 1/25/2024 1:57 PM, Dmitry Baryshkov wrote:
> > On 25/01/2024 21:38, Paloma Arellano wrote:
> >> Adjust the encoder format programming in the case of video mode for DP
> >> to accommodate CDM related changes.
> >>
> >> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >> ---
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 16 +++++++++
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |  8 +++++
> >>   .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 35 ++++++++++++++++---
> >>   drivers/gpu/drm/msm/dp/dp_display.c           | 12 +++++++
> >>   drivers/gpu/drm/msm/msm_drv.h                 |  9 ++++-
> >>   5 files changed, 75 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> index b0896814c1562..99ec53446ad21 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> @@ -222,6 +222,22 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = {
> >>       15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10
> >>   };
> >>   +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
> >> const struct drm_display_mode *mode)
> >> +{
> >> +    const struct dpu_encoder_virt *dpu_enc;
> >> +    const struct msm_display_info *disp_info;
> >> +    struct msm_drm_private *priv;
> >> +
> >> +    dpu_enc = to_dpu_encoder_virt(drm_enc);
> >> +    disp_info = &dpu_enc->disp_info;
> >> +    priv = drm_enc->dev->dev_private;
> >> +
> >> +    if (disp_info->intf_type == INTF_DP &&
> >> + msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]],
> >> mode))
> >
> > This should not require interacting with DP. If we got here, we must
> > be sure that 4:2:0 is supported and can be configured.
> Ack. Will drop this function and only check for if the mode is YUV420.
> >
> >> +        return DRM_FORMAT_YUV420;
> >> +
> >> +    return DRM_FORMAT_RGB888;
> >> +}
> >>     bool dpu_encoder_is_widebus_enabled(const struct drm_encoder
> >> *drm_enc)
> >>   {
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> >> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> >> index 7b4afa71f1f96..62255d0aa4487 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> >> @@ -162,6 +162,14 @@ int dpu_encoder_get_vsync_count(struct
> >> drm_encoder *drm_enc);
> >>    */
> >>   bool dpu_encoder_is_widebus_enabled(const struct drm_encoder
> >> *drm_enc);
> >>   +/**
> >> + * dpu_encoder_get_drm_fmt - return DRM fourcc format
> >> + * @drm_enc:    Pointer to previously created drm encoder structure
> >> + * @mode:    Corresponding drm_display_mode for dpu encoder
> >> + */
> >> +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
> >> +                const struct drm_display_mode *mode);
> >> +
> >>   /**
> >>    * dpu_encoder_get_crc_values_cnt - get number of physical encoders
> >> contained
> >>    *    in virtual encoder that can collect CRC values
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >> index e284bf448bdda..a1dde0ff35dc8 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >> @@ -234,6 +234,7 @@ static void
> >> dpu_encoder_phys_vid_setup_timing_engine(
> >>   {
> >>       struct drm_display_mode mode;
> >>       struct dpu_hw_intf_timing_params timing_params = { 0 };
> >> +    struct dpu_hw_cdm *hw_cdm;
> >>       const struct dpu_format *fmt = NULL;
> >>       u32 fmt_fourcc = DRM_FORMAT_RGB888;
> >>       unsigned long lock_flags;
> >> @@ -254,17 +255,26 @@ static void
> >> dpu_encoder_phys_vid_setup_timing_engine(
> >>       DPU_DEBUG_VIDENC(phys_enc, "enabling mode:\n");
> >>       drm_mode_debug_printmodeline(&mode);
> >>   -    if (phys_enc->split_role != ENC_ROLE_SOLO) {
> >> +    hw_cdm = phys_enc->hw_cdm;
> >> +    if (hw_cdm) {
> >> +        intf_cfg.cdm = hw_cdm->idx;
> >> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent, &mode);
> >> +    }
> >> +
> >> +    if (phys_enc->split_role != ENC_ROLE_SOLO ||
> >> +        dpu_encoder_get_drm_fmt(phys_enc->parent, &mode) ==
> >> DRM_FORMAT_YUV420) {
> >>           mode.hdisplay >>= 1;
> >>           mode.htotal >>= 1;
> >>           mode.hsync_start >>= 1;
> >>           mode.hsync_end >>= 1;
> >> +        mode.hskew >>= 1;
> >
> > Separate patch.
> Ack.
> >
> >>             DPU_DEBUG_VIDENC(phys_enc,
> >> -            "split_role %d, halve horizontal %d %d %d %d\n",
> >> +            "split_role %d, halve horizontal %d %d %d %d %d\n",
> >>               phys_enc->split_role,
> >>               mode.hdisplay, mode.htotal,
> >> -            mode.hsync_start, mode.hsync_end);
> >> +            mode.hsync_start, mode.hsync_end,
> >> +            mode.hskew);
> >>       }
> >>         drm_mode_to_intf_timing_params(phys_enc, &mode, &timing_params);
> >> @@ -412,8 +422,15 @@ static int dpu_encoder_phys_vid_control_vblank_irq(
> >>   static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys
> >> *phys_enc)
> >>   {
> >>       struct dpu_hw_ctl *ctl;
> >> +    struct dpu_hw_cdm *hw_cdm;
> >> +    const struct dpu_format *fmt = NULL;
> >> +    u32 fmt_fourcc = DRM_FORMAT_RGB888;
> >>         ctl = phys_enc->hw_ctl;
> >> +    hw_cdm = phys_enc->hw_cdm;
> >> +    if (hw_cdm)
> >> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent,
> >> &phys_enc->cached_mode);
> >> +    fmt = dpu_get_dpu_format(fmt_fourcc);
> >>         DPU_DEBUG_VIDENC(phys_enc, "\n");
> >>   @@ -422,6 +439,8 @@ static void dpu_encoder_phys_vid_enable(struct
> >> dpu_encoder_phys *phys_enc)
> >>         dpu_encoder_helper_split_config(phys_enc,
> >> phys_enc->hw_intf->idx);
> >>   +    dpu_encoder_helper_phys_setup_cdm(phys_enc, fmt,
> >> CDM_CDWN_OUTPUT_HDMI);
> >
> > If there is no CDM, why do we need to call this?
> Inside of dpu_encoder_helper_phys_setup_cdm(), there's a check to see if
> there is a hw_cdm. If there is not, then it immediately exits the function.
> >
> >> +
> >>       dpu_encoder_phys_vid_setup_timing_engine(phys_enc);
> >>         /*
> >> @@ -437,7 +456,15 @@ static void dpu_encoder_phys_vid_enable(struct
> >> dpu_encoder_phys *phys_enc)
> >>       if (ctl->ops.update_pending_flush_merge_3d &&
> >> phys_enc->hw_pp->merge_3d)
> >>           ctl->ops.update_pending_flush_merge_3d(ctl,
> >> phys_enc->hw_pp->merge_3d->idx);
> >>   -    if (ctl->ops.update_pending_flush_periph &&
> >> phys_enc->hw_intf->cap->type == INTF_DP)
> >> +    if (ctl->ops.update_pending_flush_cdm && phys_enc->hw_cdm)
> >> +        ctl->ops.update_pending_flush_cdm(ctl, hw_cdm->idx);
> >> +
> >> +    /*
> >> +     * Peripheral flush must be updated whenever flushing SDP
> >> packets is needed.
> >> +     * SDP packets are required for any YUV format (YUV420, YUV422,
> >> YUV444).
> >> +     */
> >> +    if (ctl->ops.update_pending_flush_periph &&
> >> phys_enc->hw_intf->cap->type == INTF_DP &&
> >> +        phys_enc->hw_cdm)
> >>           ctl->ops.update_pending_flush_periph(ctl,
> >> phys_enc->hw_intf->idx);
> >
> > Should there be a flush if we are switching from YUV 420 to RGB mode?
> We only need to flush for the sdp packet, but for msa we do not need to
> flush.

What about having SDP with RGB as colorimetry? In other words, if
there is a decision point, this one looks incorrect.

> >
> > Also, I'd say, we should move update_pending_flush_periph invocation
> > to this patch.
> Ack
> >
> >>     skip_flush:
> >> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
> >> b/drivers/gpu/drm/msm/dp/dp_display.c
> >> index 6d764f5b08727..4329435518351 100644
> >> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> >> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> >> @@ -1399,6 +1399,18 @@ void __exit msm_dp_unregister(void)
> >>       platform_driver_unregister(&dp_display_driver);
> >>   }
> >>   +bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
> >> +                   const struct drm_display_mode *mode)
> >> +{
> >> +    struct dp_display_private *dp;
> >> +    const struct drm_display_info *info;
> >> +
> >> +    dp = container_of(dp_display, struct dp_display_private,
> >> dp_display);
> >> +    info = &dp_display->connector->display_info;
> >> +
> >> +    return dp_panel_vsc_sdp_supported(dp->panel) &&
> >> drm_mode_is_420_only(info, mode);
> >
> > YUV 420 modes should be filtered out in mode_valid if VSC SDP is not
> > supported.
> Ack. Will change
> >
> >> +}
> >> +
> >>   bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)
> >>   {
> >>       struct dp_display_private *dp;
> >> diff --git a/drivers/gpu/drm/msm/msm_drv.h
> >> b/drivers/gpu/drm/msm/msm_drv.h
> >> index 16a7cbc0b7dd8..b9581bd934e9e 100644
> >> --- a/drivers/gpu/drm/msm/msm_drv.h
> >> +++ b/drivers/gpu/drm/msm/msm_drv.h
> >> @@ -387,7 +387,8 @@ void __exit msm_dp_unregister(void);
> >>   int msm_dp_modeset_init(struct msm_dp *dp_display, struct
> >> drm_device *dev,
> >>                struct drm_encoder *encoder);
> >>   void msm_dp_snapshot(struct msm_disp_state *disp_state, struct
> >> msm_dp *dp_display);
> >> -
> >> +bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
> >> +                   const struct drm_display_mode *mode);
> >>   bool msm_dp_wide_bus_available(const struct msm_dp *dp_display);
> >>     #else
> >> @@ -409,6 +410,12 @@ static inline void msm_dp_snapshot(struct
> >> msm_disp_state *disp_state, struct msm
> >>   {
> >>   }
> >>   +static inline bool msm_dp_is_yuv_420_enabled(const struct msm_dp
> >> *dp_display,
> >> +                         const struct drm_display_mode *mode)
> >> +{
> >> +    return false;
> >> +}
> >> +
> >>   static inline bool msm_dp_wide_bus_available(const struct msm_dp
> >> *dp_display)
> >>   {
> >>       return false;
> >



--
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 10/17] drm/msm/dp: modify dp_catalog_hw_revision to show major and minor val
  2024-01-25 19:38 ` [PATCH 10/17] drm/msm/dp: modify dp_catalog_hw_revision to show major and minor val Paloma Arellano
  2024-01-25 22:07   ` Dmitry Baryshkov
  2024-01-27 23:43   ` kernel test robot
@ 2024-01-28 14:02   ` kernel test robot
  2 siblings, 0 replies; 95+ messages in thread
From: kernel test robot @ 2024-01-28 14:02 UTC (permalink / raw)
  To: Paloma Arellano, freedreno
  Cc: neil.armstrong, quic_jesszhan, linux-arm-msm, llvm,
	Paloma Arellano, quic_abhinavk, dri-devel, swboyd, seanpaul,
	oe-kbuild-all, dmitry.baryshkov, marijn.suijten, quic_khsieh

Hi Paloma,

kernel test robot noticed the following build errors:

[auto build test ERROR on v6.8-rc1]
[also build test ERROR on linus/master next-20240125]
[cannot apply to drm-misc/drm-misc-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Paloma-Arellano/drm-msm-dpu-allow-dpu_encoder_helper_phys_setup_cdm-to-work-for-DP/20240126-034233
base:   v6.8-rc1
patch link:    https://lore.kernel.org/r/20240125193834.7065-11-quic_parellan%40quicinc.com
patch subject: [PATCH 10/17] drm/msm/dp: modify dp_catalog_hw_revision to show major and minor val
config: arm-defconfig (https://download.01.org/0day-ci/archive/20240128/202401282131.j7UUVG6P-lkp@intel.com/config)
compiler: clang version 14.0.6 (https://github.com/llvm/llvm-project.git f28c006a5895fc0e329fe15fead81e37457cb1d1)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240128/202401282131.j7UUVG6P-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202401282131.j7UUVG6P-lkp@intel.com/

All errors (new ones prefixed by >>):

>> drivers/gpu/drm/msm/dp/dp_catalog.c:547:11: error: implicit declaration of function 'FIELD_GET' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
           *major = DP_HW_VERSION_MAJOR(reg_dp_hw_version);
                    ^
   drivers/gpu/drm/msm/dp/dp_catalog.c:27:34: note: expanded from macro 'DP_HW_VERSION_MAJOR'
   #define DP_HW_VERSION_MAJOR(reg)        FIELD_GET(GENMASK(31, 28), reg)
                                           ^
   1 error generated.


vim +/FIELD_GET +547 drivers/gpu/drm/msm/dp/dp_catalog.c

   531	
   532	/**
   533	 * dp_catalog_hw_revision() - retrieve DP hw revision
   534	 *
   535	 * @dp_catalog: DP catalog structure
   536	 *
   537	 * Return: void
   538	 *
   539	 */
   540	void dp_catalog_hw_revision(const struct dp_catalog *dp_catalog, u16 *major, u16 *minor)
   541	{
   542		const struct dp_catalog_private *catalog = container_of(dp_catalog,
   543					struct dp_catalog_private, dp_catalog);
   544		u32 reg_dp_hw_version;
   545	
   546		reg_dp_hw_version = dp_read_ahb(catalog, REG_DP_HW_VERSION);
 > 547		*major = DP_HW_VERSION_MAJOR(reg_dp_hw_version);
   548		*minor = DP_HW_VERSION_MINOR(reg_dp_hw_version);
   549	}
   550	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 14/17] drm/msm/dpu: modify encoder programming for CDM over DP
  2024-01-28  5:55       ` Dmitry Baryshkov
@ 2024-01-29  2:58         ` Abhinav Kumar
  2024-01-29  3:42           ` Dmitry Baryshkov
  0 siblings, 1 reply; 95+ messages in thread
From: Abhinav Kumar @ 2024-01-29  2:58 UTC (permalink / raw)
  To: Dmitry Baryshkov, Paloma Arellano
  Cc: neil.armstrong, linux-arm-msm, dri-devel, swboyd, seanpaul,
	marijn.suijten, quic_jesszhan, quic_khsieh, freedreno



On 1/27/2024 9:55 PM, Dmitry Baryshkov wrote:
> On Sun, 28 Jan 2024 at 07:48, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>>
>>
>> On 1/25/2024 1:57 PM, Dmitry Baryshkov wrote:
>>> On 25/01/2024 21:38, Paloma Arellano wrote:
>>>> Adjust the encoder format programming in the case of video mode for DP
>>>> to accommodate CDM related changes.
>>>>
>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>>> ---
>>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 16 +++++++++
>>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |  8 +++++
>>>>    .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 35 ++++++++++++++++---
>>>>    drivers/gpu/drm/msm/dp/dp_display.c           | 12 +++++++
>>>>    drivers/gpu/drm/msm/msm_drv.h                 |  9 ++++-
>>>>    5 files changed, 75 insertions(+), 5 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>> index b0896814c1562..99ec53446ad21 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>> @@ -222,6 +222,22 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = {
>>>>        15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10
>>>>    };
>>>>    +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
>>>> const struct drm_display_mode *mode)
>>>> +{
>>>> +    const struct dpu_encoder_virt *dpu_enc;
>>>> +    const struct msm_display_info *disp_info;
>>>> +    struct msm_drm_private *priv;
>>>> +
>>>> +    dpu_enc = to_dpu_encoder_virt(drm_enc);
>>>> +    disp_info = &dpu_enc->disp_info;
>>>> +    priv = drm_enc->dev->dev_private;
>>>> +
>>>> +    if (disp_info->intf_type == INTF_DP &&
>>>> + msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]],
>>>> mode))
>>>
>>> This should not require interacting with DP. If we got here, we must
>>> be sure that 4:2:0 is supported and can be configured.
>> Ack. Will drop this function and only check for if the mode is YUV420.
>>>
>>>> +        return DRM_FORMAT_YUV420;
>>>> +
>>>> +    return DRM_FORMAT_RGB888;
>>>> +}
>>>>      bool dpu_encoder_is_widebus_enabled(const struct drm_encoder
>>>> *drm_enc)
>>>>    {
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>>>> index 7b4afa71f1f96..62255d0aa4487 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>>>> @@ -162,6 +162,14 @@ int dpu_encoder_get_vsync_count(struct
>>>> drm_encoder *drm_enc);
>>>>     */
>>>>    bool dpu_encoder_is_widebus_enabled(const struct drm_encoder
>>>> *drm_enc);
>>>>    +/**
>>>> + * dpu_encoder_get_drm_fmt - return DRM fourcc format
>>>> + * @drm_enc:    Pointer to previously created drm encoder structure
>>>> + * @mode:    Corresponding drm_display_mode for dpu encoder
>>>> + */
>>>> +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
>>>> +                const struct drm_display_mode *mode);
>>>> +
>>>>    /**
>>>>     * dpu_encoder_get_crc_values_cnt - get number of physical encoders
>>>> contained
>>>>     *    in virtual encoder that can collect CRC values
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>> index e284bf448bdda..a1dde0ff35dc8 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>> @@ -234,6 +234,7 @@ static void
>>>> dpu_encoder_phys_vid_setup_timing_engine(
>>>>    {
>>>>        struct drm_display_mode mode;
>>>>        struct dpu_hw_intf_timing_params timing_params = { 0 };
>>>> +    struct dpu_hw_cdm *hw_cdm;
>>>>        const struct dpu_format *fmt = NULL;
>>>>        u32 fmt_fourcc = DRM_FORMAT_RGB888;
>>>>        unsigned long lock_flags;
>>>> @@ -254,17 +255,26 @@ static void
>>>> dpu_encoder_phys_vid_setup_timing_engine(
>>>>        DPU_DEBUG_VIDENC(phys_enc, "enabling mode:\n");
>>>>        drm_mode_debug_printmodeline(&mode);
>>>>    -    if (phys_enc->split_role != ENC_ROLE_SOLO) {
>>>> +    hw_cdm = phys_enc->hw_cdm;
>>>> +    if (hw_cdm) {
>>>> +        intf_cfg.cdm = hw_cdm->idx;
>>>> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent, &mode);
>>>> +    }
>>>> +
>>>> +    if (phys_enc->split_role != ENC_ROLE_SOLO ||
>>>> +        dpu_encoder_get_drm_fmt(phys_enc->parent, &mode) ==
>>>> DRM_FORMAT_YUV420) {
>>>>            mode.hdisplay >>= 1;
>>>>            mode.htotal >>= 1;
>>>>            mode.hsync_start >>= 1;
>>>>            mode.hsync_end >>= 1;
>>>> +        mode.hskew >>= 1;
>>>
>>> Separate patch.
>> Ack.
>>>
>>>>              DPU_DEBUG_VIDENC(phys_enc,
>>>> -            "split_role %d, halve horizontal %d %d %d %d\n",
>>>> +            "split_role %d, halve horizontal %d %d %d %d %d\n",
>>>>                phys_enc->split_role,
>>>>                mode.hdisplay, mode.htotal,
>>>> -            mode.hsync_start, mode.hsync_end);
>>>> +            mode.hsync_start, mode.hsync_end,
>>>> +            mode.hskew);
>>>>        }
>>>>          drm_mode_to_intf_timing_params(phys_enc, &mode, &timing_params);
>>>> @@ -412,8 +422,15 @@ static int dpu_encoder_phys_vid_control_vblank_irq(
>>>>    static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys
>>>> *phys_enc)
>>>>    {
>>>>        struct dpu_hw_ctl *ctl;
>>>> +    struct dpu_hw_cdm *hw_cdm;
>>>> +    const struct dpu_format *fmt = NULL;
>>>> +    u32 fmt_fourcc = DRM_FORMAT_RGB888;
>>>>          ctl = phys_enc->hw_ctl;
>>>> +    hw_cdm = phys_enc->hw_cdm;
>>>> +    if (hw_cdm)
>>>> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent,
>>>> &phys_enc->cached_mode);
>>>> +    fmt = dpu_get_dpu_format(fmt_fourcc);
>>>>          DPU_DEBUG_VIDENC(phys_enc, "\n");
>>>>    @@ -422,6 +439,8 @@ static void dpu_encoder_phys_vid_enable(struct
>>>> dpu_encoder_phys *phys_enc)
>>>>          dpu_encoder_helper_split_config(phys_enc,
>>>> phys_enc->hw_intf->idx);
>>>>    +    dpu_encoder_helper_phys_setup_cdm(phys_enc, fmt,
>>>> CDM_CDWN_OUTPUT_HDMI);
>>>
>>> If there is no CDM, why do we need to call this?
>> Inside of dpu_encoder_helper_phys_setup_cdm(), there's a check to see if
>> there is a hw_cdm. If there is not, then it immediately exits the function.
>>>
>>>> +
>>>>        dpu_encoder_phys_vid_setup_timing_engine(phys_enc);
>>>>          /*
>>>> @@ -437,7 +456,15 @@ static void dpu_encoder_phys_vid_enable(struct
>>>> dpu_encoder_phys *phys_enc)
>>>>        if (ctl->ops.update_pending_flush_merge_3d &&
>>>> phys_enc->hw_pp->merge_3d)
>>>>            ctl->ops.update_pending_flush_merge_3d(ctl,
>>>> phys_enc->hw_pp->merge_3d->idx);
>>>>    -    if (ctl->ops.update_pending_flush_periph &&
>>>> phys_enc->hw_intf->cap->type == INTF_DP)
>>>> +    if (ctl->ops.update_pending_flush_cdm && phys_enc->hw_cdm)
>>>> +        ctl->ops.update_pending_flush_cdm(ctl, hw_cdm->idx);
>>>> +
>>>> +    /*
>>>> +     * Peripheral flush must be updated whenever flushing SDP
>>>> packets is needed.
>>>> +     * SDP packets are required for any YUV format (YUV420, YUV422,
>>>> YUV444).
>>>> +     */
>>>> +    if (ctl->ops.update_pending_flush_periph &&
>>>> phys_enc->hw_intf->cap->type == INTF_DP &&
>>>> +        phys_enc->hw_cdm)
>>>>            ctl->ops.update_pending_flush_periph(ctl,
>>>> phys_enc->hw_intf->idx);
>>>
>>> Should there be a flush if we are switching from YUV 420 to RGB mode?
>> We only need to flush for the sdp packet, but for msa we do not need to
>> flush.
> 
> What about having SDP with RGB as colorimetry? In other words, if
> there is a decision point, this one looks incorrect.
> 

There are two ways to do it:

1) Use SDP for both RGB and YUV as that supports both. If we implement 
this policy, then what you are asking for is correct that we will need 
SDP even to switch back to RGB. But to implement this we will also need 
to have some sort of state management in the encoder layer about what is 
the current encoder fmt Vs what is the prev fmt and then trigger 
peripheral flush only during transitions from RGB to YUV and vice-versa

2) Use SDP only for YUV because MSA does not support YUV formats and use 
MSA for RGB

We decided to implement (2) and there is no significant impact of 
switching between MSA and SDPs but state management becomes easier.

>>>
>>> Also, I'd say, we should move update_pending_flush_periph invocation
>>> to this patch.
>> Ack
>>>
>>>>      skip_flush:
>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
>>>> b/drivers/gpu/drm/msm/dp/dp_display.c
>>>> index 6d764f5b08727..4329435518351 100644
>>>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
>>>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
>>>> @@ -1399,6 +1399,18 @@ void __exit msm_dp_unregister(void)
>>>>        platform_driver_unregister(&dp_display_driver);
>>>>    }
>>>>    +bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
>>>> +                   const struct drm_display_mode *mode)
>>>> +{
>>>> +    struct dp_display_private *dp;
>>>> +    const struct drm_display_info *info;
>>>> +
>>>> +    dp = container_of(dp_display, struct dp_display_private,
>>>> dp_display);
>>>> +    info = &dp_display->connector->display_info;
>>>> +
>>>> +    return dp_panel_vsc_sdp_supported(dp->panel) &&
>>>> drm_mode_is_420_only(info, mode);
>>>
>>> YUV 420 modes should be filtered out in mode_valid if VSC SDP is not
>>> supported.
>> Ack. Will change
>>>
>>>> +}
>>>> +
>>>>    bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)
>>>>    {
>>>>        struct dp_display_private *dp;
>>>> diff --git a/drivers/gpu/drm/msm/msm_drv.h
>>>> b/drivers/gpu/drm/msm/msm_drv.h
>>>> index 16a7cbc0b7dd8..b9581bd934e9e 100644
>>>> --- a/drivers/gpu/drm/msm/msm_drv.h
>>>> +++ b/drivers/gpu/drm/msm/msm_drv.h
>>>> @@ -387,7 +387,8 @@ void __exit msm_dp_unregister(void);
>>>>    int msm_dp_modeset_init(struct msm_dp *dp_display, struct
>>>> drm_device *dev,
>>>>                 struct drm_encoder *encoder);
>>>>    void msm_dp_snapshot(struct msm_disp_state *disp_state, struct
>>>> msm_dp *dp_display);
>>>> -
>>>> +bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
>>>> +                   const struct drm_display_mode *mode);
>>>>    bool msm_dp_wide_bus_available(const struct msm_dp *dp_display);
>>>>      #else
>>>> @@ -409,6 +410,12 @@ static inline void msm_dp_snapshot(struct
>>>> msm_disp_state *disp_state, struct msm
>>>>    {
>>>>    }
>>>>    +static inline bool msm_dp_is_yuv_420_enabled(const struct msm_dp
>>>> *dp_display,
>>>> +                         const struct drm_display_mode *mode)
>>>> +{
>>>> +    return false;
>>>> +}
>>>> +
>>>>    static inline bool msm_dp_wide_bus_available(const struct msm_dp
>>>> *dp_display)
>>>>    {
>>>>        return false;
>>>
> 
> 
> 
> --
> With best wishes
> Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 01/17] drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP
  2024-01-27  0:39     ` Paloma Arellano
@ 2024-01-29  3:06       ` Abhinav Kumar
  2024-01-29  3:23         ` Dmitry Baryshkov
  0 siblings, 1 reply; 95+ messages in thread
From: Abhinav Kumar @ 2024-01-29  3:06 UTC (permalink / raw)
  To: Paloma Arellano, Dmitry Baryshkov, freedreno
  Cc: neil.armstrong, linux-arm-msm, dri-devel, swboyd, seanpaul,
	marijn.suijten, quic_jesszhan, quic_khsieh



On 1/26/2024 4:39 PM, Paloma Arellano wrote:
> 
> On 1/25/2024 1:14 PM, Dmitry Baryshkov wrote:
>> On 25/01/2024 21:38, Paloma Arellano wrote:
>>> Generalize dpu_encoder_helper_phys_setup_cdm to be compatible with DP.
>>>
>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>> ---
>>>   .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  4 +--
>>>   .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 31 ++++++++++---------
>>>   2 files changed, 18 insertions(+), 17 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h 
>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>>> index 993f263433314..37ac385727c3b 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>>> @@ -153,6 +153,7 @@ enum dpu_intr_idx {
>>>    * @hw_intf:        Hardware interface to the intf registers
>>>    * @hw_wb:        Hardware interface to the wb registers
>>>    * @hw_cdm:        Hardware interface to the CDM registers
>>> + * @cdm_cfg:    CDM block config needed to store WB/DP block's CDM 
>>> configuration
>>
>> Please realign the description.
> Ack
>>
>>>    * @dpu_kms:        Pointer to the dpu_kms top level
>>>    * @cached_mode:    DRM mode cached at mode_set time, acted on in 
>>> enable
>>>    * @vblank_ctl_lock:    Vblank ctl mutex lock to protect 
>>> vblank_refcount
>>> @@ -183,6 +184,7 @@ struct dpu_encoder_phys {
>>>       struct dpu_hw_intf *hw_intf;
>>>       struct dpu_hw_wb *hw_wb;
>>>       struct dpu_hw_cdm *hw_cdm;
>>> +    struct dpu_hw_cdm_cfg cdm_cfg;
>>
>> It might be slightly better to move it after all the pointers, so 
>> after the dpu_kms.
> Ack
>>
>>>       struct dpu_kms *dpu_kms;
>>>       struct drm_display_mode cached_mode;
>>>       struct mutex vblank_ctl_lock;
>>> @@ -213,7 +215,6 @@ static inline int 
>>> dpu_encoder_phys_inc_pending(struct dpu_encoder_phys *phys)
>>>    * @wbirq_refcount:     Reference count of writeback interrupt
>>>    * @wb_done_timeout_cnt: number of wb done irq timeout errors
>>>    * @wb_cfg:  writeback block config to store fb related details
>>> - * @cdm_cfg: cdm block config needed to store writeback block's CDM 
>>> configuration
>>>    * @wb_conn: backpointer to writeback connector
>>>    * @wb_job: backpointer to current writeback job
>>>    * @dest:   dpu buffer layout for current writeback output buffer
>>> @@ -223,7 +224,6 @@ struct dpu_encoder_phys_wb {
>>>       atomic_t wbirq_refcount;
>>>       int wb_done_timeout_cnt;
>>>       struct dpu_hw_wb_cfg wb_cfg;
>>> -    struct dpu_hw_cdm_cfg cdm_cfg;
>>>       struct drm_writeback_connector *wb_conn;
>>>       struct drm_writeback_job *wb_job;
>>>       struct dpu_hw_fmt_layout dest;
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c 
>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>>> index 4cd2d9e3131a4..072fc6950e496 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>>> @@ -269,28 +269,21 @@ static void 
>>> dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
>>>    *                                     This API does not handle 
>>> DPU_CHROMA_H1V2.
>>>    * @phys_enc:Pointer to physical encoder
>>>    */
>>> -static void dpu_encoder_helper_phys_setup_cdm(struct 
>>> dpu_encoder_phys *phys_enc)
>>> +static void dpu_encoder_helper_phys_setup_cdm(struct 
>>> dpu_encoder_phys *phys_enc,
>>> +                          const struct dpu_format *dpu_fmt,
>>> +                          u32 output_type)
>>>   {
>>>       struct dpu_hw_cdm *hw_cdm;
>>>       struct dpu_hw_cdm_cfg *cdm_cfg;
>>>       struct dpu_hw_pingpong *hw_pp;
>>> -    struct dpu_encoder_phys_wb *wb_enc;
>>> -    const struct msm_format *format;
>>> -    const struct dpu_format *dpu_fmt;
>>> -    struct drm_writeback_job *wb_job;
>>>       int ret;
>>>         if (!phys_enc)
>>>           return;
>>>   -    wb_enc = to_dpu_encoder_phys_wb(phys_enc);
>>> -    cdm_cfg = &wb_enc->cdm_cfg;
>>> +    cdm_cfg = &phys_enc->cdm_cfg;
>>>       hw_pp = phys_enc->hw_pp;
>>>       hw_cdm = phys_enc->hw_cdm;
>>> -    wb_job = wb_enc->wb_job;
>>> -
>>> -    format = msm_framebuffer_format(wb_enc->wb_job->fb);
>>> -    dpu_fmt = dpu_get_dpu_format_ext(format->pixel_format, 
>>> wb_job->fb->modifier);
>>>         if (!hw_cdm)
>>>           return;
>>> @@ -306,10 +299,10 @@ static void 
>>> dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
>>>         memset(cdm_cfg, 0, sizeof(struct dpu_hw_cdm_cfg));
>>>   -    cdm_cfg->output_width = wb_job->fb->width;
>>> -    cdm_cfg->output_height = wb_job->fb->height;
>>> +    cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
>>> +    cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
>>
>> This is a semantic change. Instead of passing the FB size, this passes 
>> the mode dimensions. They are not guaranteed to be the same, 
>> especially for the WB case.
>>

The WB job is storing the output FB of WB. I cannot think of a use-case 
where this cannot match the current mode programmed to the WB encoder.

Yes, if it was the drm_plane's FB, then it cannot be guaranteed as the 
plane can scale the contents but here thats not the case. Here its the 
output FB of WB.

>>>       cdm_cfg->output_fmt = dpu_fmt;
>>> -    cdm_cfg->output_type = CDM_CDWN_OUTPUT_WB;
>>> +    cdm_cfg->output_type = output_type;
>>>       cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
>>>               CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
>>>       cdm_cfg->csc_cfg = &dpu_csc10_rgb2yuv_601l;
>>> @@ -462,6 +455,14 @@ static void dpu_encoder_phys_wb_setup(
>>>       struct dpu_hw_wb *hw_wb = phys_enc->hw_wb;
>>>       struct drm_display_mode mode = phys_enc->cached_mode;
>>>       struct drm_framebuffer *fb = NULL;
>>> +    struct dpu_encoder_phys_wb *wb_enc = 
>>> to_dpu_encoder_phys_wb(phys_enc);
>>> +    struct drm_writeback_job *wb_job;
>>> +    const struct msm_format *format;
>>> +    const struct dpu_format *dpu_fmt;
>>> +
>>> +    wb_job = wb_enc->wb_job;
>>> +    format = msm_framebuffer_format(wb_enc->wb_job->fb);
>>> +    dpu_fmt = dpu_get_dpu_format_ext(format->pixel_format, 
>>> wb_job->fb->modifier);
>>>         DPU_DEBUG("[mode_set:%d, \"%s\",%d,%d]\n",
>>>               hw_wb->idx - WB_0, mode.name,
>>> @@ -475,7 +476,7 @@ static void dpu_encoder_phys_wb_setup(
>>>         dpu_encoder_phys_wb_setup_fb(phys_enc, fb);
>>>   -    dpu_encoder_helper_phys_setup_cdm(phys_enc);
>>> +    dpu_encoder_helper_phys_setup_cdm(phys_enc, dpu_fmt, 
>>> CDM_CDWN_OUTPUT_WB);
>>>         dpu_encoder_phys_wb_setup_ctl(phys_enc);
>>>   }
>>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 17/17] drm/msm/dp: allow YUV420 mode for DP connector when VSC SDP supported
  2024-01-25 22:05   ` Dmitry Baryshkov
@ 2024-01-29  3:17     ` Abhinav Kumar
  2024-01-29  3:52       ` Dmitry Baryshkov
  0 siblings, 1 reply; 95+ messages in thread
From: Abhinav Kumar @ 2024-01-29  3:17 UTC (permalink / raw)
  To: Dmitry Baryshkov, Paloma Arellano, freedreno
  Cc: neil.armstrong, linux-arm-msm, dri-devel, swboyd, seanpaul,
	marijn.suijten, quic_jesszhan, quic_khsieh



On 1/25/2024 2:05 PM, Dmitry Baryshkov wrote:
> On 25/01/2024 21:38, Paloma Arellano wrote:
>> All the components of YUV420 over DP are added. Therefore, let's mark the
>> connector property as true for DP connector when the DP type is not eDP
>> and when VSC SDP is supported.
>>
>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/dp/dp_display.c | 5 ++++-
>>   1 file changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
>> b/drivers/gpu/drm/msm/dp/dp_display.c
>> index 4329435518351..97edd607400b8 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
>> @@ -370,11 +370,14 @@ static int dp_display_process_hpd_high(struct 
>> dp_display_private *dp)
>>       dp_link_process_request(dp->link);
>> -    if (!dp->dp_display.is_edp)
>> +    if (!dp->dp_display.is_edp) {
>> +        if (dp_panel_vsc_sdp_supported(dp->panel))
>> +            dp->dp_display.connector->ycbcr_420_allowed = true;
> 
> Please consider fixing a TODO in drm_bridge_connector_init().
> 

I am not totally clear if that TODO can ever go for DP/HDMI usage of 
drm_bridge_connector.

We do not know if the sink supports VSC SDP till we read the DPCD and 
till we know that sink supports VSC SDP, there is no reason to mark the 
YUV modes as supported. This is the same logic followed across vendors.

drm_bride_connector_init() happens much earlier than the point where we 
read DPCD. The only thing which can be done is perhaps add some callback 
to update_ycbcr_420_allowed once DPCD is read. But I don't think its 
absolutely necessary to have a callback just for this.

>>           drm_dp_set_subconnector_property(dp->dp_display.connector,
>>                            connector_status_connected,
>>                            dp->panel->dpcd,
>>                            dp->panel->downstream_ports);
>> +    }
>>       edid = dp->panel->edid;
> 

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 01/17] drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP
  2024-01-29  3:06       ` Abhinav Kumar
@ 2024-01-29  3:23         ` Dmitry Baryshkov
  2024-01-29  4:00           ` Abhinav Kumar
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-29  3:23 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno

On Mon, 29 Jan 2024 at 05:06, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 1/26/2024 4:39 PM, Paloma Arellano wrote:
> >
> > On 1/25/2024 1:14 PM, Dmitry Baryshkov wrote:
> >> On 25/01/2024 21:38, Paloma Arellano wrote:
> >>> Generalize dpu_encoder_helper_phys_setup_cdm to be compatible with DP.
> >>>
> >>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >>> ---
> >>>   .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  4 +--
> >>>   .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 31 ++++++++++---------
> >>>   2 files changed, 18 insertions(+), 17 deletions(-)
> >>>
> >>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >>> index 993f263433314..37ac385727c3b 100644
> >>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >>> @@ -153,6 +153,7 @@ enum dpu_intr_idx {
> >>>    * @hw_intf:        Hardware interface to the intf registers
> >>>    * @hw_wb:        Hardware interface to the wb registers
> >>>    * @hw_cdm:        Hardware interface to the CDM registers
> >>> + * @cdm_cfg:    CDM block config needed to store WB/DP block's CDM
> >>> configuration
> >>
> >> Please realign the description.
> > Ack
> >>
> >>>    * @dpu_kms:        Pointer to the dpu_kms top level
> >>>    * @cached_mode:    DRM mode cached at mode_set time, acted on in
> >>> enable
> >>>    * @vblank_ctl_lock:    Vblank ctl mutex lock to protect
> >>> vblank_refcount
> >>> @@ -183,6 +184,7 @@ struct dpu_encoder_phys {
> >>>       struct dpu_hw_intf *hw_intf;
> >>>       struct dpu_hw_wb *hw_wb;
> >>>       struct dpu_hw_cdm *hw_cdm;
> >>> +    struct dpu_hw_cdm_cfg cdm_cfg;
> >>
> >> It might be slightly better to move it after all the pointers, so
> >> after the dpu_kms.
> > Ack
> >>
> >>>       struct dpu_kms *dpu_kms;
> >>>       struct drm_display_mode cached_mode;
> >>>       struct mutex vblank_ctl_lock;
> >>> @@ -213,7 +215,6 @@ static inline int
> >>> dpu_encoder_phys_inc_pending(struct dpu_encoder_phys *phys)
> >>>    * @wbirq_refcount:     Reference count of writeback interrupt
> >>>    * @wb_done_timeout_cnt: number of wb done irq timeout errors
> >>>    * @wb_cfg:  writeback block config to store fb related details
> >>> - * @cdm_cfg: cdm block config needed to store writeback block's CDM
> >>> configuration
> >>>    * @wb_conn: backpointer to writeback connector
> >>>    * @wb_job: backpointer to current writeback job
> >>>    * @dest:   dpu buffer layout for current writeback output buffer
> >>> @@ -223,7 +224,6 @@ struct dpu_encoder_phys_wb {
> >>>       atomic_t wbirq_refcount;
> >>>       int wb_done_timeout_cnt;
> >>>       struct dpu_hw_wb_cfg wb_cfg;
> >>> -    struct dpu_hw_cdm_cfg cdm_cfg;
> >>>       struct drm_writeback_connector *wb_conn;
> >>>       struct drm_writeback_job *wb_job;
> >>>       struct dpu_hw_fmt_layout dest;
> >>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> >>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> >>> index 4cd2d9e3131a4..072fc6950e496 100644
> >>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> >>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> >>> @@ -269,28 +269,21 @@ static void
> >>> dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
> >>>    *                                     This API does not handle
> >>> DPU_CHROMA_H1V2.
> >>>    * @phys_enc:Pointer to physical encoder
> >>>    */
> >>> -static void dpu_encoder_helper_phys_setup_cdm(struct
> >>> dpu_encoder_phys *phys_enc)
> >>> +static void dpu_encoder_helper_phys_setup_cdm(struct
> >>> dpu_encoder_phys *phys_enc,
> >>> +                          const struct dpu_format *dpu_fmt,
> >>> +                          u32 output_type)
> >>>   {
> >>>       struct dpu_hw_cdm *hw_cdm;
> >>>       struct dpu_hw_cdm_cfg *cdm_cfg;
> >>>       struct dpu_hw_pingpong *hw_pp;
> >>> -    struct dpu_encoder_phys_wb *wb_enc;
> >>> -    const struct msm_format *format;
> >>> -    const struct dpu_format *dpu_fmt;
> >>> -    struct drm_writeback_job *wb_job;
> >>>       int ret;
> >>>         if (!phys_enc)
> >>>           return;
> >>>   -    wb_enc = to_dpu_encoder_phys_wb(phys_enc);
> >>> -    cdm_cfg = &wb_enc->cdm_cfg;
> >>> +    cdm_cfg = &phys_enc->cdm_cfg;
> >>>       hw_pp = phys_enc->hw_pp;
> >>>       hw_cdm = phys_enc->hw_cdm;
> >>> -    wb_job = wb_enc->wb_job;
> >>> -
> >>> -    format = msm_framebuffer_format(wb_enc->wb_job->fb);
> >>> -    dpu_fmt = dpu_get_dpu_format_ext(format->pixel_format,
> >>> wb_job->fb->modifier);
> >>>         if (!hw_cdm)
> >>>           return;
> >>> @@ -306,10 +299,10 @@ static void
> >>> dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
> >>>         memset(cdm_cfg, 0, sizeof(struct dpu_hw_cdm_cfg));
> >>>   -    cdm_cfg->output_width = wb_job->fb->width;
> >>> -    cdm_cfg->output_height = wb_job->fb->height;
> >>> +    cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
> >>> +    cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
> >>
> >> This is a semantic change. Instead of passing the FB size, this passes
> >> the mode dimensions. They are not guaranteed to be the same,
> >> especially for the WB case.
> >>
>
> The WB job is storing the output FB of WB. I cannot think of a use-case
> where this cannot match the current mode programmed to the WB encoder.
>
> Yes, if it was the drm_plane's FB, then it cannot be guaranteed as the
> plane can scale the contents but here thats not the case. Here its the
> output FB of WB.

Is it a part of WB uAPI, to have the FB dimensions equal to mode
dimensions? Or is it just our current limitation? I can easily imagine
WB outputting data to a part of the FB (just like we can clip FB using
plane's clip rectangle).

This boils down to a question, whether CDM should be setup in terms of
actual output date or the physical memory buffer parameters. I suspect
the former is the case (which makes this change correct). But it
either should be described in the commit message or (even better)
split to a separate commit.


-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 14/17] drm/msm/dpu: modify encoder programming for CDM over DP
  2024-01-29  2:58         ` Abhinav Kumar
@ 2024-01-29  3:42           ` Dmitry Baryshkov
  2024-01-29  5:03             ` Abhinav Kumar
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-29  3:42 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno

On Mon, 29 Jan 2024 at 04:58, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 1/27/2024 9:55 PM, Dmitry Baryshkov wrote:
> > On Sun, 28 Jan 2024 at 07:48, Paloma Arellano <quic_parellan@quicinc.com> wrote:
> >>
> >>
> >> On 1/25/2024 1:57 PM, Dmitry Baryshkov wrote:
> >>> On 25/01/2024 21:38, Paloma Arellano wrote:
> >>>> Adjust the encoder format programming in the case of video mode for DP
> >>>> to accommodate CDM related changes.
> >>>>
> >>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >>>> ---
> >>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 16 +++++++++
> >>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |  8 +++++
> >>>>    .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 35 ++++++++++++++++---
> >>>>    drivers/gpu/drm/msm/dp/dp_display.c           | 12 +++++++
> >>>>    drivers/gpu/drm/msm/msm_drv.h                 |  9 ++++-
> >>>>    5 files changed, 75 insertions(+), 5 deletions(-)
> >>>>
> >>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >>>> index b0896814c1562..99ec53446ad21 100644
> >>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >>>> @@ -222,6 +222,22 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = {
> >>>>        15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10
> >>>>    };
> >>>>    +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
> >>>> const struct drm_display_mode *mode)
> >>>> +{
> >>>> +    const struct dpu_encoder_virt *dpu_enc;
> >>>> +    const struct msm_display_info *disp_info;
> >>>> +    struct msm_drm_private *priv;
> >>>> +
> >>>> +    dpu_enc = to_dpu_encoder_virt(drm_enc);
> >>>> +    disp_info = &dpu_enc->disp_info;
> >>>> +    priv = drm_enc->dev->dev_private;
> >>>> +
> >>>> +    if (disp_info->intf_type == INTF_DP &&
> >>>> + msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]],
> >>>> mode))
> >>>
> >>> This should not require interacting with DP. If we got here, we must
> >>> be sure that 4:2:0 is supported and can be configured.
> >> Ack. Will drop this function and only check for if the mode is YUV420.
> >>>
> >>>> +        return DRM_FORMAT_YUV420;
> >>>> +
> >>>> +    return DRM_FORMAT_RGB888;
> >>>> +}
> >>>>      bool dpu_encoder_is_widebus_enabled(const struct drm_encoder
> >>>> *drm_enc)
> >>>>    {
> >>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> >>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> >>>> index 7b4afa71f1f96..62255d0aa4487 100644
> >>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> >>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> >>>> @@ -162,6 +162,14 @@ int dpu_encoder_get_vsync_count(struct
> >>>> drm_encoder *drm_enc);
> >>>>     */
> >>>>    bool dpu_encoder_is_widebus_enabled(const struct drm_encoder
> >>>> *drm_enc);
> >>>>    +/**
> >>>> + * dpu_encoder_get_drm_fmt - return DRM fourcc format
> >>>> + * @drm_enc:    Pointer to previously created drm encoder structure
> >>>> + * @mode:    Corresponding drm_display_mode for dpu encoder
> >>>> + */
> >>>> +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
> >>>> +                const struct drm_display_mode *mode);
> >>>> +
> >>>>    /**
> >>>>     * dpu_encoder_get_crc_values_cnt - get number of physical encoders
> >>>> contained
> >>>>     *    in virtual encoder that can collect CRC values
> >>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >>>> index e284bf448bdda..a1dde0ff35dc8 100644
> >>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >>>> @@ -234,6 +234,7 @@ static void
> >>>> dpu_encoder_phys_vid_setup_timing_engine(
> >>>>    {
> >>>>        struct drm_display_mode mode;
> >>>>        struct dpu_hw_intf_timing_params timing_params = { 0 };
> >>>> +    struct dpu_hw_cdm *hw_cdm;
> >>>>        const struct dpu_format *fmt = NULL;
> >>>>        u32 fmt_fourcc = DRM_FORMAT_RGB888;
> >>>>        unsigned long lock_flags;
> >>>> @@ -254,17 +255,26 @@ static void
> >>>> dpu_encoder_phys_vid_setup_timing_engine(
> >>>>        DPU_DEBUG_VIDENC(phys_enc, "enabling mode:\n");
> >>>>        drm_mode_debug_printmodeline(&mode);
> >>>>    -    if (phys_enc->split_role != ENC_ROLE_SOLO) {
> >>>> +    hw_cdm = phys_enc->hw_cdm;
> >>>> +    if (hw_cdm) {
> >>>> +        intf_cfg.cdm = hw_cdm->idx;
> >>>> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent, &mode);
> >>>> +    }
> >>>> +
> >>>> +    if (phys_enc->split_role != ENC_ROLE_SOLO ||
> >>>> +        dpu_encoder_get_drm_fmt(phys_enc->parent, &mode) ==
> >>>> DRM_FORMAT_YUV420) {
> >>>>            mode.hdisplay >>= 1;
> >>>>            mode.htotal >>= 1;
> >>>>            mode.hsync_start >>= 1;
> >>>>            mode.hsync_end >>= 1;
> >>>> +        mode.hskew >>= 1;
> >>>
> >>> Separate patch.
> >> Ack.
> >>>
> >>>>              DPU_DEBUG_VIDENC(phys_enc,
> >>>> -            "split_role %d, halve horizontal %d %d %d %d\n",
> >>>> +            "split_role %d, halve horizontal %d %d %d %d %d\n",
> >>>>                phys_enc->split_role,
> >>>>                mode.hdisplay, mode.htotal,
> >>>> -            mode.hsync_start, mode.hsync_end);
> >>>> +            mode.hsync_start, mode.hsync_end,
> >>>> +            mode.hskew);
> >>>>        }
> >>>>          drm_mode_to_intf_timing_params(phys_enc, &mode, &timing_params);
> >>>> @@ -412,8 +422,15 @@ static int dpu_encoder_phys_vid_control_vblank_irq(
> >>>>    static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys
> >>>> *phys_enc)
> >>>>    {
> >>>>        struct dpu_hw_ctl *ctl;
> >>>> +    struct dpu_hw_cdm *hw_cdm;
> >>>> +    const struct dpu_format *fmt = NULL;
> >>>> +    u32 fmt_fourcc = DRM_FORMAT_RGB888;
> >>>>          ctl = phys_enc->hw_ctl;
> >>>> +    hw_cdm = phys_enc->hw_cdm;
> >>>> +    if (hw_cdm)
> >>>> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent,
> >>>> &phys_enc->cached_mode);
> >>>> +    fmt = dpu_get_dpu_format(fmt_fourcc);
> >>>>          DPU_DEBUG_VIDENC(phys_enc, "\n");
> >>>>    @@ -422,6 +439,8 @@ static void dpu_encoder_phys_vid_enable(struct
> >>>> dpu_encoder_phys *phys_enc)
> >>>>          dpu_encoder_helper_split_config(phys_enc,
> >>>> phys_enc->hw_intf->idx);
> >>>>    +    dpu_encoder_helper_phys_setup_cdm(phys_enc, fmt,
> >>>> CDM_CDWN_OUTPUT_HDMI);
> >>>
> >>> If there is no CDM, why do we need to call this?
> >> Inside of dpu_encoder_helper_phys_setup_cdm(), there's a check to see if
> >> there is a hw_cdm. If there is not, then it immediately exits the function.
> >>>
> >>>> +
> >>>>        dpu_encoder_phys_vid_setup_timing_engine(phys_enc);
> >>>>          /*
> >>>> @@ -437,7 +456,15 @@ static void dpu_encoder_phys_vid_enable(struct
> >>>> dpu_encoder_phys *phys_enc)
> >>>>        if (ctl->ops.update_pending_flush_merge_3d &&
> >>>> phys_enc->hw_pp->merge_3d)
> >>>>            ctl->ops.update_pending_flush_merge_3d(ctl,
> >>>> phys_enc->hw_pp->merge_3d->idx);
> >>>>    -    if (ctl->ops.update_pending_flush_periph &&
> >>>> phys_enc->hw_intf->cap->type == INTF_DP)
> >>>> +    if (ctl->ops.update_pending_flush_cdm && phys_enc->hw_cdm)
> >>>> +        ctl->ops.update_pending_flush_cdm(ctl, hw_cdm->idx);
> >>>> +
> >>>> +    /*
> >>>> +     * Peripheral flush must be updated whenever flushing SDP
> >>>> packets is needed.
> >>>> +     * SDP packets are required for any YUV format (YUV420, YUV422,
> >>>> YUV444).
> >>>> +     */
> >>>> +    if (ctl->ops.update_pending_flush_periph &&
> >>>> phys_enc->hw_intf->cap->type == INTF_DP &&
> >>>> +        phys_enc->hw_cdm)
> >>>>            ctl->ops.update_pending_flush_periph(ctl,
> >>>> phys_enc->hw_intf->idx);
> >>>
> >>> Should there be a flush if we are switching from YUV 420 to RGB mode?
> >> We only need to flush for the sdp packet, but for msa we do not need to
> >> flush.
> >
> > What about having SDP with RGB as colorimetry? In other words, if
> > there is a decision point, this one looks incorrect.
> >
>
> There are two ways to do it:
>
> 1) Use SDP for both RGB and YUV as that supports both. If we implement
> this policy, then what you are asking for is correct that we will need
> SDP even to switch back to RGB. But to implement this we will also need
> to have some sort of state management in the encoder layer about what is
> the current encoder fmt Vs what is the prev fmt and then trigger
> peripheral flush only during transitions from RGB to YUV and vice-versa
>
> 2) Use SDP only for YUV because MSA does not support YUV formats and use
> MSA for RGB
>
> We decided to implement (2) and there is no significant impact of
> switching between MSA and SDPs but state management becomes easier.

Yes. However as you wrote, there might be other usecases concerning
SDP. Having this in mind, it sounds like the driver should decide
whether to flush peripheral at a different place (when the SDP
infoframe is being updated?). And the dpu_encoder_phys_vid_enable()
should use this previous decision. Maybe this should be a part of
msm_dp_ API, something like msm_dp_needs_peripheral_flush()?

>
> >>>
> >>> Also, I'd say, we should move update_pending_flush_periph invocation
> >>> to this patch.
> >> Ack
> >>>
> >>>>      skip_flush:
> >>>> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
> >>>> b/drivers/gpu/drm/msm/dp/dp_display.c
> >>>> index 6d764f5b08727..4329435518351 100644
> >>>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> >>>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> >>>> @@ -1399,6 +1399,18 @@ void __exit msm_dp_unregister(void)
> >>>>        platform_driver_unregister(&dp_display_driver);
> >>>>    }
> >>>>    +bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
> >>>> +                   const struct drm_display_mode *mode)
> >>>> +{
> >>>> +    struct dp_display_private *dp;
> >>>> +    const struct drm_display_info *info;
> >>>> +
> >>>> +    dp = container_of(dp_display, struct dp_display_private,
> >>>> dp_display);
> >>>> +    info = &dp_display->connector->display_info;
> >>>> +
> >>>> +    return dp_panel_vsc_sdp_supported(dp->panel) &&
> >>>> drm_mode_is_420_only(info, mode);
> >>>
> >>> YUV 420 modes should be filtered out in mode_valid if VSC SDP is not
> >>> supported.
> >> Ack. Will change
> >>>
> >>>> +}
> >>>> +
> >>>>    bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)
> >>>>    {
> >>>>        struct dp_display_private *dp;
> >>>> diff --git a/drivers/gpu/drm/msm/msm_drv.h
> >>>> b/drivers/gpu/drm/msm/msm_drv.h
> >>>> index 16a7cbc0b7dd8..b9581bd934e9e 100644
> >>>> --- a/drivers/gpu/drm/msm/msm_drv.h
> >>>> +++ b/drivers/gpu/drm/msm/msm_drv.h
> >>>> @@ -387,7 +387,8 @@ void __exit msm_dp_unregister(void);
> >>>>    int msm_dp_modeset_init(struct msm_dp *dp_display, struct
> >>>> drm_device *dev,
> >>>>                 struct drm_encoder *encoder);
> >>>>    void msm_dp_snapshot(struct msm_disp_state *disp_state, struct
> >>>> msm_dp *dp_display);
> >>>> -
> >>>> +bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
> >>>> +                   const struct drm_display_mode *mode);
> >>>>    bool msm_dp_wide_bus_available(const struct msm_dp *dp_display);
> >>>>      #else
> >>>> @@ -409,6 +410,12 @@ static inline void msm_dp_snapshot(struct
> >>>> msm_disp_state *disp_state, struct msm
> >>>>    {
> >>>>    }
> >>>>    +static inline bool msm_dp_is_yuv_420_enabled(const struct msm_dp
> >>>> *dp_display,
> >>>> +                         const struct drm_display_mode *mode)
> >>>> +{
> >>>> +    return false;
> >>>> +}
> >>>> +
> >>>>    static inline bool msm_dp_wide_bus_available(const struct msm_dp
> >>>> *dp_display)
> >>>>    {
> >>>>        return false;
> >>>
> >
> >
> >
> > --
> > With best wishes
> > Dmitry



-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 17/17] drm/msm/dp: allow YUV420 mode for DP connector when VSC SDP supported
  2024-01-29  3:17     ` Abhinav Kumar
@ 2024-01-29  3:52       ` Dmitry Baryshkov
  2024-01-29  4:30         ` Abhinav Kumar
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-29  3:52 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno

On Mon, 29 Jan 2024 at 05:17, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 1/25/2024 2:05 PM, Dmitry Baryshkov wrote:
> > On 25/01/2024 21:38, Paloma Arellano wrote:
> >> All the components of YUV420 over DP are added. Therefore, let's mark the
> >> connector property as true for DP connector when the DP type is not eDP
> >> and when VSC SDP is supported.
> >>
> >> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >> ---
> >>   drivers/gpu/drm/msm/dp/dp_display.c | 5 ++++-
> >>   1 file changed, 4 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
> >> b/drivers/gpu/drm/msm/dp/dp_display.c
> >> index 4329435518351..97edd607400b8 100644
> >> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> >> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> >> @@ -370,11 +370,14 @@ static int dp_display_process_hpd_high(struct
> >> dp_display_private *dp)
> >>       dp_link_process_request(dp->link);
> >> -    if (!dp->dp_display.is_edp)
> >> +    if (!dp->dp_display.is_edp) {
> >> +        if (dp_panel_vsc_sdp_supported(dp->panel))
> >> +            dp->dp_display.connector->ycbcr_420_allowed = true;
> >
> > Please consider fixing a TODO in drm_bridge_connector_init().
> >
>
> I am not totally clear if that TODO can ever go for DP/HDMI usage of
> drm_bridge_connector.
>
> We do not know if the sink supports VSC SDP till we read the DPCD and
> till we know that sink supports VSC SDP, there is no reason to mark the
> YUV modes as supported. This is the same logic followed across vendors.
>
> drm_bride_connector_init() happens much earlier than the point where we
> read DPCD. The only thing which can be done is perhaps add some callback
> to update_ycbcr_420_allowed once DPCD is read. But I don't think its
> absolutely necessary to have a callback just for this.

After checking the drm_connector docs, I'd still hold my opinion and
consider this patch to be a misuse of the property. If you check the
drm_connector::ycbcr_420_allowed docs, you'll see that it describes
the output from the source point of view. In other words, it should be
true if the DP connector can send YUV420 rather than being set if the
attached display supports such output. This matches ycbcr420_allowed
usage by AMD, dw-hdmi, intel_hdmi and even intel_dp usage.

> >>           drm_dp_set_subconnector_property(dp->dp_display.connector,
> >>                            connector_status_connected,
> >>                            dp->panel->dpcd,
> >>                            dp->panel->downstream_ports);
> >> +    }
> >>       edid = dp->panel->edid;
> >



-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 01/17] drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP
  2024-01-29  3:23         ` Dmitry Baryshkov
@ 2024-01-29  4:00           ` Abhinav Kumar
  2024-01-29  4:12             ` Dmitry Baryshkov
  0 siblings, 1 reply; 95+ messages in thread
From: Abhinav Kumar @ 2024-01-29  4:00 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno



On 1/28/2024 7:23 PM, Dmitry Baryshkov wrote:
> On Mon, 29 Jan 2024 at 05:06, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 1/26/2024 4:39 PM, Paloma Arellano wrote:
>>>
>>> On 1/25/2024 1:14 PM, Dmitry Baryshkov wrote:
>>>> On 25/01/2024 21:38, Paloma Arellano wrote:
>>>>> Generalize dpu_encoder_helper_phys_setup_cdm to be compatible with DP.
>>>>>
>>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>>>> ---
>>>>>    .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  4 +--
>>>>>    .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 31 ++++++++++---------
>>>>>    2 files changed, 18 insertions(+), 17 deletions(-)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>>>>> index 993f263433314..37ac385727c3b 100644
>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>>>>> @@ -153,6 +153,7 @@ enum dpu_intr_idx {
>>>>>     * @hw_intf:        Hardware interface to the intf registers
>>>>>     * @hw_wb:        Hardware interface to the wb registers
>>>>>     * @hw_cdm:        Hardware interface to the CDM registers
>>>>> + * @cdm_cfg:    CDM block config needed to store WB/DP block's CDM
>>>>> configuration
>>>>
>>>> Please realign the description.
>>> Ack
>>>>
>>>>>     * @dpu_kms:        Pointer to the dpu_kms top level
>>>>>     * @cached_mode:    DRM mode cached at mode_set time, acted on in
>>>>> enable
>>>>>     * @vblank_ctl_lock:    Vblank ctl mutex lock to protect
>>>>> vblank_refcount
>>>>> @@ -183,6 +184,7 @@ struct dpu_encoder_phys {
>>>>>        struct dpu_hw_intf *hw_intf;
>>>>>        struct dpu_hw_wb *hw_wb;
>>>>>        struct dpu_hw_cdm *hw_cdm;
>>>>> +    struct dpu_hw_cdm_cfg cdm_cfg;
>>>>
>>>> It might be slightly better to move it after all the pointers, so
>>>> after the dpu_kms.
>>> Ack
>>>>
>>>>>        struct dpu_kms *dpu_kms;
>>>>>        struct drm_display_mode cached_mode;
>>>>>        struct mutex vblank_ctl_lock;
>>>>> @@ -213,7 +215,6 @@ static inline int
>>>>> dpu_encoder_phys_inc_pending(struct dpu_encoder_phys *phys)
>>>>>     * @wbirq_refcount:     Reference count of writeback interrupt
>>>>>     * @wb_done_timeout_cnt: number of wb done irq timeout errors
>>>>>     * @wb_cfg:  writeback block config to store fb related details
>>>>> - * @cdm_cfg: cdm block config needed to store writeback block's CDM
>>>>> configuration
>>>>>     * @wb_conn: backpointer to writeback connector
>>>>>     * @wb_job: backpointer to current writeback job
>>>>>     * @dest:   dpu buffer layout for current writeback output buffer
>>>>> @@ -223,7 +224,6 @@ struct dpu_encoder_phys_wb {
>>>>>        atomic_t wbirq_refcount;
>>>>>        int wb_done_timeout_cnt;
>>>>>        struct dpu_hw_wb_cfg wb_cfg;
>>>>> -    struct dpu_hw_cdm_cfg cdm_cfg;
>>>>>        struct drm_writeback_connector *wb_conn;
>>>>>        struct drm_writeback_job *wb_job;
>>>>>        struct dpu_hw_fmt_layout dest;
>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>>>>> index 4cd2d9e3131a4..072fc6950e496 100644
>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>>>>> @@ -269,28 +269,21 @@ static void
>>>>> dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
>>>>>     *                                     This API does not handle
>>>>> DPU_CHROMA_H1V2.
>>>>>     * @phys_enc:Pointer to physical encoder
>>>>>     */
>>>>> -static void dpu_encoder_helper_phys_setup_cdm(struct
>>>>> dpu_encoder_phys *phys_enc)
>>>>> +static void dpu_encoder_helper_phys_setup_cdm(struct
>>>>> dpu_encoder_phys *phys_enc,
>>>>> +                          const struct dpu_format *dpu_fmt,
>>>>> +                          u32 output_type)
>>>>>    {
>>>>>        struct dpu_hw_cdm *hw_cdm;
>>>>>        struct dpu_hw_cdm_cfg *cdm_cfg;
>>>>>        struct dpu_hw_pingpong *hw_pp;
>>>>> -    struct dpu_encoder_phys_wb *wb_enc;
>>>>> -    const struct msm_format *format;
>>>>> -    const struct dpu_format *dpu_fmt;
>>>>> -    struct drm_writeback_job *wb_job;
>>>>>        int ret;
>>>>>          if (!phys_enc)
>>>>>            return;
>>>>>    -    wb_enc = to_dpu_encoder_phys_wb(phys_enc);
>>>>> -    cdm_cfg = &wb_enc->cdm_cfg;
>>>>> +    cdm_cfg = &phys_enc->cdm_cfg;
>>>>>        hw_pp = phys_enc->hw_pp;
>>>>>        hw_cdm = phys_enc->hw_cdm;
>>>>> -    wb_job = wb_enc->wb_job;
>>>>> -
>>>>> -    format = msm_framebuffer_format(wb_enc->wb_job->fb);
>>>>> -    dpu_fmt = dpu_get_dpu_format_ext(format->pixel_format,
>>>>> wb_job->fb->modifier);
>>>>>          if (!hw_cdm)
>>>>>            return;
>>>>> @@ -306,10 +299,10 @@ static void
>>>>> dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
>>>>>          memset(cdm_cfg, 0, sizeof(struct dpu_hw_cdm_cfg));
>>>>>    -    cdm_cfg->output_width = wb_job->fb->width;
>>>>> -    cdm_cfg->output_height = wb_job->fb->height;
>>>>> +    cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
>>>>> +    cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
>>>>
>>>> This is a semantic change. Instead of passing the FB size, this passes
>>>> the mode dimensions. They are not guaranteed to be the same,
>>>> especially for the WB case.
>>>>
>>
>> The WB job is storing the output FB of WB. I cannot think of a use-case
>> where this cannot match the current mode programmed to the WB encoder.
>>
>> Yes, if it was the drm_plane's FB, then it cannot be guaranteed as the
>> plane can scale the contents but here thats not the case. Here its the
>> output FB of WB.
> 
> Is it a part of WB uAPI, to have the FB dimensions equal to mode
> dimensions? Or is it just our current limitation? I can easily imagine
> WB outputting data to a part of the FB (just like we can clip FB using
> plane's clip rectangle).
> 
> This boils down to a question, whether CDM should be setup in terms of
> actual output date or the physical memory buffer parameters. I suspect
> the former is the case (which makes this change correct). But it
> either should be described in the commit message or (even better)
> split to a separate commit.
> 

I would say its a combination of both today.

The way I would look at it is even if WB crops a certain section of FB, 
that will not change the FB size. FB size of WB should match the rest of 
the DRM pipeline (the mode programmed to the CRTC/encoder). If WB 
decides to write to only a small section of FB (cropping), then we need 
another WB property like CROP_ROI so that we can program the WB to only 
write to a small section of the programmed FB. So in some sense, there 
is no such support in DRM UAPI today. Hence the FB of WB is the full 
mode of the WB.

CDM is before WB so follows the rest of the pipeline that is whatever 
the data feeding it was programmed to.

> 

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 01/17] drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP
  2024-01-29  4:00           ` Abhinav Kumar
@ 2024-01-29  4:12             ` Dmitry Baryshkov
  2024-01-29  4:33               ` Abhinav Kumar
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-29  4:12 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno

On Mon, 29 Jan 2024 at 06:01, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 1/28/2024 7:23 PM, Dmitry Baryshkov wrote:
> > On Mon, 29 Jan 2024 at 05:06, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >>
> >>
> >> On 1/26/2024 4:39 PM, Paloma Arellano wrote:
> >>>
> >>> On 1/25/2024 1:14 PM, Dmitry Baryshkov wrote:
> >>>> On 25/01/2024 21:38, Paloma Arellano wrote:
> >>>>> Generalize dpu_encoder_helper_phys_setup_cdm to be compatible with DP.
> >>>>>
> >>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >>>>> ---
> >>>>>    .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  4 +--
> >>>>>    .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 31 ++++++++++---------
> >>>>>    2 files changed, 18 insertions(+), 17 deletions(-)
> >>>>>
> >>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >>>>> index 993f263433314..37ac385727c3b 100644
> >>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >>>>> @@ -153,6 +153,7 @@ enum dpu_intr_idx {
> >>>>>     * @hw_intf:        Hardware interface to the intf registers
> >>>>>     * @hw_wb:        Hardware interface to the wb registers
> >>>>>     * @hw_cdm:        Hardware interface to the CDM registers
> >>>>> + * @cdm_cfg:    CDM block config needed to store WB/DP block's CDM
> >>>>> configuration
> >>>>
> >>>> Please realign the description.
> >>> Ack
> >>>>
> >>>>>     * @dpu_kms:        Pointer to the dpu_kms top level
> >>>>>     * @cached_mode:    DRM mode cached at mode_set time, acted on in
> >>>>> enable
> >>>>>     * @vblank_ctl_lock:    Vblank ctl mutex lock to protect
> >>>>> vblank_refcount
> >>>>> @@ -183,6 +184,7 @@ struct dpu_encoder_phys {
> >>>>>        struct dpu_hw_intf *hw_intf;
> >>>>>        struct dpu_hw_wb *hw_wb;
> >>>>>        struct dpu_hw_cdm *hw_cdm;
> >>>>> +    struct dpu_hw_cdm_cfg cdm_cfg;
> >>>>
> >>>> It might be slightly better to move it after all the pointers, so
> >>>> after the dpu_kms.
> >>> Ack
> >>>>
> >>>>>        struct dpu_kms *dpu_kms;
> >>>>>        struct drm_display_mode cached_mode;
> >>>>>        struct mutex vblank_ctl_lock;
> >>>>> @@ -213,7 +215,6 @@ static inline int
> >>>>> dpu_encoder_phys_inc_pending(struct dpu_encoder_phys *phys)
> >>>>>     * @wbirq_refcount:     Reference count of writeback interrupt
> >>>>>     * @wb_done_timeout_cnt: number of wb done irq timeout errors
> >>>>>     * @wb_cfg:  writeback block config to store fb related details
> >>>>> - * @cdm_cfg: cdm block config needed to store writeback block's CDM
> >>>>> configuration
> >>>>>     * @wb_conn: backpointer to writeback connector
> >>>>>     * @wb_job: backpointer to current writeback job
> >>>>>     * @dest:   dpu buffer layout for current writeback output buffer
> >>>>> @@ -223,7 +224,6 @@ struct dpu_encoder_phys_wb {
> >>>>>        atomic_t wbirq_refcount;
> >>>>>        int wb_done_timeout_cnt;
> >>>>>        struct dpu_hw_wb_cfg wb_cfg;
> >>>>> -    struct dpu_hw_cdm_cfg cdm_cfg;
> >>>>>        struct drm_writeback_connector *wb_conn;
> >>>>>        struct drm_writeback_job *wb_job;
> >>>>>        struct dpu_hw_fmt_layout dest;
> >>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> >>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> >>>>> index 4cd2d9e3131a4..072fc6950e496 100644
> >>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> >>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> >>>>> @@ -269,28 +269,21 @@ static void
> >>>>> dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
> >>>>>     *                                     This API does not handle
> >>>>> DPU_CHROMA_H1V2.
> >>>>>     * @phys_enc:Pointer to physical encoder
> >>>>>     */
> >>>>> -static void dpu_encoder_helper_phys_setup_cdm(struct
> >>>>> dpu_encoder_phys *phys_enc)
> >>>>> +static void dpu_encoder_helper_phys_setup_cdm(struct
> >>>>> dpu_encoder_phys *phys_enc,
> >>>>> +                          const struct dpu_format *dpu_fmt,
> >>>>> +                          u32 output_type)
> >>>>>    {
> >>>>>        struct dpu_hw_cdm *hw_cdm;
> >>>>>        struct dpu_hw_cdm_cfg *cdm_cfg;
> >>>>>        struct dpu_hw_pingpong *hw_pp;
> >>>>> -    struct dpu_encoder_phys_wb *wb_enc;
> >>>>> -    const struct msm_format *format;
> >>>>> -    const struct dpu_format *dpu_fmt;
> >>>>> -    struct drm_writeback_job *wb_job;
> >>>>>        int ret;
> >>>>>          if (!phys_enc)
> >>>>>            return;
> >>>>>    -    wb_enc = to_dpu_encoder_phys_wb(phys_enc);
> >>>>> -    cdm_cfg = &wb_enc->cdm_cfg;
> >>>>> +    cdm_cfg = &phys_enc->cdm_cfg;
> >>>>>        hw_pp = phys_enc->hw_pp;
> >>>>>        hw_cdm = phys_enc->hw_cdm;
> >>>>> -    wb_job = wb_enc->wb_job;
> >>>>> -
> >>>>> -    format = msm_framebuffer_format(wb_enc->wb_job->fb);
> >>>>> -    dpu_fmt = dpu_get_dpu_format_ext(format->pixel_format,
> >>>>> wb_job->fb->modifier);
> >>>>>          if (!hw_cdm)
> >>>>>            return;
> >>>>> @@ -306,10 +299,10 @@ static void
> >>>>> dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
> >>>>>          memset(cdm_cfg, 0, sizeof(struct dpu_hw_cdm_cfg));
> >>>>>    -    cdm_cfg->output_width = wb_job->fb->width;
> >>>>> -    cdm_cfg->output_height = wb_job->fb->height;
> >>>>> +    cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
> >>>>> +    cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
> >>>>
> >>>> This is a semantic change. Instead of passing the FB size, this passes
> >>>> the mode dimensions. They are not guaranteed to be the same,
> >>>> especially for the WB case.
> >>>>
> >>
> >> The WB job is storing the output FB of WB. I cannot think of a use-case
> >> where this cannot match the current mode programmed to the WB encoder.
> >>
> >> Yes, if it was the drm_plane's FB, then it cannot be guaranteed as the
> >> plane can scale the contents but here thats not the case. Here its the
> >> output FB of WB.
> >
> > Is it a part of WB uAPI, to have the FB dimensions equal to mode
> > dimensions? Or is it just our current limitation? I can easily imagine
> > WB outputting data to a part of the FB (just like we can clip FB using
> > plane's clip rectangle).
> >
> > This boils down to a question, whether CDM should be setup in terms of
> > actual output date or the physical memory buffer parameters. I suspect
> > the former is the case (which makes this change correct). But it
> > either should be described in the commit message or (even better)
> > split to a separate commit.
> >
>
> I would say its a combination of both today.
>
> The way I would look at it is even if WB crops a certain section of FB,
> that will not change the FB size. FB size of WB should match the rest of
> the DRM pipeline (the mode programmed to the CRTC/encoder). If WB
> decides to write to only a small section of FB (cropping), then we need
> another WB property like CROP_ROI so that we can program the WB to only
> write to a small section of the programmed FB. So in some sense, there
> is no such support in DRM UAPI today. Hence the FB of WB is the full
> mode of the WB.

 I'd say, CROP_ROI can refer to cropping of the image source (esp. in
the cloned output case). For writing to the part of the FB there can
be DST_X/_Y/_W/_H properties. But this becomes off-topic.

> CDM is before WB so follows the rest of the pipeline that is whatever
> the data feeding it was programmed to.

Yes. So the change is correct, but it should be split or documented
properly. I prefer the first option.


-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 17/17] drm/msm/dp: allow YUV420 mode for DP connector when VSC SDP supported
  2024-01-29  3:52       ` Dmitry Baryshkov
@ 2024-01-29  4:30         ` Abhinav Kumar
  2024-01-29  5:05           ` Dmitry Baryshkov
  0 siblings, 1 reply; 95+ messages in thread
From: Abhinav Kumar @ 2024-01-29  4:30 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno



On 1/28/2024 7:52 PM, Dmitry Baryshkov wrote:
> On Mon, 29 Jan 2024 at 05:17, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 1/25/2024 2:05 PM, Dmitry Baryshkov wrote:
>>> On 25/01/2024 21:38, Paloma Arellano wrote:
>>>> All the components of YUV420 over DP are added. Therefore, let's mark the
>>>> connector property as true for DP connector when the DP type is not eDP
>>>> and when VSC SDP is supported.
>>>>
>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>>> ---
>>>>    drivers/gpu/drm/msm/dp/dp_display.c | 5 ++++-
>>>>    1 file changed, 4 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
>>>> b/drivers/gpu/drm/msm/dp/dp_display.c
>>>> index 4329435518351..97edd607400b8 100644
>>>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
>>>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
>>>> @@ -370,11 +370,14 @@ static int dp_display_process_hpd_high(struct
>>>> dp_display_private *dp)
>>>>        dp_link_process_request(dp->link);
>>>> -    if (!dp->dp_display.is_edp)
>>>> +    if (!dp->dp_display.is_edp) {
>>>> +        if (dp_panel_vsc_sdp_supported(dp->panel))
>>>> +            dp->dp_display.connector->ycbcr_420_allowed = true;
>>>
>>> Please consider fixing a TODO in drm_bridge_connector_init().
>>>
>>
>> I am not totally clear if that TODO can ever go for DP/HDMI usage of
>> drm_bridge_connector.
>>
>> We do not know if the sink supports VSC SDP till we read the DPCD and
>> till we know that sink supports VSC SDP, there is no reason to mark the
>> YUV modes as supported. This is the same logic followed across vendors.
>>
>> drm_bride_connector_init() happens much earlier than the point where we
>> read DPCD. The only thing which can be done is perhaps add some callback
>> to update_ycbcr_420_allowed once DPCD is read. But I don't think its
>> absolutely necessary to have a callback just for this.
> 
> After checking the drm_connector docs, I'd still hold my opinion and
> consider this patch to be a misuse of the property. If you check the
> drm_connector::ycbcr_420_allowed docs, you'll see that it describes
> the output from the source point of view. In other words, it should be
> true if the DP connector can send YUV420 rather than being set if the
> attached display supports such output. This matches ycbcr420_allowed
> usage by AMD, dw-hdmi, intel_hdmi and even intel_dp usage.
> 

hmmm I think I misread intel_dp_update_420(). I saw this is called after 
HPD so I thought they unset ycbcr_420_allowed if VSC SDP is not 
supported. But they have other DPCD checking there so anyway they will 
fail this bridge_connector_init() model.

But one argument which I can give in my defense is, lets say the sink 
exposed YUV formats but did not support SDP, then atomic_check() will 
keep failing or should keep failing. This will avoid this scenario. But 
we can assume that would be a rogue sink.

I think we can pass a yuv_supported flag to msm_dp_modeset_init() and 
set it to true from dpu_kms if catalog has CDM block and get rid of the 
dp_panel_vsc_sdp_supported().

But that doesnt address the TODO you have pointed to. What is really the 
expectation of the TODO? Do we need to pass a ycbcr_420_allowed flag to
drm_bridge_connector_init()?

That would need a tree wide cleanup and thats difficult to sign up for 
in this series and I would not as well.

One thing which I can suggest to be less intrusive is have a new API 
called drm_bridge_connector_init_with_YUV() which looks something like 
below:

struct drm_connector *drm_bridge_connector_init_with_ycbcr_420(struct 
drm_device *drm, struct drm_encoder *encoder)
{
	drm_bridge_connector_init();
	connector->ycbcr_420_allowed = true;
}

But I don't know if the community would be interested in this idea or 
would find that useful.

>>>>            drm_dp_set_subconnector_property(dp->dp_display.connector,
>>>>                             connector_status_connected,
>>>>                             dp->panel->dpcd,
>>>>                             dp->panel->downstream_ports);
>>>> +    }
>>>>        edid = dp->panel->edid;
>>>
> 
> 
> 

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 01/17] drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP
  2024-01-29  4:12             ` Dmitry Baryshkov
@ 2024-01-29  4:33               ` Abhinav Kumar
  2024-01-29  5:12                 ` Dmitry Baryshkov
  0 siblings, 1 reply; 95+ messages in thread
From: Abhinav Kumar @ 2024-01-29  4:33 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno



On 1/28/2024 8:12 PM, Dmitry Baryshkov wrote:
> On Mon, 29 Jan 2024 at 06:01, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 1/28/2024 7:23 PM, Dmitry Baryshkov wrote:
>>> On Mon, 29 Jan 2024 at 05:06, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>>>
>>>>
>>>>
>>>> On 1/26/2024 4:39 PM, Paloma Arellano wrote:
>>>>>
>>>>> On 1/25/2024 1:14 PM, Dmitry Baryshkov wrote:
>>>>>> On 25/01/2024 21:38, Paloma Arellano wrote:
>>>>>>> Generalize dpu_encoder_helper_phys_setup_cdm to be compatible with DP.
>>>>>>>
>>>>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>>>>>> ---
>>>>>>>     .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  4 +--
>>>>>>>     .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 31 ++++++++++---------
>>>>>>>     2 files changed, 18 insertions(+), 17 deletions(-)
>>>>>>>
>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>>>>>>> index 993f263433314..37ac385727c3b 100644
>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>>>>>>> @@ -153,6 +153,7 @@ enum dpu_intr_idx {
>>>>>>>      * @hw_intf:        Hardware interface to the intf registers
>>>>>>>      * @hw_wb:        Hardware interface to the wb registers
>>>>>>>      * @hw_cdm:        Hardware interface to the CDM registers
>>>>>>> + * @cdm_cfg:    CDM block config needed to store WB/DP block's CDM
>>>>>>> configuration
>>>>>>
>>>>>> Please realign the description.
>>>>> Ack
>>>>>>
>>>>>>>      * @dpu_kms:        Pointer to the dpu_kms top level
>>>>>>>      * @cached_mode:    DRM mode cached at mode_set time, acted on in
>>>>>>> enable
>>>>>>>      * @vblank_ctl_lock:    Vblank ctl mutex lock to protect
>>>>>>> vblank_refcount
>>>>>>> @@ -183,6 +184,7 @@ struct dpu_encoder_phys {
>>>>>>>         struct dpu_hw_intf *hw_intf;
>>>>>>>         struct dpu_hw_wb *hw_wb;
>>>>>>>         struct dpu_hw_cdm *hw_cdm;
>>>>>>> +    struct dpu_hw_cdm_cfg cdm_cfg;
>>>>>>
>>>>>> It might be slightly better to move it after all the pointers, so
>>>>>> after the dpu_kms.
>>>>> Ack
>>>>>>
>>>>>>>         struct dpu_kms *dpu_kms;
>>>>>>>         struct drm_display_mode cached_mode;
>>>>>>>         struct mutex vblank_ctl_lock;
>>>>>>> @@ -213,7 +215,6 @@ static inline int
>>>>>>> dpu_encoder_phys_inc_pending(struct dpu_encoder_phys *phys)
>>>>>>>      * @wbirq_refcount:     Reference count of writeback interrupt
>>>>>>>      * @wb_done_timeout_cnt: number of wb done irq timeout errors
>>>>>>>      * @wb_cfg:  writeback block config to store fb related details
>>>>>>> - * @cdm_cfg: cdm block config needed to store writeback block's CDM
>>>>>>> configuration
>>>>>>>      * @wb_conn: backpointer to writeback connector
>>>>>>>      * @wb_job: backpointer to current writeback job
>>>>>>>      * @dest:   dpu buffer layout for current writeback output buffer
>>>>>>> @@ -223,7 +224,6 @@ struct dpu_encoder_phys_wb {
>>>>>>>         atomic_t wbirq_refcount;
>>>>>>>         int wb_done_timeout_cnt;
>>>>>>>         struct dpu_hw_wb_cfg wb_cfg;
>>>>>>> -    struct dpu_hw_cdm_cfg cdm_cfg;
>>>>>>>         struct drm_writeback_connector *wb_conn;
>>>>>>>         struct drm_writeback_job *wb_job;
>>>>>>>         struct dpu_hw_fmt_layout dest;
>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>>>>>>> index 4cd2d9e3131a4..072fc6950e496 100644
>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>>>>>>> @@ -269,28 +269,21 @@ static void
>>>>>>> dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
>>>>>>>      *                                     This API does not handle
>>>>>>> DPU_CHROMA_H1V2.
>>>>>>>      * @phys_enc:Pointer to physical encoder
>>>>>>>      */
>>>>>>> -static void dpu_encoder_helper_phys_setup_cdm(struct
>>>>>>> dpu_encoder_phys *phys_enc)
>>>>>>> +static void dpu_encoder_helper_phys_setup_cdm(struct
>>>>>>> dpu_encoder_phys *phys_enc,
>>>>>>> +                          const struct dpu_format *dpu_fmt,
>>>>>>> +                          u32 output_type)
>>>>>>>     {
>>>>>>>         struct dpu_hw_cdm *hw_cdm;
>>>>>>>         struct dpu_hw_cdm_cfg *cdm_cfg;
>>>>>>>         struct dpu_hw_pingpong *hw_pp;
>>>>>>> -    struct dpu_encoder_phys_wb *wb_enc;
>>>>>>> -    const struct msm_format *format;
>>>>>>> -    const struct dpu_format *dpu_fmt;
>>>>>>> -    struct drm_writeback_job *wb_job;
>>>>>>>         int ret;
>>>>>>>           if (!phys_enc)
>>>>>>>             return;
>>>>>>>     -    wb_enc = to_dpu_encoder_phys_wb(phys_enc);
>>>>>>> -    cdm_cfg = &wb_enc->cdm_cfg;
>>>>>>> +    cdm_cfg = &phys_enc->cdm_cfg;
>>>>>>>         hw_pp = phys_enc->hw_pp;
>>>>>>>         hw_cdm = phys_enc->hw_cdm;
>>>>>>> -    wb_job = wb_enc->wb_job;
>>>>>>> -
>>>>>>> -    format = msm_framebuffer_format(wb_enc->wb_job->fb);
>>>>>>> -    dpu_fmt = dpu_get_dpu_format_ext(format->pixel_format,
>>>>>>> wb_job->fb->modifier);
>>>>>>>           if (!hw_cdm)
>>>>>>>             return;
>>>>>>> @@ -306,10 +299,10 @@ static void
>>>>>>> dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
>>>>>>>           memset(cdm_cfg, 0, sizeof(struct dpu_hw_cdm_cfg));
>>>>>>>     -    cdm_cfg->output_width = wb_job->fb->width;
>>>>>>> -    cdm_cfg->output_height = wb_job->fb->height;
>>>>>>> +    cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
>>>>>>> +    cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
>>>>>>
>>>>>> This is a semantic change. Instead of passing the FB size, this passes
>>>>>> the mode dimensions. They are not guaranteed to be the same,
>>>>>> especially for the WB case.
>>>>>>
>>>>
>>>> The WB job is storing the output FB of WB. I cannot think of a use-case
>>>> where this cannot match the current mode programmed to the WB encoder.
>>>>
>>>> Yes, if it was the drm_plane's FB, then it cannot be guaranteed as the
>>>> plane can scale the contents but here thats not the case. Here its the
>>>> output FB of WB.
>>>
>>> Is it a part of WB uAPI, to have the FB dimensions equal to mode
>>> dimensions? Or is it just our current limitation? I can easily imagine
>>> WB outputting data to a part of the FB (just like we can clip FB using
>>> plane's clip rectangle).
>>>
>>> This boils down to a question, whether CDM should be setup in terms of
>>> actual output date or the physical memory buffer parameters. I suspect
>>> the former is the case (which makes this change correct). But it
>>> either should be described in the commit message or (even better)
>>> split to a separate commit.
>>>
>>
>> I would say its a combination of both today.
>>
>> The way I would look at it is even if WB crops a certain section of FB,
>> that will not change the FB size. FB size of WB should match the rest of
>> the DRM pipeline (the mode programmed to the CRTC/encoder). If WB
>> decides to write to only a small section of FB (cropping), then we need
>> another WB property like CROP_ROI so that we can program the WB to only
>> write to a small section of the programmed FB. So in some sense, there
>> is no such support in DRM UAPI today. Hence the FB of WB is the full
>> mode of the WB.
> 
>   I'd say, CROP_ROI can refer to cropping of the image source (esp. in
> the cloned output case). For writing to the part of the FB there can
> be DST_X/_Y/_W/_H properties. But this becomes off-topic.
> 
>> CDM is before WB so follows the rest of the pipeline that is whatever
>> the data feeding it was programmed to.
> 
> Yes. So the change is correct, but it should be split or documented
> properly. I prefer the first option.
> 

Ok just to clarify you prefer below part of the change to be moved to 
its own commit right?

-    cdm_cfg->output_width = wb_job->fb->width;
-    cdm_cfg->output_height = wb_job->fb->height;
+    cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
+    cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;

If so, ack.

> 

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 14/17] drm/msm/dpu: modify encoder programming for CDM over DP
  2024-01-29  3:42           ` Dmitry Baryshkov
@ 2024-01-29  5:03             ` Abhinav Kumar
  2024-01-29  6:12               ` Dmitry Baryshkov
  0 siblings, 1 reply; 95+ messages in thread
From: Abhinav Kumar @ 2024-01-29  5:03 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno



On 1/28/2024 7:42 PM, Dmitry Baryshkov wrote:
> On Mon, 29 Jan 2024 at 04:58, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 1/27/2024 9:55 PM, Dmitry Baryshkov wrote:
>>> On Sun, 28 Jan 2024 at 07:48, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>>>>
>>>>
>>>> On 1/25/2024 1:57 PM, Dmitry Baryshkov wrote:
>>>>> On 25/01/2024 21:38, Paloma Arellano wrote:
>>>>>> Adjust the encoder format programming in the case of video mode for DP
>>>>>> to accommodate CDM related changes.
>>>>>>
>>>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>>>>> ---
>>>>>>     drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 16 +++++++++
>>>>>>     drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |  8 +++++
>>>>>>     .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 35 ++++++++++++++++---
>>>>>>     drivers/gpu/drm/msm/dp/dp_display.c           | 12 +++++++
>>>>>>     drivers/gpu/drm/msm/msm_drv.h                 |  9 ++++-
>>>>>>     5 files changed, 75 insertions(+), 5 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>> index b0896814c1562..99ec53446ad21 100644
>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>> @@ -222,6 +222,22 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = {
>>>>>>         15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10
>>>>>>     };
>>>>>>     +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
>>>>>> const struct drm_display_mode *mode)
>>>>>> +{
>>>>>> +    const struct dpu_encoder_virt *dpu_enc;
>>>>>> +    const struct msm_display_info *disp_info;
>>>>>> +    struct msm_drm_private *priv;
>>>>>> +
>>>>>> +    dpu_enc = to_dpu_encoder_virt(drm_enc);
>>>>>> +    disp_info = &dpu_enc->disp_info;
>>>>>> +    priv = drm_enc->dev->dev_private;
>>>>>> +
>>>>>> +    if (disp_info->intf_type == INTF_DP &&
>>>>>> + msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]],
>>>>>> mode))
>>>>>
>>>>> This should not require interacting with DP. If we got here, we must
>>>>> be sure that 4:2:0 is supported and can be configured.
>>>> Ack. Will drop this function and only check for if the mode is YUV420.
>>>>>
>>>>>> +        return DRM_FORMAT_YUV420;
>>>>>> +
>>>>>> +    return DRM_FORMAT_RGB888;
>>>>>> +}
>>>>>>       bool dpu_encoder_is_widebus_enabled(const struct drm_encoder
>>>>>> *drm_enc)
>>>>>>     {
>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>>>>>> index 7b4afa71f1f96..62255d0aa4487 100644
>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>>>>>> @@ -162,6 +162,14 @@ int dpu_encoder_get_vsync_count(struct
>>>>>> drm_encoder *drm_enc);
>>>>>>      */
>>>>>>     bool dpu_encoder_is_widebus_enabled(const struct drm_encoder
>>>>>> *drm_enc);
>>>>>>     +/**
>>>>>> + * dpu_encoder_get_drm_fmt - return DRM fourcc format
>>>>>> + * @drm_enc:    Pointer to previously created drm encoder structure
>>>>>> + * @mode:    Corresponding drm_display_mode for dpu encoder
>>>>>> + */
>>>>>> +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
>>>>>> +                const struct drm_display_mode *mode);
>>>>>> +
>>>>>>     /**
>>>>>>      * dpu_encoder_get_crc_values_cnt - get number of physical encoders
>>>>>> contained
>>>>>>      *    in virtual encoder that can collect CRC values
>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>>>> index e284bf448bdda..a1dde0ff35dc8 100644
>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>>>> @@ -234,6 +234,7 @@ static void
>>>>>> dpu_encoder_phys_vid_setup_timing_engine(
>>>>>>     {
>>>>>>         struct drm_display_mode mode;
>>>>>>         struct dpu_hw_intf_timing_params timing_params = { 0 };
>>>>>> +    struct dpu_hw_cdm *hw_cdm;
>>>>>>         const struct dpu_format *fmt = NULL;
>>>>>>         u32 fmt_fourcc = DRM_FORMAT_RGB888;
>>>>>>         unsigned long lock_flags;
>>>>>> @@ -254,17 +255,26 @@ static void
>>>>>> dpu_encoder_phys_vid_setup_timing_engine(
>>>>>>         DPU_DEBUG_VIDENC(phys_enc, "enabling mode:\n");
>>>>>>         drm_mode_debug_printmodeline(&mode);
>>>>>>     -    if (phys_enc->split_role != ENC_ROLE_SOLO) {
>>>>>> +    hw_cdm = phys_enc->hw_cdm;
>>>>>> +    if (hw_cdm) {
>>>>>> +        intf_cfg.cdm = hw_cdm->idx;
>>>>>> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent, &mode);
>>>>>> +    }
>>>>>> +
>>>>>> +    if (phys_enc->split_role != ENC_ROLE_SOLO ||
>>>>>> +        dpu_encoder_get_drm_fmt(phys_enc->parent, &mode) ==
>>>>>> DRM_FORMAT_YUV420) {
>>>>>>             mode.hdisplay >>= 1;
>>>>>>             mode.htotal >>= 1;
>>>>>>             mode.hsync_start >>= 1;
>>>>>>             mode.hsync_end >>= 1;
>>>>>> +        mode.hskew >>= 1;
>>>>>
>>>>> Separate patch.
>>>> Ack.
>>>>>
>>>>>>               DPU_DEBUG_VIDENC(phys_enc,
>>>>>> -            "split_role %d, halve horizontal %d %d %d %d\n",
>>>>>> +            "split_role %d, halve horizontal %d %d %d %d %d\n",
>>>>>>                 phys_enc->split_role,
>>>>>>                 mode.hdisplay, mode.htotal,
>>>>>> -            mode.hsync_start, mode.hsync_end);
>>>>>> +            mode.hsync_start, mode.hsync_end,
>>>>>> +            mode.hskew);
>>>>>>         }
>>>>>>           drm_mode_to_intf_timing_params(phys_enc, &mode, &timing_params);
>>>>>> @@ -412,8 +422,15 @@ static int dpu_encoder_phys_vid_control_vblank_irq(
>>>>>>     static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys
>>>>>> *phys_enc)
>>>>>>     {
>>>>>>         struct dpu_hw_ctl *ctl;
>>>>>> +    struct dpu_hw_cdm *hw_cdm;
>>>>>> +    const struct dpu_format *fmt = NULL;
>>>>>> +    u32 fmt_fourcc = DRM_FORMAT_RGB888;
>>>>>>           ctl = phys_enc->hw_ctl;
>>>>>> +    hw_cdm = phys_enc->hw_cdm;
>>>>>> +    if (hw_cdm)
>>>>>> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent,
>>>>>> &phys_enc->cached_mode);
>>>>>> +    fmt = dpu_get_dpu_format(fmt_fourcc);
>>>>>>           DPU_DEBUG_VIDENC(phys_enc, "\n");
>>>>>>     @@ -422,6 +439,8 @@ static void dpu_encoder_phys_vid_enable(struct
>>>>>> dpu_encoder_phys *phys_enc)
>>>>>>           dpu_encoder_helper_split_config(phys_enc,
>>>>>> phys_enc->hw_intf->idx);
>>>>>>     +    dpu_encoder_helper_phys_setup_cdm(phys_enc, fmt,
>>>>>> CDM_CDWN_OUTPUT_HDMI);
>>>>>
>>>>> If there is no CDM, why do we need to call this?
>>>> Inside of dpu_encoder_helper_phys_setup_cdm(), there's a check to see if
>>>> there is a hw_cdm. If there is not, then it immediately exits the function.
>>>>>
>>>>>> +
>>>>>>         dpu_encoder_phys_vid_setup_timing_engine(phys_enc);
>>>>>>           /*
>>>>>> @@ -437,7 +456,15 @@ static void dpu_encoder_phys_vid_enable(struct
>>>>>> dpu_encoder_phys *phys_enc)
>>>>>>         if (ctl->ops.update_pending_flush_merge_3d &&
>>>>>> phys_enc->hw_pp->merge_3d)
>>>>>>             ctl->ops.update_pending_flush_merge_3d(ctl,
>>>>>> phys_enc->hw_pp->merge_3d->idx);
>>>>>>     -    if (ctl->ops.update_pending_flush_periph &&
>>>>>> phys_enc->hw_intf->cap->type == INTF_DP)
>>>>>> +    if (ctl->ops.update_pending_flush_cdm && phys_enc->hw_cdm)
>>>>>> +        ctl->ops.update_pending_flush_cdm(ctl, hw_cdm->idx);
>>>>>> +
>>>>>> +    /*
>>>>>> +     * Peripheral flush must be updated whenever flushing SDP
>>>>>> packets is needed.
>>>>>> +     * SDP packets are required for any YUV format (YUV420, YUV422,
>>>>>> YUV444).
>>>>>> +     */
>>>>>> +    if (ctl->ops.update_pending_flush_periph &&
>>>>>> phys_enc->hw_intf->cap->type == INTF_DP &&
>>>>>> +        phys_enc->hw_cdm)
>>>>>>             ctl->ops.update_pending_flush_periph(ctl,
>>>>>> phys_enc->hw_intf->idx);
>>>>>
>>>>> Should there be a flush if we are switching from YUV 420 to RGB mode?
>>>> We only need to flush for the sdp packet, but for msa we do not need to
>>>> flush.
>>>
>>> What about having SDP with RGB as colorimetry? In other words, if
>>> there is a decision point, this one looks incorrect.
>>>
>>
>> There are two ways to do it:
>>
>> 1) Use SDP for both RGB and YUV as that supports both. If we implement
>> this policy, then what you are asking for is correct that we will need
>> SDP even to switch back to RGB. But to implement this we will also need
>> to have some sort of state management in the encoder layer about what is
>> the current encoder fmt Vs what is the prev fmt and then trigger
>> peripheral flush only during transitions from RGB to YUV and vice-versa
>>
>> 2) Use SDP only for YUV because MSA does not support YUV formats and use
>> MSA for RGB
>>
>> We decided to implement (2) and there is no significant impact of
>> switching between MSA and SDPs but state management becomes easier.
> 
> Yes. However as you wrote, there might be other usecases concerning
> SDP. Having this in mind, it sounds like the driver should decide
> whether to flush peripheral at a different place (when the SDP
> infoframe is being updated?). And the dpu_encoder_phys_vid_enable()
> should use this previous decision. Maybe this should be a part of
> msm_dp_ API, something like msm_dp_needs_peripheral_flush()?
> 

Correct. The decision to flush peripheral or not certainly comes from 
the peripheral itself . In this case its DP.

I think perhaps the usage of hw_cdm here makes it hard to understand 
that but the idea behind this was that in the change "drm/msm/dpu: 
reserve CDM blocks for DP if mode is YUV420 ", hw_cdm is assigned only 
if msm_dp_is_yuv_420_enabled() returns true.

So in some sense, the API you are asking for is already 
msm_dp_is_yuv_420_enabled() but we can rename that to 
msm_dp_needs_periph_flush().

The issue here is the phys layer cannot call msm_dp_is_yuv_420_enabled() 
so its kind of round-about by checking hw_cdm.

The check is not entirely wrong because for DP, we need hw_cdm for all 
YUV formats and not just 420 but the relationship is maybe not clear but 
I thought the comment above that would help a bit:

/*
	 * Peripheral flush must be updated whenever flushing SDP packets is 
needed.
	 * SDP packets are required for any YUV format (YUV420, YUV422, YUV444).
	 */

The only other way I can think of is maybe we need to introduce a new 
phys variable called phys_enc->needs_update_periph_flush and we can set 
that in dpu_encoder.c as that can call msm_dp_needs_periph_flush().

What do you think of this way?

>>
>>>>>
>>>>> Also, I'd say, we should move update_pending_flush_periph invocation
>>>>> to this patch.
>>>> Ack
>>>>>
>>>>>>       skip_flush:
>>>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
>>>>>> b/drivers/gpu/drm/msm/dp/dp_display.c
>>>>>> index 6d764f5b08727..4329435518351 100644
>>>>>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
>>>>>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
>>>>>> @@ -1399,6 +1399,18 @@ void __exit msm_dp_unregister(void)
>>>>>>         platform_driver_unregister(&dp_display_driver);
>>>>>>     }
>>>>>>     +bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
>>>>>> +                   const struct drm_display_mode *mode)
>>>>>> +{
>>>>>> +    struct dp_display_private *dp;
>>>>>> +    const struct drm_display_info *info;
>>>>>> +
>>>>>> +    dp = container_of(dp_display, struct dp_display_private,
>>>>>> dp_display);
>>>>>> +    info = &dp_display->connector->display_info;
>>>>>> +
>>>>>> +    return dp_panel_vsc_sdp_supported(dp->panel) &&
>>>>>> drm_mode_is_420_only(info, mode);
>>>>>
>>>>> YUV 420 modes should be filtered out in mode_valid if VSC SDP is not
>>>>> supported.
>>>> Ack. Will change
>>>>>
>>>>>> +}
>>>>>> +
>>>>>>     bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)
>>>>>>     {
>>>>>>         struct dp_display_private *dp;
>>>>>> diff --git a/drivers/gpu/drm/msm/msm_drv.h
>>>>>> b/drivers/gpu/drm/msm/msm_drv.h
>>>>>> index 16a7cbc0b7dd8..b9581bd934e9e 100644
>>>>>> --- a/drivers/gpu/drm/msm/msm_drv.h
>>>>>> +++ b/drivers/gpu/drm/msm/msm_drv.h
>>>>>> @@ -387,7 +387,8 @@ void __exit msm_dp_unregister(void);
>>>>>>     int msm_dp_modeset_init(struct msm_dp *dp_display, struct
>>>>>> drm_device *dev,
>>>>>>                  struct drm_encoder *encoder);
>>>>>>     void msm_dp_snapshot(struct msm_disp_state *disp_state, struct
>>>>>> msm_dp *dp_display);
>>>>>> -
>>>>>> +bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
>>>>>> +                   const struct drm_display_mode *mode);
>>>>>>     bool msm_dp_wide_bus_available(const struct msm_dp *dp_display);
>>>>>>       #else
>>>>>> @@ -409,6 +410,12 @@ static inline void msm_dp_snapshot(struct
>>>>>> msm_disp_state *disp_state, struct msm
>>>>>>     {
>>>>>>     }
>>>>>>     +static inline bool msm_dp_is_yuv_420_enabled(const struct msm_dp
>>>>>> *dp_display,
>>>>>> +                         const struct drm_display_mode *mode)
>>>>>> +{
>>>>>> +    return false;
>>>>>> +}
>>>>>> +
>>>>>>     static inline bool msm_dp_wide_bus_available(const struct msm_dp
>>>>>> *dp_display)
>>>>>>     {
>>>>>>         return false;
>>>>>
>>>
>>>
>>>
>>> --
>>> With best wishes
>>> Dmitry
> 
> 
> 

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 17/17] drm/msm/dp: allow YUV420 mode for DP connector when VSC SDP supported
  2024-01-29  4:30         ` Abhinav Kumar
@ 2024-01-29  5:05           ` Dmitry Baryshkov
  2024-01-29  5:36             ` Abhinav Kumar
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-29  5:05 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno

On Mon, 29 Jan 2024 at 06:30, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 1/28/2024 7:52 PM, Dmitry Baryshkov wrote:
> > On Mon, 29 Jan 2024 at 05:17, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >>
> >>
> >> On 1/25/2024 2:05 PM, Dmitry Baryshkov wrote:
> >>> On 25/01/2024 21:38, Paloma Arellano wrote:
> >>>> All the components of YUV420 over DP are added. Therefore, let's mark the
> >>>> connector property as true for DP connector when the DP type is not eDP
> >>>> and when VSC SDP is supported.
> >>>>
> >>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >>>> ---
> >>>>    drivers/gpu/drm/msm/dp/dp_display.c | 5 ++++-
> >>>>    1 file changed, 4 insertions(+), 1 deletion(-)
> >>>>
> >>>> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
> >>>> b/drivers/gpu/drm/msm/dp/dp_display.c
> >>>> index 4329435518351..97edd607400b8 100644
> >>>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> >>>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> >>>> @@ -370,11 +370,14 @@ static int dp_display_process_hpd_high(struct
> >>>> dp_display_private *dp)
> >>>>        dp_link_process_request(dp->link);
> >>>> -    if (!dp->dp_display.is_edp)
> >>>> +    if (!dp->dp_display.is_edp) {
> >>>> +        if (dp_panel_vsc_sdp_supported(dp->panel))
> >>>> +            dp->dp_display.connector->ycbcr_420_allowed = true;
> >>>
> >>> Please consider fixing a TODO in drm_bridge_connector_init().
> >>>
> >>
> >> I am not totally clear if that TODO can ever go for DP/HDMI usage of
> >> drm_bridge_connector.
> >>
> >> We do not know if the sink supports VSC SDP till we read the DPCD and
> >> till we know that sink supports VSC SDP, there is no reason to mark the
> >> YUV modes as supported. This is the same logic followed across vendors.
> >>
> >> drm_bride_connector_init() happens much earlier than the point where we
> >> read DPCD. The only thing which can be done is perhaps add some callback
> >> to update_ycbcr_420_allowed once DPCD is read. But I don't think its
> >> absolutely necessary to have a callback just for this.
> >
> > After checking the drm_connector docs, I'd still hold my opinion and
> > consider this patch to be a misuse of the property. If you check the
> > drm_connector::ycbcr_420_allowed docs, you'll see that it describes
> > the output from the source point of view. In other words, it should be
> > true if the DP connector can send YUV420 rather than being set if the
> > attached display supports such output. This matches ycbcr420_allowed
> > usage by AMD, dw-hdmi, intel_hdmi and even intel_dp usage.
> >
>
> hmmm I think I misread intel_dp_update_420(). I saw this is called after
> HPD so I thought they unset ycbcr_420_allowed if VSC SDP is not
> supported. But they have other DPCD checking there so anyway they will
> fail this bridge_connector_init() model.
>
> But one argument which I can give in my defense is, lets say the sink
> exposed YUV formats but did not support SDP, then atomic_check() will
> keep failing or should keep failing. This will avoid this scenario. But
> we can assume that would be a rogue sink.

This should be handled in DP's atomic_check. As usual, bonus point if
this is done via helpers that can be reused by other platforms.

> I think we can pass a yuv_supported flag to msm_dp_modeset_init() and
> set it to true from dpu_kms if catalog has CDM block and get rid of the
> dp_panel_vsc_sdp_supported().

These are two different issues. CDM should be checked in PDU (whether
the DPU can provide YUV data to the DP block).

>
> But that doesnt address the TODO you have pointed to. What is really the
> expectation of the TODO? Do we need to pass a ycbcr_420_allowed flag to
> drm_bridge_connector_init()?

Ugh. No. I was thinking about a `ycbcr420_allowed` flag in the struct
drm_bridge (to follow existing interlace_allowed) flag. But, this
might be not the best option. Each bridge can either pass through YUV
data from the previous bridge or generate YCbCr data on its own. So in
theory this demands two flags plus one flag for the encoder. Which
might be an overkill, until we end up in a situation when the driver
can not decide for the full bridge chain.

So let's probably ignore the TODO for the purpose of this series. Just
fix the usage of ycbcr420_allowed according to docs.

>
> That would need a tree wide cleanup and thats difficult to sign up for
> in this series and I would not as well.
>
> One thing which I can suggest to be less intrusive is have a new API
> called drm_bridge_connector_init_with_YUV() which looks something like
> below:
>
> struct drm_connector *drm_bridge_connector_init_with_ycbcr_420(struct
> drm_device *drm, struct drm_encoder *encoder)
> {
>         drm_bridge_connector_init();
>         connector->ycbcr_420_allowed = true;
> }
>
> But I don't know if the community would be interested in this idea or
> would find that useful.
>
> >>>>            drm_dp_set_subconnector_property(dp->dp_display.connector,
> >>>>                             connector_status_connected,
> >>>>                             dp->panel->dpcd,
> >>>>                             dp->panel->downstream_ports);
> >>>> +    }
> >>>>        edid = dp->panel->edid;
> >>>
> >
> >
> >



-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 01/17] drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP
  2024-01-29  4:33               ` Abhinav Kumar
@ 2024-01-29  5:12                 ` Dmitry Baryshkov
  2024-01-29 23:06                   ` Paloma Arellano
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-29  5:12 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno

On Mon, 29 Jan 2024 at 06:33, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 1/28/2024 8:12 PM, Dmitry Baryshkov wrote:
> > On Mon, 29 Jan 2024 at 06:01, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >>
> >>
> >> On 1/28/2024 7:23 PM, Dmitry Baryshkov wrote:
> >>> On Mon, 29 Jan 2024 at 05:06, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>>>
> >>>>
> >>>>
> >>>> On 1/26/2024 4:39 PM, Paloma Arellano wrote:
> >>>>>
> >>>>> On 1/25/2024 1:14 PM, Dmitry Baryshkov wrote:
> >>>>>> On 25/01/2024 21:38, Paloma Arellano wrote:
> >>>>>>> Generalize dpu_encoder_helper_phys_setup_cdm to be compatible with DP.
> >>>>>>>
> >>>>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >>>>>>> ---
> >>>>>>>     .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  4 +--
> >>>>>>>     .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 31 ++++++++++---------
> >>>>>>>     2 files changed, 18 insertions(+), 17 deletions(-)
> >>>>>>>
> >>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >>>>>>> index 993f263433314..37ac385727c3b 100644
> >>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >>>>>>> @@ -153,6 +153,7 @@ enum dpu_intr_idx {
> >>>>>>>      * @hw_intf:        Hardware interface to the intf registers
> >>>>>>>      * @hw_wb:        Hardware interface to the wb registers
> >>>>>>>      * @hw_cdm:        Hardware interface to the CDM registers
> >>>>>>> + * @cdm_cfg:    CDM block config needed to store WB/DP block's CDM
> >>>>>>> configuration
> >>>>>>
> >>>>>> Please realign the description.
> >>>>> Ack
> >>>>>>
> >>>>>>>      * @dpu_kms:        Pointer to the dpu_kms top level
> >>>>>>>      * @cached_mode:    DRM mode cached at mode_set time, acted on in
> >>>>>>> enable
> >>>>>>>      * @vblank_ctl_lock:    Vblank ctl mutex lock to protect
> >>>>>>> vblank_refcount
> >>>>>>> @@ -183,6 +184,7 @@ struct dpu_encoder_phys {
> >>>>>>>         struct dpu_hw_intf *hw_intf;
> >>>>>>>         struct dpu_hw_wb *hw_wb;
> >>>>>>>         struct dpu_hw_cdm *hw_cdm;
> >>>>>>> +    struct dpu_hw_cdm_cfg cdm_cfg;
> >>>>>>
> >>>>>> It might be slightly better to move it after all the pointers, so
> >>>>>> after the dpu_kms.
> >>>>> Ack
> >>>>>>
> >>>>>>>         struct dpu_kms *dpu_kms;
> >>>>>>>         struct drm_display_mode cached_mode;
> >>>>>>>         struct mutex vblank_ctl_lock;
> >>>>>>> @@ -213,7 +215,6 @@ static inline int
> >>>>>>> dpu_encoder_phys_inc_pending(struct dpu_encoder_phys *phys)
> >>>>>>>      * @wbirq_refcount:     Reference count of writeback interrupt
> >>>>>>>      * @wb_done_timeout_cnt: number of wb done irq timeout errors
> >>>>>>>      * @wb_cfg:  writeback block config to store fb related details
> >>>>>>> - * @cdm_cfg: cdm block config needed to store writeback block's CDM
> >>>>>>> configuration
> >>>>>>>      * @wb_conn: backpointer to writeback connector
> >>>>>>>      * @wb_job: backpointer to current writeback job
> >>>>>>>      * @dest:   dpu buffer layout for current writeback output buffer
> >>>>>>> @@ -223,7 +224,6 @@ struct dpu_encoder_phys_wb {
> >>>>>>>         atomic_t wbirq_refcount;
> >>>>>>>         int wb_done_timeout_cnt;
> >>>>>>>         struct dpu_hw_wb_cfg wb_cfg;
> >>>>>>> -    struct dpu_hw_cdm_cfg cdm_cfg;
> >>>>>>>         struct drm_writeback_connector *wb_conn;
> >>>>>>>         struct drm_writeback_job *wb_job;
> >>>>>>>         struct dpu_hw_fmt_layout dest;
> >>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> >>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> >>>>>>> index 4cd2d9e3131a4..072fc6950e496 100644
> >>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> >>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
> >>>>>>> @@ -269,28 +269,21 @@ static void
> >>>>>>> dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
> >>>>>>>      *                                     This API does not handle
> >>>>>>> DPU_CHROMA_H1V2.
> >>>>>>>      * @phys_enc:Pointer to physical encoder
> >>>>>>>      */
> >>>>>>> -static void dpu_encoder_helper_phys_setup_cdm(struct
> >>>>>>> dpu_encoder_phys *phys_enc)
> >>>>>>> +static void dpu_encoder_helper_phys_setup_cdm(struct
> >>>>>>> dpu_encoder_phys *phys_enc,
> >>>>>>> +                          const struct dpu_format *dpu_fmt,
> >>>>>>> +                          u32 output_type)
> >>>>>>>     {
> >>>>>>>         struct dpu_hw_cdm *hw_cdm;
> >>>>>>>         struct dpu_hw_cdm_cfg *cdm_cfg;
> >>>>>>>         struct dpu_hw_pingpong *hw_pp;
> >>>>>>> -    struct dpu_encoder_phys_wb *wb_enc;
> >>>>>>> -    const struct msm_format *format;
> >>>>>>> -    const struct dpu_format *dpu_fmt;
> >>>>>>> -    struct drm_writeback_job *wb_job;
> >>>>>>>         int ret;
> >>>>>>>           if (!phys_enc)
> >>>>>>>             return;
> >>>>>>>     -    wb_enc = to_dpu_encoder_phys_wb(phys_enc);
> >>>>>>> -    cdm_cfg = &wb_enc->cdm_cfg;
> >>>>>>> +    cdm_cfg = &phys_enc->cdm_cfg;
> >>>>>>>         hw_pp = phys_enc->hw_pp;
> >>>>>>>         hw_cdm = phys_enc->hw_cdm;
> >>>>>>> -    wb_job = wb_enc->wb_job;
> >>>>>>> -
> >>>>>>> -    format = msm_framebuffer_format(wb_enc->wb_job->fb);
> >>>>>>> -    dpu_fmt = dpu_get_dpu_format_ext(format->pixel_format,
> >>>>>>> wb_job->fb->modifier);
> >>>>>>>           if (!hw_cdm)
> >>>>>>>             return;
> >>>>>>> @@ -306,10 +299,10 @@ static void
> >>>>>>> dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
> >>>>>>>           memset(cdm_cfg, 0, sizeof(struct dpu_hw_cdm_cfg));
> >>>>>>>     -    cdm_cfg->output_width = wb_job->fb->width;
> >>>>>>> -    cdm_cfg->output_height = wb_job->fb->height;
> >>>>>>> +    cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
> >>>>>>> +    cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
> >>>>>>
> >>>>>> This is a semantic change. Instead of passing the FB size, this passes
> >>>>>> the mode dimensions. They are not guaranteed to be the same,
> >>>>>> especially for the WB case.
> >>>>>>
> >>>>
> >>>> The WB job is storing the output FB of WB. I cannot think of a use-case
> >>>> where this cannot match the current mode programmed to the WB encoder.
> >>>>
> >>>> Yes, if it was the drm_plane's FB, then it cannot be guaranteed as the
> >>>> plane can scale the contents but here thats not the case. Here its the
> >>>> output FB of WB.
> >>>
> >>> Is it a part of WB uAPI, to have the FB dimensions equal to mode
> >>> dimensions? Or is it just our current limitation? I can easily imagine
> >>> WB outputting data to a part of the FB (just like we can clip FB using
> >>> plane's clip rectangle).
> >>>
> >>> This boils down to a question, whether CDM should be setup in terms of
> >>> actual output date or the physical memory buffer parameters. I suspect
> >>> the former is the case (which makes this change correct). But it
> >>> either should be described in the commit message or (even better)
> >>> split to a separate commit.
> >>>
> >>
> >> I would say its a combination of both today.
> >>
> >> The way I would look at it is even if WB crops a certain section of FB,
> >> that will not change the FB size. FB size of WB should match the rest of
> >> the DRM pipeline (the mode programmed to the CRTC/encoder). If WB
> >> decides to write to only a small section of FB (cropping), then we need
> >> another WB property like CROP_ROI so that we can program the WB to only
> >> write to a small section of the programmed FB. So in some sense, there
> >> is no such support in DRM UAPI today. Hence the FB of WB is the full
> >> mode of the WB.
> >
> >   I'd say, CROP_ROI can refer to cropping of the image source (esp. in
> > the cloned output case). For writing to the part of the FB there can
> > be DST_X/_Y/_W/_H properties. But this becomes off-topic.
> >
> >> CDM is before WB so follows the rest of the pipeline that is whatever
> >> the data feeding it was programmed to.
> >
> > Yes. So the change is correct, but it should be split or documented
> > properly. I prefer the first option.
> >
>
> Ok just to clarify you prefer below part of the change to be moved to
> its own commit right?
>
> -    cdm_cfg->output_width = wb_job->fb->width;
> -    cdm_cfg->output_height = wb_job->fb->height;
> +    cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
> +    cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
>
> If so, ack.

Yes.


-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 17/17] drm/msm/dp: allow YUV420 mode for DP connector when VSC SDP supported
  2024-01-29  5:05           ` Dmitry Baryshkov
@ 2024-01-29  5:36             ` Abhinav Kumar
  0 siblings, 0 replies; 95+ messages in thread
From: Abhinav Kumar @ 2024-01-29  5:36 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno



On 1/28/2024 9:05 PM, Dmitry Baryshkov wrote:
> On Mon, 29 Jan 2024 at 06:30, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 1/28/2024 7:52 PM, Dmitry Baryshkov wrote:
>>> On Mon, 29 Jan 2024 at 05:17, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>>>
>>>>
>>>>
>>>> On 1/25/2024 2:05 PM, Dmitry Baryshkov wrote:
>>>>> On 25/01/2024 21:38, Paloma Arellano wrote:
>>>>>> All the components of YUV420 over DP are added. Therefore, let's mark the
>>>>>> connector property as true for DP connector when the DP type is not eDP
>>>>>> and when VSC SDP is supported.
>>>>>>
>>>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>>>>> ---
>>>>>>     drivers/gpu/drm/msm/dp/dp_display.c | 5 ++++-
>>>>>>     1 file changed, 4 insertions(+), 1 deletion(-)
>>>>>>
>>>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
>>>>>> b/drivers/gpu/drm/msm/dp/dp_display.c
>>>>>> index 4329435518351..97edd607400b8 100644
>>>>>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
>>>>>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
>>>>>> @@ -370,11 +370,14 @@ static int dp_display_process_hpd_high(struct
>>>>>> dp_display_private *dp)
>>>>>>         dp_link_process_request(dp->link);
>>>>>> -    if (!dp->dp_display.is_edp)
>>>>>> +    if (!dp->dp_display.is_edp) {
>>>>>> +        if (dp_panel_vsc_sdp_supported(dp->panel))
>>>>>> +            dp->dp_display.connector->ycbcr_420_allowed = true;
>>>>>
>>>>> Please consider fixing a TODO in drm_bridge_connector_init().
>>>>>
>>>>
>>>> I am not totally clear if that TODO can ever go for DP/HDMI usage of
>>>> drm_bridge_connector.
>>>>
>>>> We do not know if the sink supports VSC SDP till we read the DPCD and
>>>> till we know that sink supports VSC SDP, there is no reason to mark the
>>>> YUV modes as supported. This is the same logic followed across vendors.
>>>>
>>>> drm_bride_connector_init() happens much earlier than the point where we
>>>> read DPCD. The only thing which can be done is perhaps add some callback
>>>> to update_ycbcr_420_allowed once DPCD is read. But I don't think its
>>>> absolutely necessary to have a callback just for this.
>>>
>>> After checking the drm_connector docs, I'd still hold my opinion and
>>> consider this patch to be a misuse of the property. If you check the
>>> drm_connector::ycbcr_420_allowed docs, you'll see that it describes
>>> the output from the source point of view. In other words, it should be
>>> true if the DP connector can send YUV420 rather than being set if the
>>> attached display supports such output. This matches ycbcr420_allowed
>>> usage by AMD, dw-hdmi, intel_hdmi and even intel_dp usage.
>>>
>>
>> hmmm I think I misread intel_dp_update_420(). I saw this is called after
>> HPD so I thought they unset ycbcr_420_allowed if VSC SDP is not
>> supported. But they have other DPCD checking there so anyway they will
>> fail this bridge_connector_init() model.
>>
>> But one argument which I can give in my defense is, lets say the sink
>> exposed YUV formats but did not support SDP, then atomic_check() will
>> keep failing or should keep failing. This will avoid this scenario. But
>> we can assume that would be a rogue sink.
> 
> This should be handled in DP's atomic_check. As usual, bonus point if
> this is done via helpers that can be reused by other platforms.
> 
>> I think we can pass a yuv_supported flag to msm_dp_modeset_init() and
>> set it to true from dpu_kms if catalog has CDM block and get rid of the
>> dp_panel_vsc_sdp_supported().
> 
> These are two different issues. CDM should be checked in PDU (whether
> the DPU can provide YUV data to the DP block).
> 

Yes, I found this issue while discussing this. We need to make this change.

>>
>> But that doesnt address the TODO you have pointed to. What is really the
>> expectation of the TODO? Do we need to pass a ycbcr_420_allowed flag to
>> drm_bridge_connector_init()?
> 
> Ugh. No. I was thinking about a `ycbcr420_allowed` flag in the struct
> drm_bridge (to follow existing interlace_allowed) flag. But, this
> might be not the best option. Each bridge can either pass through YUV
> data from the previous bridge or generate YCbCr data on its own. So in
> theory this demands two flags plus one flag for the encoder. Which
> might be an overkill, until we end up in a situation when the driver
> can not decide for the full bridge chain.
> 

Yes.

> So let's probably ignore the TODO for the purpose of this series. Just
> fix the usage of ycbcr420_allowed according to docs.
> 

Ack.

>>
>> That would need a tree wide cleanup and thats difficult to sign up for
>> in this series and I would not as well.
>>
>> One thing which I can suggest to be less intrusive is have a new API
>> called drm_bridge_connector_init_with_YUV() which looks something like
>> below:
>>
>> struct drm_connector *drm_bridge_connector_init_with_ycbcr_420(struct
>> drm_device *drm, struct drm_encoder *encoder)
>> {
>>          drm_bridge_connector_init();
>>          connector->ycbcr_420_allowed = true;
>> }
>>
>> But I don't know if the community would be interested in this idea or
>> would find that useful.
>>
>>>>>>             drm_dp_set_subconnector_property(dp->dp_display.connector,
>>>>>>                              connector_status_connected,
>>>>>>                              dp->panel->dpcd,
>>>>>>                              dp->panel->downstream_ports);
>>>>>> +    }
>>>>>>         edid = dp->panel->edid;
>>>>>
>>>
>>>
>>>
> 
> 
> 

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 14/17] drm/msm/dpu: modify encoder programming for CDM over DP
  2024-01-29  5:03             ` Abhinav Kumar
@ 2024-01-29  6:12               ` Dmitry Baryshkov
  2024-01-29  7:08                 ` Abhinav Kumar
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-29  6:12 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno

On Mon, 29 Jan 2024 at 07:03, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 1/28/2024 7:42 PM, Dmitry Baryshkov wrote:
> > On Mon, 29 Jan 2024 at 04:58, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >>
> >>
> >> On 1/27/2024 9:55 PM, Dmitry Baryshkov wrote:
> >>> On Sun, 28 Jan 2024 at 07:48, Paloma Arellano <quic_parellan@quicinc.com> wrote:
> >>>>
> >>>>
> >>>> On 1/25/2024 1:57 PM, Dmitry Baryshkov wrote:
> >>>>> On 25/01/2024 21:38, Paloma Arellano wrote:
> >>>>>> Adjust the encoder format programming in the case of video mode for DP
> >>>>>> to accommodate CDM related changes.
> >>>>>>
> >>>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >>>>>> ---
> >>>>>>     drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 16 +++++++++
> >>>>>>     drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |  8 +++++
> >>>>>>     .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 35 ++++++++++++++++---
> >>>>>>     drivers/gpu/drm/msm/dp/dp_display.c           | 12 +++++++
> >>>>>>     drivers/gpu/drm/msm/msm_drv.h                 |  9 ++++-
> >>>>>>     5 files changed, 75 insertions(+), 5 deletions(-)
> >>>>>>
> >>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >>>>>> index b0896814c1562..99ec53446ad21 100644
> >>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >>>>>> @@ -222,6 +222,22 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = {
> >>>>>>         15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10
> >>>>>>     };
> >>>>>>     +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
> >>>>>> const struct drm_display_mode *mode)
> >>>>>> +{
> >>>>>> +    const struct dpu_encoder_virt *dpu_enc;
> >>>>>> +    const struct msm_display_info *disp_info;
> >>>>>> +    struct msm_drm_private *priv;
> >>>>>> +
> >>>>>> +    dpu_enc = to_dpu_encoder_virt(drm_enc);
> >>>>>> +    disp_info = &dpu_enc->disp_info;
> >>>>>> +    priv = drm_enc->dev->dev_private;
> >>>>>> +
> >>>>>> +    if (disp_info->intf_type == INTF_DP &&
> >>>>>> + msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]],
> >>>>>> mode))
> >>>>>
> >>>>> This should not require interacting with DP. If we got here, we must
> >>>>> be sure that 4:2:0 is supported and can be configured.
> >>>> Ack. Will drop this function and only check for if the mode is YUV420.
> >>>>>
> >>>>>> +        return DRM_FORMAT_YUV420;
> >>>>>> +
> >>>>>> +    return DRM_FORMAT_RGB888;
> >>>>>> +}
> >>>>>>       bool dpu_encoder_is_widebus_enabled(const struct drm_encoder
> >>>>>> *drm_enc)
> >>>>>>     {
> >>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> >>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> >>>>>> index 7b4afa71f1f96..62255d0aa4487 100644
> >>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> >>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> >>>>>> @@ -162,6 +162,14 @@ int dpu_encoder_get_vsync_count(struct
> >>>>>> drm_encoder *drm_enc);
> >>>>>>      */
> >>>>>>     bool dpu_encoder_is_widebus_enabled(const struct drm_encoder
> >>>>>> *drm_enc);
> >>>>>>     +/**
> >>>>>> + * dpu_encoder_get_drm_fmt - return DRM fourcc format
> >>>>>> + * @drm_enc:    Pointer to previously created drm encoder structure
> >>>>>> + * @mode:    Corresponding drm_display_mode for dpu encoder
> >>>>>> + */
> >>>>>> +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
> >>>>>> +                const struct drm_display_mode *mode);
> >>>>>> +
> >>>>>>     /**
> >>>>>>      * dpu_encoder_get_crc_values_cnt - get number of physical encoders
> >>>>>> contained
> >>>>>>      *    in virtual encoder that can collect CRC values
> >>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >>>>>> index e284bf448bdda..a1dde0ff35dc8 100644
> >>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >>>>>> @@ -234,6 +234,7 @@ static void
> >>>>>> dpu_encoder_phys_vid_setup_timing_engine(
> >>>>>>     {
> >>>>>>         struct drm_display_mode mode;
> >>>>>>         struct dpu_hw_intf_timing_params timing_params = { 0 };
> >>>>>> +    struct dpu_hw_cdm *hw_cdm;
> >>>>>>         const struct dpu_format *fmt = NULL;
> >>>>>>         u32 fmt_fourcc = DRM_FORMAT_RGB888;
> >>>>>>         unsigned long lock_flags;
> >>>>>> @@ -254,17 +255,26 @@ static void
> >>>>>> dpu_encoder_phys_vid_setup_timing_engine(
> >>>>>>         DPU_DEBUG_VIDENC(phys_enc, "enabling mode:\n");
> >>>>>>         drm_mode_debug_printmodeline(&mode);
> >>>>>>     -    if (phys_enc->split_role != ENC_ROLE_SOLO) {
> >>>>>> +    hw_cdm = phys_enc->hw_cdm;
> >>>>>> +    if (hw_cdm) {
> >>>>>> +        intf_cfg.cdm = hw_cdm->idx;
> >>>>>> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent, &mode);
> >>>>>> +    }
> >>>>>> +
> >>>>>> +    if (phys_enc->split_role != ENC_ROLE_SOLO ||
> >>>>>> +        dpu_encoder_get_drm_fmt(phys_enc->parent, &mode) ==
> >>>>>> DRM_FORMAT_YUV420) {
> >>>>>>             mode.hdisplay >>= 1;
> >>>>>>             mode.htotal >>= 1;
> >>>>>>             mode.hsync_start >>= 1;
> >>>>>>             mode.hsync_end >>= 1;
> >>>>>> +        mode.hskew >>= 1;
> >>>>>
> >>>>> Separate patch.
> >>>> Ack.
> >>>>>
> >>>>>>               DPU_DEBUG_VIDENC(phys_enc,
> >>>>>> -            "split_role %d, halve horizontal %d %d %d %d\n",
> >>>>>> +            "split_role %d, halve horizontal %d %d %d %d %d\n",
> >>>>>>                 phys_enc->split_role,
> >>>>>>                 mode.hdisplay, mode.htotal,
> >>>>>> -            mode.hsync_start, mode.hsync_end);
> >>>>>> +            mode.hsync_start, mode.hsync_end,
> >>>>>> +            mode.hskew);
> >>>>>>         }
> >>>>>>           drm_mode_to_intf_timing_params(phys_enc, &mode, &timing_params);
> >>>>>> @@ -412,8 +422,15 @@ static int dpu_encoder_phys_vid_control_vblank_irq(
> >>>>>>     static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys
> >>>>>> *phys_enc)
> >>>>>>     {
> >>>>>>         struct dpu_hw_ctl *ctl;
> >>>>>> +    struct dpu_hw_cdm *hw_cdm;
> >>>>>> +    const struct dpu_format *fmt = NULL;
> >>>>>> +    u32 fmt_fourcc = DRM_FORMAT_RGB888;
> >>>>>>           ctl = phys_enc->hw_ctl;
> >>>>>> +    hw_cdm = phys_enc->hw_cdm;
> >>>>>> +    if (hw_cdm)
> >>>>>> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent,
> >>>>>> &phys_enc->cached_mode);
> >>>>>> +    fmt = dpu_get_dpu_format(fmt_fourcc);
> >>>>>>           DPU_DEBUG_VIDENC(phys_enc, "\n");
> >>>>>>     @@ -422,6 +439,8 @@ static void dpu_encoder_phys_vid_enable(struct
> >>>>>> dpu_encoder_phys *phys_enc)
> >>>>>>           dpu_encoder_helper_split_config(phys_enc,
> >>>>>> phys_enc->hw_intf->idx);
> >>>>>>     +    dpu_encoder_helper_phys_setup_cdm(phys_enc, fmt,
> >>>>>> CDM_CDWN_OUTPUT_HDMI);
> >>>>>
> >>>>> If there is no CDM, why do we need to call this?
> >>>> Inside of dpu_encoder_helper_phys_setup_cdm(), there's a check to see if
> >>>> there is a hw_cdm. If there is not, then it immediately exits the function.
> >>>>>
> >>>>>> +
> >>>>>>         dpu_encoder_phys_vid_setup_timing_engine(phys_enc);
> >>>>>>           /*
> >>>>>> @@ -437,7 +456,15 @@ static void dpu_encoder_phys_vid_enable(struct
> >>>>>> dpu_encoder_phys *phys_enc)
> >>>>>>         if (ctl->ops.update_pending_flush_merge_3d &&
> >>>>>> phys_enc->hw_pp->merge_3d)
> >>>>>>             ctl->ops.update_pending_flush_merge_3d(ctl,
> >>>>>> phys_enc->hw_pp->merge_3d->idx);
> >>>>>>     -    if (ctl->ops.update_pending_flush_periph &&
> >>>>>> phys_enc->hw_intf->cap->type == INTF_DP)
> >>>>>> +    if (ctl->ops.update_pending_flush_cdm && phys_enc->hw_cdm)
> >>>>>> +        ctl->ops.update_pending_flush_cdm(ctl, hw_cdm->idx);
> >>>>>> +
> >>>>>> +    /*
> >>>>>> +     * Peripheral flush must be updated whenever flushing SDP
> >>>>>> packets is needed.
> >>>>>> +     * SDP packets are required for any YUV format (YUV420, YUV422,
> >>>>>> YUV444).
> >>>>>> +     */
> >>>>>> +    if (ctl->ops.update_pending_flush_periph &&
> >>>>>> phys_enc->hw_intf->cap->type == INTF_DP &&
> >>>>>> +        phys_enc->hw_cdm)
> >>>>>>             ctl->ops.update_pending_flush_periph(ctl,
> >>>>>> phys_enc->hw_intf->idx);
> >>>>>
> >>>>> Should there be a flush if we are switching from YUV 420 to RGB mode?
> >>>> We only need to flush for the sdp packet, but for msa we do not need to
> >>>> flush.
> >>>
> >>> What about having SDP with RGB as colorimetry? In other words, if
> >>> there is a decision point, this one looks incorrect.
> >>>
> >>
> >> There are two ways to do it:
> >>
> >> 1) Use SDP for both RGB and YUV as that supports both. If we implement
> >> this policy, then what you are asking for is correct that we will need
> >> SDP even to switch back to RGB. But to implement this we will also need
> >> to have some sort of state management in the encoder layer about what is
> >> the current encoder fmt Vs what is the prev fmt and then trigger
> >> peripheral flush only during transitions from RGB to YUV and vice-versa
> >>
> >> 2) Use SDP only for YUV because MSA does not support YUV formats and use
> >> MSA for RGB
> >>
> >> We decided to implement (2) and there is no significant impact of
> >> switching between MSA and SDPs but state management becomes easier.
> >
> > Yes. However as you wrote, there might be other usecases concerning
> > SDP. Having this in mind, it sounds like the driver should decide
> > whether to flush peripheral at a different place (when the SDP
> > infoframe is being updated?). And the dpu_encoder_phys_vid_enable()
> > should use this previous decision. Maybe this should be a part of
> > msm_dp_ API, something like msm_dp_needs_peripheral_flush()?
> >
>
> Correct. The decision to flush peripheral or not certainly comes from
> the peripheral itself . In this case its DP.
>
> I think perhaps the usage of hw_cdm here makes it hard to understand
> that but the idea behind this was that in the change "drm/msm/dpu:
> reserve CDM blocks for DP if mode is YUV420 ", hw_cdm is assigned only
> if msm_dp_is_yuv_420_enabled() returns true.

Yes.

>
> So in some sense, the API you are asking for is already
> msm_dp_is_yuv_420_enabled() but we can rename that to
> msm_dp_needs_periph_flush().

No. This leaks details. We might need peripheral flush for other
reasons. So this decision should be made inside the DP driver.
BTW, is there a need to flush-peripheral each time the INTF gets
enabled? When some bits of configuration were updated (like SDP
infoframe or CDM config)?

>
> The issue here is the phys layer cannot call msm_dp_is_yuv_420_enabled()
> so its kind of round-about by checking hw_cdm.

Which maybe means that I should finish phys / encoder rework.

>
> The check is not entirely wrong because for DP, we need hw_cdm for all
> YUV formats and not just 420 but the relationship is maybe not clear but
> I thought the comment above that would help a bit:
>
> /*
>          * Peripheral flush must be updated whenever flushing SDP packets is
> needed.
>          * SDP packets are required for any YUV format (YUV420, YUV422, YUV444).
>          */
>
> The only other way I can think of is maybe we need to introduce a new
> phys variable called phys_enc->needs_update_periph_flush and we can set
> that in dpu_encoder.c as that can call msm_dp_needs_periph_flush().
>
> What do you think of this way?

Let me understand first the requirements for peripheral flush (see the
questions above).

>
> >>
> >>>>>
> >>>>> Also, I'd say, we should move update_pending_flush_periph invocation
> >>>>> to this patch.
> >>>> Ack
> >>>>>
> >>>>>>       skip_flush:
> >>>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
> >>>>>> b/drivers/gpu/drm/msm/dp/dp_display.c
> >>>>>> index 6d764f5b08727..4329435518351 100644
> >>>>>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> >>>>>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> >>>>>> @@ -1399,6 +1399,18 @@ void __exit msm_dp_unregister(void)
> >>>>>>         platform_driver_unregister(&dp_display_driver);
> >>>>>>     }
> >>>>>>     +bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
> >>>>>> +                   const struct drm_display_mode *mode)
> >>>>>> +{
> >>>>>> +    struct dp_display_private *dp;
> >>>>>> +    const struct drm_display_info *info;
> >>>>>> +
> >>>>>> +    dp = container_of(dp_display, struct dp_display_private,
> >>>>>> dp_display);
> >>>>>> +    info = &dp_display->connector->display_info;
> >>>>>> +
> >>>>>> +    return dp_panel_vsc_sdp_supported(dp->panel) &&
> >>>>>> drm_mode_is_420_only(info, mode);
> >>>>>
> >>>>> YUV 420 modes should be filtered out in mode_valid if VSC SDP is not
> >>>>> supported.
> >>>> Ack. Will change
> >>>>>
> >>>>>> +}
> >>>>>> +
> >>>>>>     bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)
> >>>>>>     {
> >>>>>>         struct dp_display_private *dp;
> >>>>>> diff --git a/drivers/gpu/drm/msm/msm_drv.h
> >>>>>> b/drivers/gpu/drm/msm/msm_drv.h
> >>>>>> index 16a7cbc0b7dd8..b9581bd934e9e 100644
> >>>>>> --- a/drivers/gpu/drm/msm/msm_drv.h
> >>>>>> +++ b/drivers/gpu/drm/msm/msm_drv.h
> >>>>>> @@ -387,7 +387,8 @@ void __exit msm_dp_unregister(void);
> >>>>>>     int msm_dp_modeset_init(struct msm_dp *dp_display, struct
> >>>>>> drm_device *dev,
> >>>>>>                  struct drm_encoder *encoder);
> >>>>>>     void msm_dp_snapshot(struct msm_disp_state *disp_state, struct
> >>>>>> msm_dp *dp_display);
> >>>>>> -
> >>>>>> +bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
> >>>>>> +                   const struct drm_display_mode *mode);
> >>>>>>     bool msm_dp_wide_bus_available(const struct msm_dp *dp_display);
> >>>>>>       #else
> >>>>>> @@ -409,6 +410,12 @@ static inline void msm_dp_snapshot(struct
> >>>>>> msm_disp_state *disp_state, struct msm
> >>>>>>     {
> >>>>>>     }
> >>>>>>     +static inline bool msm_dp_is_yuv_420_enabled(const struct msm_dp
> >>>>>> *dp_display,
> >>>>>> +                         const struct drm_display_mode *mode)
> >>>>>> +{
> >>>>>> +    return false;
> >>>>>> +}
> >>>>>> +
> >>>>>>     static inline bool msm_dp_wide_bus_available(const struct msm_dp
> >>>>>> *dp_display)
> >>>>>>     {
> >>>>>>         return false;
> >>>>>
> >>>
> >>>
> >>>
> >>> --
> >>> With best wishes
> >>> Dmitry
> >
> >
> >



-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 14/17] drm/msm/dpu: modify encoder programming for CDM over DP
  2024-01-29  6:12               ` Dmitry Baryshkov
@ 2024-01-29  7:08                 ` Abhinav Kumar
  2024-01-29 23:44                   ` Dmitry Baryshkov
  0 siblings, 1 reply; 95+ messages in thread
From: Abhinav Kumar @ 2024-01-29  7:08 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno



On 1/28/2024 10:12 PM, Dmitry Baryshkov wrote:
> On Mon, 29 Jan 2024 at 07:03, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 1/28/2024 7:42 PM, Dmitry Baryshkov wrote:
>>> On Mon, 29 Jan 2024 at 04:58, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>>>
>>>>
>>>>
>>>> On 1/27/2024 9:55 PM, Dmitry Baryshkov wrote:
>>>>> On Sun, 28 Jan 2024 at 07:48, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>>>>>>
>>>>>>
>>>>>> On 1/25/2024 1:57 PM, Dmitry Baryshkov wrote:
>>>>>>> On 25/01/2024 21:38, Paloma Arellano wrote:
>>>>>>>> Adjust the encoder format programming in the case of video mode for DP
>>>>>>>> to accommodate CDM related changes.
>>>>>>>>
>>>>>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>>>>>>> ---
>>>>>>>>      drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 16 +++++++++
>>>>>>>>      drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |  8 +++++
>>>>>>>>      .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 35 ++++++++++++++++---
>>>>>>>>      drivers/gpu/drm/msm/dp/dp_display.c           | 12 +++++++
>>>>>>>>      drivers/gpu/drm/msm/msm_drv.h                 |  9 ++++-
>>>>>>>>      5 files changed, 75 insertions(+), 5 deletions(-)
>>>>>>>>
>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>>>> index b0896814c1562..99ec53446ad21 100644
>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>>>> @@ -222,6 +222,22 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = {
>>>>>>>>          15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10
>>>>>>>>      };
>>>>>>>>      +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
>>>>>>>> const struct drm_display_mode *mode)
>>>>>>>> +{
>>>>>>>> +    const struct dpu_encoder_virt *dpu_enc;
>>>>>>>> +    const struct msm_display_info *disp_info;
>>>>>>>> +    struct msm_drm_private *priv;
>>>>>>>> +
>>>>>>>> +    dpu_enc = to_dpu_encoder_virt(drm_enc);
>>>>>>>> +    disp_info = &dpu_enc->disp_info;
>>>>>>>> +    priv = drm_enc->dev->dev_private;
>>>>>>>> +
>>>>>>>> +    if (disp_info->intf_type == INTF_DP &&
>>>>>>>> + msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]],
>>>>>>>> mode))
>>>>>>>
>>>>>>> This should not require interacting with DP. If we got here, we must
>>>>>>> be sure that 4:2:0 is supported and can be configured.
>>>>>> Ack. Will drop this function and only check for if the mode is YUV420.
>>>>>>>
>>>>>>>> +        return DRM_FORMAT_YUV420;
>>>>>>>> +
>>>>>>>> +    return DRM_FORMAT_RGB888;
>>>>>>>> +}
>>>>>>>>        bool dpu_encoder_is_widebus_enabled(const struct drm_encoder
>>>>>>>> *drm_enc)
>>>>>>>>      {
>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>>>>>>>> index 7b4afa71f1f96..62255d0aa4487 100644
>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>>>>>>>> @@ -162,6 +162,14 @@ int dpu_encoder_get_vsync_count(struct
>>>>>>>> drm_encoder *drm_enc);
>>>>>>>>       */
>>>>>>>>      bool dpu_encoder_is_widebus_enabled(const struct drm_encoder
>>>>>>>> *drm_enc);
>>>>>>>>      +/**
>>>>>>>> + * dpu_encoder_get_drm_fmt - return DRM fourcc format
>>>>>>>> + * @drm_enc:    Pointer to previously created drm encoder structure
>>>>>>>> + * @mode:    Corresponding drm_display_mode for dpu encoder
>>>>>>>> + */
>>>>>>>> +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
>>>>>>>> +                const struct drm_display_mode *mode);
>>>>>>>> +
>>>>>>>>      /**
>>>>>>>>       * dpu_encoder_get_crc_values_cnt - get number of physical encoders
>>>>>>>> contained
>>>>>>>>       *    in virtual encoder that can collect CRC values
>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>>>>>> index e284bf448bdda..a1dde0ff35dc8 100644
>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>>>>>> @@ -234,6 +234,7 @@ static void
>>>>>>>> dpu_encoder_phys_vid_setup_timing_engine(
>>>>>>>>      {
>>>>>>>>          struct drm_display_mode mode;
>>>>>>>>          struct dpu_hw_intf_timing_params timing_params = { 0 };
>>>>>>>> +    struct dpu_hw_cdm *hw_cdm;
>>>>>>>>          const struct dpu_format *fmt = NULL;
>>>>>>>>          u32 fmt_fourcc = DRM_FORMAT_RGB888;
>>>>>>>>          unsigned long lock_flags;
>>>>>>>> @@ -254,17 +255,26 @@ static void
>>>>>>>> dpu_encoder_phys_vid_setup_timing_engine(
>>>>>>>>          DPU_DEBUG_VIDENC(phys_enc, "enabling mode:\n");
>>>>>>>>          drm_mode_debug_printmodeline(&mode);
>>>>>>>>      -    if (phys_enc->split_role != ENC_ROLE_SOLO) {
>>>>>>>> +    hw_cdm = phys_enc->hw_cdm;
>>>>>>>> +    if (hw_cdm) {
>>>>>>>> +        intf_cfg.cdm = hw_cdm->idx;
>>>>>>>> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent, &mode);
>>>>>>>> +    }
>>>>>>>> +
>>>>>>>> +    if (phys_enc->split_role != ENC_ROLE_SOLO ||
>>>>>>>> +        dpu_encoder_get_drm_fmt(phys_enc->parent, &mode) ==
>>>>>>>> DRM_FORMAT_YUV420) {
>>>>>>>>              mode.hdisplay >>= 1;
>>>>>>>>              mode.htotal >>= 1;
>>>>>>>>              mode.hsync_start >>= 1;
>>>>>>>>              mode.hsync_end >>= 1;
>>>>>>>> +        mode.hskew >>= 1;
>>>>>>>
>>>>>>> Separate patch.
>>>>>> Ack.
>>>>>>>
>>>>>>>>                DPU_DEBUG_VIDENC(phys_enc,
>>>>>>>> -            "split_role %d, halve horizontal %d %d %d %d\n",
>>>>>>>> +            "split_role %d, halve horizontal %d %d %d %d %d\n",
>>>>>>>>                  phys_enc->split_role,
>>>>>>>>                  mode.hdisplay, mode.htotal,
>>>>>>>> -            mode.hsync_start, mode.hsync_end);
>>>>>>>> +            mode.hsync_start, mode.hsync_end,
>>>>>>>> +            mode.hskew);
>>>>>>>>          }
>>>>>>>>            drm_mode_to_intf_timing_params(phys_enc, &mode, &timing_params);
>>>>>>>> @@ -412,8 +422,15 @@ static int dpu_encoder_phys_vid_control_vblank_irq(
>>>>>>>>      static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys
>>>>>>>> *phys_enc)
>>>>>>>>      {
>>>>>>>>          struct dpu_hw_ctl *ctl;
>>>>>>>> +    struct dpu_hw_cdm *hw_cdm;
>>>>>>>> +    const struct dpu_format *fmt = NULL;
>>>>>>>> +    u32 fmt_fourcc = DRM_FORMAT_RGB888;
>>>>>>>>            ctl = phys_enc->hw_ctl;
>>>>>>>> +    hw_cdm = phys_enc->hw_cdm;
>>>>>>>> +    if (hw_cdm)
>>>>>>>> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent,
>>>>>>>> &phys_enc->cached_mode);
>>>>>>>> +    fmt = dpu_get_dpu_format(fmt_fourcc);
>>>>>>>>            DPU_DEBUG_VIDENC(phys_enc, "\n");
>>>>>>>>      @@ -422,6 +439,8 @@ static void dpu_encoder_phys_vid_enable(struct
>>>>>>>> dpu_encoder_phys *phys_enc)
>>>>>>>>            dpu_encoder_helper_split_config(phys_enc,
>>>>>>>> phys_enc->hw_intf->idx);
>>>>>>>>      +    dpu_encoder_helper_phys_setup_cdm(phys_enc, fmt,
>>>>>>>> CDM_CDWN_OUTPUT_HDMI);
>>>>>>>
>>>>>>> If there is no CDM, why do we need to call this?
>>>>>> Inside of dpu_encoder_helper_phys_setup_cdm(), there's a check to see if
>>>>>> there is a hw_cdm. If there is not, then it immediately exits the function.
>>>>>>>
>>>>>>>> +
>>>>>>>>          dpu_encoder_phys_vid_setup_timing_engine(phys_enc);
>>>>>>>>            /*
>>>>>>>> @@ -437,7 +456,15 @@ static void dpu_encoder_phys_vid_enable(struct
>>>>>>>> dpu_encoder_phys *phys_enc)
>>>>>>>>          if (ctl->ops.update_pending_flush_merge_3d &&
>>>>>>>> phys_enc->hw_pp->merge_3d)
>>>>>>>>              ctl->ops.update_pending_flush_merge_3d(ctl,
>>>>>>>> phys_enc->hw_pp->merge_3d->idx);
>>>>>>>>      -    if (ctl->ops.update_pending_flush_periph &&
>>>>>>>> phys_enc->hw_intf->cap->type == INTF_DP)
>>>>>>>> +    if (ctl->ops.update_pending_flush_cdm && phys_enc->hw_cdm)
>>>>>>>> +        ctl->ops.update_pending_flush_cdm(ctl, hw_cdm->idx);
>>>>>>>> +
>>>>>>>> +    /*
>>>>>>>> +     * Peripheral flush must be updated whenever flushing SDP
>>>>>>>> packets is needed.
>>>>>>>> +     * SDP packets are required for any YUV format (YUV420, YUV422,
>>>>>>>> YUV444).
>>>>>>>> +     */
>>>>>>>> +    if (ctl->ops.update_pending_flush_periph &&
>>>>>>>> phys_enc->hw_intf->cap->type == INTF_DP &&
>>>>>>>> +        phys_enc->hw_cdm)
>>>>>>>>              ctl->ops.update_pending_flush_periph(ctl,
>>>>>>>> phys_enc->hw_intf->idx);
>>>>>>>
>>>>>>> Should there be a flush if we are switching from YUV 420 to RGB mode?
>>>>>> We only need to flush for the sdp packet, but for msa we do not need to
>>>>>> flush.
>>>>>
>>>>> What about having SDP with RGB as colorimetry? In other words, if
>>>>> there is a decision point, this one looks incorrect.
>>>>>
>>>>
>>>> There are two ways to do it:
>>>>
>>>> 1) Use SDP for both RGB and YUV as that supports both. If we implement
>>>> this policy, then what you are asking for is correct that we will need
>>>> SDP even to switch back to RGB. But to implement this we will also need
>>>> to have some sort of state management in the encoder layer about what is
>>>> the current encoder fmt Vs what is the prev fmt and then trigger
>>>> peripheral flush only during transitions from RGB to YUV and vice-versa
>>>>
>>>> 2) Use SDP only for YUV because MSA does not support YUV formats and use
>>>> MSA for RGB
>>>>
>>>> We decided to implement (2) and there is no significant impact of
>>>> switching between MSA and SDPs but state management becomes easier.
>>>
>>> Yes. However as you wrote, there might be other usecases concerning
>>> SDP. Having this in mind, it sounds like the driver should decide
>>> whether to flush peripheral at a different place (when the SDP
>>> infoframe is being updated?). And the dpu_encoder_phys_vid_enable()
>>> should use this previous decision. Maybe this should be a part of
>>> msm_dp_ API, something like msm_dp_needs_peripheral_flush()?
>>>
>>
>> Correct. The decision to flush peripheral or not certainly comes from
>> the peripheral itself . In this case its DP.
>>
>> I think perhaps the usage of hw_cdm here makes it hard to understand
>> that but the idea behind this was that in the change "drm/msm/dpu:
>> reserve CDM blocks for DP if mode is YUV420 ", hw_cdm is assigned only
>> if msm_dp_is_yuv_420_enabled() returns true.
> 
> Yes.
> 
>>
>> So in some sense, the API you are asking for is already
>> msm_dp_is_yuv_420_enabled() but we can rename that to
>> msm_dp_needs_periph_flush().
> 
> No. This leaks details. We might need peripheral flush for other
> reasons. So this decision should be made inside the DP driver.
> BTW, is there a need to flush-peripheral each time the INTF gets
> enabled? When some bits of configuration were updated (like SDP
> infoframe or CDM config)?
> 

Not really leaking any details. Interface decides when DPU's flush bit 
needs to be invoked. All the conditions needing the flush can be 
absorbed within msm_dp_needs_periph_flush() which will be within DP 
driver. So I dont see any issue with that.

The peripheral flush needs to be invoked whenever SDP/PPS packets need 
to be sent out at the very least. Those are the two main use-cases so far.

Not necessarily each time the INTF is enabled.

But ....

For PPS, we would typically enable DSC from the first frame itself and 
we dont support dynamically turning DSC ON/OFF so its a fair assumption 
that we need to the peripheral flush for DSC only during enable.

For SDP, so today we enforce a modeset when we switch from a case of 
needing cdm / not needing cdm and vice-versa. So even this use-case 
should be accompanied by a disable()/enable().

So are you suggesting that we unconditionally just do peripheral_flush 
from enable()?

I need to do some checking but maybe ....

>>
>> The issue here is the phys layer cannot call msm_dp_is_yuv_420_enabled()
>> so its kind of round-about by checking hw_cdm.
> 
> Which maybe means that I should finish phys / encoder rework.
> 

Ugh no. Not another rework just for this.

>>
>> The check is not entirely wrong because for DP, we need hw_cdm for all
>> YUV formats and not just 420 but the relationship is maybe not clear but
>> I thought the comment above that would help a bit:
>>
>> /*
>>           * Peripheral flush must be updated whenever flushing SDP packets is
>> needed.
>>           * SDP packets are required for any YUV format (YUV420, YUV422, YUV444).
>>           */
>>
>> The only other way I can think of is maybe we need to introduce a new
>> phys variable called phys_enc->needs_update_periph_flush and we can set
>> that in dpu_encoder.c as that can call msm_dp_needs_periph_flush().
>>
>> What do you think of this way?
> 
> Let me understand first the requirements for peripheral flush (see the
> questions above).
> 
>>
>>>>
>>>>>>>
>>>>>>> Also, I'd say, we should move update_pending_flush_periph invocation
>>>>>>> to this patch.
>>>>>> Ack
>>>>>>>
>>>>>>>>        skip_flush:
>>>>>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
>>>>>>>> b/drivers/gpu/drm/msm/dp/dp_display.c
>>>>>>>> index 6d764f5b08727..4329435518351 100644
>>>>>>>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
>>>>>>>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
>>>>>>>> @@ -1399,6 +1399,18 @@ void __exit msm_dp_unregister(void)
>>>>>>>>          platform_driver_unregister(&dp_display_driver);
>>>>>>>>      }
>>>>>>>>      +bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
>>>>>>>> +                   const struct drm_display_mode *mode)
>>>>>>>> +{
>>>>>>>> +    struct dp_display_private *dp;
>>>>>>>> +    const struct drm_display_info *info;
>>>>>>>> +
>>>>>>>> +    dp = container_of(dp_display, struct dp_display_private,
>>>>>>>> dp_display);
>>>>>>>> +    info = &dp_display->connector->display_info;
>>>>>>>> +
>>>>>>>> +    return dp_panel_vsc_sdp_supported(dp->panel) &&
>>>>>>>> drm_mode_is_420_only(info, mode);
>>>>>>>
>>>>>>> YUV 420 modes should be filtered out in mode_valid if VSC SDP is not
>>>>>>> supported.
>>>>>> Ack. Will change
>>>>>>>
>>>>>>>> +}
>>>>>>>> +
>>>>>>>>      bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)
>>>>>>>>      {
>>>>>>>>          struct dp_display_private *dp;
>>>>>>>> diff --git a/drivers/gpu/drm/msm/msm_drv.h
>>>>>>>> b/drivers/gpu/drm/msm/msm_drv.h
>>>>>>>> index 16a7cbc0b7dd8..b9581bd934e9e 100644
>>>>>>>> --- a/drivers/gpu/drm/msm/msm_drv.h
>>>>>>>> +++ b/drivers/gpu/drm/msm/msm_drv.h
>>>>>>>> @@ -387,7 +387,8 @@ void __exit msm_dp_unregister(void);
>>>>>>>>      int msm_dp_modeset_init(struct msm_dp *dp_display, struct
>>>>>>>> drm_device *dev,
>>>>>>>>                   struct drm_encoder *encoder);
>>>>>>>>      void msm_dp_snapshot(struct msm_disp_state *disp_state, struct
>>>>>>>> msm_dp *dp_display);
>>>>>>>> -
>>>>>>>> +bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
>>>>>>>> +                   const struct drm_display_mode *mode);
>>>>>>>>      bool msm_dp_wide_bus_available(const struct msm_dp *dp_display);
>>>>>>>>        #else
>>>>>>>> @@ -409,6 +410,12 @@ static inline void msm_dp_snapshot(struct
>>>>>>>> msm_disp_state *disp_state, struct msm
>>>>>>>>      {
>>>>>>>>      }
>>>>>>>>      +static inline bool msm_dp_is_yuv_420_enabled(const struct msm_dp
>>>>>>>> *dp_display,
>>>>>>>> +                         const struct drm_display_mode *mode)
>>>>>>>> +{
>>>>>>>> +    return false;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>>      static inline bool msm_dp_wide_bus_available(const struct msm_dp
>>>>>>>> *dp_display)
>>>>>>>>      {
>>>>>>>>          return false;
>>>>>>>
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> With best wishes
>>>>> Dmitry
>>>
>>>
>>>
> 
> 
> 

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 01/17] drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP
  2024-01-29  5:12                 ` Dmitry Baryshkov
@ 2024-01-29 23:06                   ` Paloma Arellano
  0 siblings, 0 replies; 95+ messages in thread
From: Paloma Arellano @ 2024-01-29 23:06 UTC (permalink / raw)
  To: Dmitry Baryshkov, Abhinav Kumar
  Cc: neil.armstrong, linux-arm-msm, dri-devel, swboyd, seanpaul,
	marijn.suijten, quic_jesszhan, quic_khsieh, freedreno


On 1/28/2024 9:12 PM, Dmitry Baryshkov wrote:
> On Mon, 29 Jan 2024 at 06:33, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>> On 1/28/2024 8:12 PM, Dmitry Baryshkov wrote:
>>> On Mon, 29 Jan 2024 at 06:01, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>>>
>>>>
>>>> On 1/28/2024 7:23 PM, Dmitry Baryshkov wrote:
>>>>> On Mon, 29 Jan 2024 at 05:06, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>>>>>
>>>>>>
>>>>>> On 1/26/2024 4:39 PM, Paloma Arellano wrote:
>>>>>>> On 1/25/2024 1:14 PM, Dmitry Baryshkov wrote:
>>>>>>>> On 25/01/2024 21:38, Paloma Arellano wrote:
>>>>>>>>> Generalize dpu_encoder_helper_phys_setup_cdm to be compatible with DP.
>>>>>>>>>
>>>>>>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>>>>>>>> ---
>>>>>>>>>      .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  4 +--
>>>>>>>>>      .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 31 ++++++++++---------
>>>>>>>>>      2 files changed, 18 insertions(+), 17 deletions(-)
>>>>>>>>>
>>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>>>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>>>>>>>>> index 993f263433314..37ac385727c3b 100644
>>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>>>>>>>>> @@ -153,6 +153,7 @@ enum dpu_intr_idx {
>>>>>>>>>       * @hw_intf:        Hardware interface to the intf registers
>>>>>>>>>       * @hw_wb:        Hardware interface to the wb registers
>>>>>>>>>       * @hw_cdm:        Hardware interface to the CDM registers
>>>>>>>>> + * @cdm_cfg:    CDM block config needed to store WB/DP block's CDM
>>>>>>>>> configuration
>>>>>>>> Please realign the description.
>>>>>>> Ack
>>>>>>>>>       * @dpu_kms:        Pointer to the dpu_kms top level
>>>>>>>>>       * @cached_mode:    DRM mode cached at mode_set time, acted on in
>>>>>>>>> enable
>>>>>>>>>       * @vblank_ctl_lock:    Vblank ctl mutex lock to protect
>>>>>>>>> vblank_refcount
>>>>>>>>> @@ -183,6 +184,7 @@ struct dpu_encoder_phys {
>>>>>>>>>          struct dpu_hw_intf *hw_intf;
>>>>>>>>>          struct dpu_hw_wb *hw_wb;
>>>>>>>>>          struct dpu_hw_cdm *hw_cdm;
>>>>>>>>> +    struct dpu_hw_cdm_cfg cdm_cfg;
>>>>>>>> It might be slightly better to move it after all the pointers, so
>>>>>>>> after the dpu_kms.
>>>>>>> Ack
>>>>>>>>>          struct dpu_kms *dpu_kms;
>>>>>>>>>          struct drm_display_mode cached_mode;
>>>>>>>>>          struct mutex vblank_ctl_lock;
>>>>>>>>> @@ -213,7 +215,6 @@ static inline int
>>>>>>>>> dpu_encoder_phys_inc_pending(struct dpu_encoder_phys *phys)
>>>>>>>>>       * @wbirq_refcount:     Reference count of writeback interrupt
>>>>>>>>>       * @wb_done_timeout_cnt: number of wb done irq timeout errors
>>>>>>>>>       * @wb_cfg:  writeback block config to store fb related details
>>>>>>>>> - * @cdm_cfg: cdm block config needed to store writeback block's CDM
>>>>>>>>> configuration
>>>>>>>>>       * @wb_conn: backpointer to writeback connector
>>>>>>>>>       * @wb_job: backpointer to current writeback job
>>>>>>>>>       * @dest:   dpu buffer layout for current writeback output buffer
>>>>>>>>> @@ -223,7 +224,6 @@ struct dpu_encoder_phys_wb {
>>>>>>>>>          atomic_t wbirq_refcount;
>>>>>>>>>          int wb_done_timeout_cnt;
>>>>>>>>>          struct dpu_hw_wb_cfg wb_cfg;
>>>>>>>>> -    struct dpu_hw_cdm_cfg cdm_cfg;
>>>>>>>>>          struct drm_writeback_connector *wb_conn;
>>>>>>>>>          struct drm_writeback_job *wb_job;
>>>>>>>>>          struct dpu_hw_fmt_layout dest;
>>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>>>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>>>>>>>>> index 4cd2d9e3131a4..072fc6950e496 100644
>>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
>>>>>>>>> @@ -269,28 +269,21 @@ static void
>>>>>>>>> dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
>>>>>>>>>       *                                     This API does not handle
>>>>>>>>> DPU_CHROMA_H1V2.
>>>>>>>>>       * @phys_enc:Pointer to physical encoder
>>>>>>>>>       */
>>>>>>>>> -static void dpu_encoder_helper_phys_setup_cdm(struct
>>>>>>>>> dpu_encoder_phys *phys_enc)
>>>>>>>>> +static void dpu_encoder_helper_phys_setup_cdm(struct
>>>>>>>>> dpu_encoder_phys *phys_enc,
>>>>>>>>> +                          const struct dpu_format *dpu_fmt,
>>>>>>>>> +                          u32 output_type)
>>>>>>>>>      {
>>>>>>>>>          struct dpu_hw_cdm *hw_cdm;
>>>>>>>>>          struct dpu_hw_cdm_cfg *cdm_cfg;
>>>>>>>>>          struct dpu_hw_pingpong *hw_pp;
>>>>>>>>> -    struct dpu_encoder_phys_wb *wb_enc;
>>>>>>>>> -    const struct msm_format *format;
>>>>>>>>> -    const struct dpu_format *dpu_fmt;
>>>>>>>>> -    struct drm_writeback_job *wb_job;
>>>>>>>>>          int ret;
>>>>>>>>>            if (!phys_enc)
>>>>>>>>>              return;
>>>>>>>>>      -    wb_enc = to_dpu_encoder_phys_wb(phys_enc);
>>>>>>>>> -    cdm_cfg = &wb_enc->cdm_cfg;
>>>>>>>>> +    cdm_cfg = &phys_enc->cdm_cfg;
>>>>>>>>>          hw_pp = phys_enc->hw_pp;
>>>>>>>>>          hw_cdm = phys_enc->hw_cdm;
>>>>>>>>> -    wb_job = wb_enc->wb_job;
>>>>>>>>> -
>>>>>>>>> -    format = msm_framebuffer_format(wb_enc->wb_job->fb);
>>>>>>>>> -    dpu_fmt = dpu_get_dpu_format_ext(format->pixel_format,
>>>>>>>>> wb_job->fb->modifier);
>>>>>>>>>            if (!hw_cdm)
>>>>>>>>>              return;
>>>>>>>>> @@ -306,10 +299,10 @@ static void
>>>>>>>>> dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
>>>>>>>>>            memset(cdm_cfg, 0, sizeof(struct dpu_hw_cdm_cfg));
>>>>>>>>>      -    cdm_cfg->output_width = wb_job->fb->width;
>>>>>>>>> -    cdm_cfg->output_height = wb_job->fb->height;
>>>>>>>>> +    cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
>>>>>>>>> +    cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
>>>>>>>> This is a semantic change. Instead of passing the FB size, this passes
>>>>>>>> the mode dimensions. They are not guaranteed to be the same,
>>>>>>>> especially for the WB case.
>>>>>>>>
>>>>>> The WB job is storing the output FB of WB. I cannot think of a use-case
>>>>>> where this cannot match the current mode programmed to the WB encoder.
>>>>>>
>>>>>> Yes, if it was the drm_plane's FB, then it cannot be guaranteed as the
>>>>>> plane can scale the contents but here thats not the case. Here its the
>>>>>> output FB of WB.
>>>>> Is it a part of WB uAPI, to have the FB dimensions equal to mode
>>>>> dimensions? Or is it just our current limitation? I can easily imagine
>>>>> WB outputting data to a part of the FB (just like we can clip FB using
>>>>> plane's clip rectangle).
>>>>>
>>>>> This boils down to a question, whether CDM should be setup in terms of
>>>>> actual output date or the physical memory buffer parameters. I suspect
>>>>> the former is the case (which makes this change correct). But it
>>>>> either should be described in the commit message or (even better)
>>>>> split to a separate commit.
>>>>>
>>>> I would say its a combination of both today.
>>>>
>>>> The way I would look at it is even if WB crops a certain section of FB,
>>>> that will not change the FB size. FB size of WB should match the rest of
>>>> the DRM pipeline (the mode programmed to the CRTC/encoder). If WB
>>>> decides to write to only a small section of FB (cropping), then we need
>>>> another WB property like CROP_ROI so that we can program the WB to only
>>>> write to a small section of the programmed FB. So in some sense, there
>>>> is no such support in DRM UAPI today. Hence the FB of WB is the full
>>>> mode of the WB.
>>>    I'd say, CROP_ROI can refer to cropping of the image source (esp. in
>>> the cloned output case). For writing to the part of the FB there can
>>> be DST_X/_Y/_W/_H properties. But this becomes off-topic.
>>>
>>>> CDM is before WB so follows the rest of the pipeline that is whatever
>>>> the data feeding it was programmed to.
>>> Yes. So the change is correct, but it should be split or documented
>>> properly. I prefer the first option.
>>>
>> Ok just to clarify you prefer below part of the change to be moved to
>> its own commit right?
>>
>> -    cdm_cfg->output_width = wb_job->fb->width;
>> -    cdm_cfg->output_height = wb_job->fb->height;
>> +    cdm_cfg->output_width = phys_enc->cached_mode.hdisplay;
>> +    cdm_cfg->output_height = phys_enc->cached_mode.vdisplay;
>>
>> If so, ack.
> Yes.
Ack will change in next version.
>
>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 05/17] drm/msm/dp: add an API to indicate if sink supports VSC SDP
  2024-01-27  2:40       ` Dmitry Baryshkov
  2024-01-27  3:57         ` Abhinav Kumar
@ 2024-01-29 23:20         ` Paloma Arellano
  1 sibling, 0 replies; 95+ messages in thread
From: Paloma Arellano @ 2024-01-29 23:20 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: neil.armstrong, linux-arm-msm, quic_abhinavk, dri-devel, swboyd,
	seanpaul, marijn.suijten, quic_jesszhan, quic_khsieh, freedreno


On 1/26/2024 6:40 PM, Dmitry Baryshkov wrote:
> On Sat, 27 Jan 2024 at 02:58, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>>
>> On 1/25/2024 1:23 PM, Dmitry Baryshkov wrote:
>>> On 25/01/2024 21:38, Paloma Arellano wrote:
>>>> YUV420 format is supported only in the VSC SDP packet and not through
>>>> MSA. Hence add an API which indicates the sink support which can be used
>>>> by the rest of the DP programming.
>>> This API ideally should go to drm/display/drm_dp_helper.c
>> I'm not familiar how other vendors are checking if VSC SDP is supported.
>> So in moving this API, I'm going to let the other vendors make the
>> changes themselves.
> Let me show it for you:
>
> bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp)
> {
>          u8 dprx = 0;
>
>          if (drm_dp_dpcd_readb(&intel_dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST,
>                                &dprx) != 1)
>                  return false;
>          return dprx & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED;
> }
>
>
>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>>> ---
>>>>    drivers/gpu/drm/msm/dp/dp_display.c |  3 ++-
>>>>    drivers/gpu/drm/msm/dp/dp_panel.c   | 35 +++++++++++++++++++++++++----
>>>>    drivers/gpu/drm/msm/dp/dp_panel.h   |  1 +
>>>>    3 files changed, 34 insertions(+), 5 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
>>>> b/drivers/gpu/drm/msm/dp/dp_display.c
>>>> index ddac55f45a722..f6b3b6ca242f8 100644
>>>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
>>>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
>>>> @@ -1617,7 +1617,8 @@ void dp_bridge_mode_set(struct drm_bridge
>>>> *drm_bridge,
>>>>            !!(dp_display->dp_mode.drm_mode.flags & DRM_MODE_FLAG_NHSYNC);
>>>>          dp_display->dp_mode.out_fmt_is_yuv_420 =
>>>> - drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode);
>>>> + drm_mode_is_420_only(&dp->connector->display_info, adjusted_mode) &&
>>>> +        dp_panel_vsc_sdp_supported(dp_display->panel);
>>>>          /* populate wide_bus_support to different layers */
>>>>        dp_display->ctrl->wide_bus_en =
>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c
>>>> b/drivers/gpu/drm/msm/dp/dp_panel.c
>>>> index 127f6af995cd1..af7820b6d35ec 100644
>>>> --- a/drivers/gpu/drm/msm/dp/dp_panel.c
>>>> +++ b/drivers/gpu/drm/msm/dp/dp_panel.c
>>>> @@ -17,6 +17,9 @@ struct dp_panel_private {
>>>>        struct dp_link *link;
>>>>        struct dp_catalog *catalog;
>>>>        bool panel_on;
>>>> +    bool vsc_supported;
>>>> +    u8 major;
>>>> +    u8 minor;
>>>>    };
>>>>      static void dp_panel_read_psr_cap(struct dp_panel_private *panel)
>>>> @@ -43,9 +46,10 @@ static void dp_panel_read_psr_cap(struct
>>>> dp_panel_private *panel)
>>>>    static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
>>>>    {
>>>>        int rc;
>>>> +    ssize_t rlen;
>>>>        struct dp_panel_private *panel;
>>>>        struct dp_link_info *link_info;
>>>> -    u8 *dpcd, major, minor;
>>>> +    u8 *dpcd, rx_feature;
>>>>          panel = container_of(dp_panel, struct dp_panel_private,
>>>> dp_panel);
>>>>        dpcd = dp_panel->dpcd;
>>>> @@ -53,10 +57,19 @@ static int dp_panel_read_dpcd(struct dp_panel
>>>> *dp_panel)
>>>>        if (rc)
>>>>            return rc;
>>>>    +    rlen = drm_dp_dpcd_read(panel->aux,
>>>> DP_DPRX_FEATURE_ENUMERATION_LIST, &rx_feature, 1);
>>>> +    if (rlen != 1) {
>>>> +        panel->vsc_supported = false;
>>>> +        pr_debug("failed to read DP_DPRX_FEATURE_ENUMERATION_LIST\n");
>>>> +    } else {
>>>> +        panel->vsc_supported = !!(rx_feature &
>>>> DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED);
>>>> +        pr_debug("vsc=%d\n", panel->vsc_supported);
>>>> +    }
>>>> +
>>>>        link_info = &dp_panel->link_info;
>>>>        link_info->revision = dpcd[DP_DPCD_REV];
>>>> -    major = (link_info->revision >> 4) & 0x0f;
>>>> -    minor = link_info->revision & 0x0f;
>>>> +    panel->major = (link_info->revision >> 4) & 0x0f;
>>>> +    panel->minor = link_info->revision & 0x0f;
>>>>          link_info->rate = drm_dp_max_link_rate(dpcd);
>>>>        link_info->num_lanes = drm_dp_max_lane_count(dpcd);
>>>> @@ -69,7 +82,7 @@ static int dp_panel_read_dpcd(struct dp_panel
>>>> *dp_panel)
>>>>        if (link_info->rate > dp_panel->max_dp_link_rate)
>>>>            link_info->rate = dp_panel->max_dp_link_rate;
>>>>    -    drm_dbg_dp(panel->drm_dev, "version: %d.%d\n", major, minor);
>>>> +    drm_dbg_dp(panel->drm_dev, "version: %d.%d\n", panel->major,
>>>> panel->minor);
>>>>        drm_dbg_dp(panel->drm_dev, "link_rate=%d\n", link_info->rate);
>>>>        drm_dbg_dp(panel->drm_dev, "lane_count=%d\n",
>>>> link_info->num_lanes);
>>>>    @@ -280,6 +293,20 @@ void dp_panel_tpg_config(struct dp_panel
>>>> *dp_panel, bool enable)
>>>>        dp_catalog_panel_tpg_enable(catalog,
>>>> &panel->dp_panel.dp_mode.drm_mode);
>>>>    }
>>>>    +bool dp_panel_vsc_sdp_supported(struct dp_panel *dp_panel)
>>>> +{
>>>> +    struct dp_panel_private *panel;
>>>> +
>>>> +    if (!dp_panel) {
>>>> +        pr_err("invalid input\n");
>>>> +        return false;
>>>> +    }
>>>> +
>>>> +    panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
>>>> +
>>>> +    return panel->major >= 1 && panel->minor >= 3 &&
>>>> panel->vsc_supported;
> Anyway, this check is incorrect. Please compare the whole revision
> against DP_DPCD_REV_13 instead of doing a maj/min comparison.
Ack
>
>>>> +}
>>>> +
>>>>    void dp_panel_dump_regs(struct dp_panel *dp_panel)
>>>>    {
>>>>        struct dp_catalog *catalog;
>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h
>>>> b/drivers/gpu/drm/msm/dp/dp_panel.h
>>>> index 6ec68be9f2366..590eca5ce304b 100644
>>>> --- a/drivers/gpu/drm/msm/dp/dp_panel.h
>>>> +++ b/drivers/gpu/drm/msm/dp/dp_panel.h
>>>> @@ -66,6 +66,7 @@ int dp_panel_get_modes(struct dp_panel *dp_panel,
>>>>            struct drm_connector *connector);
>>>>    void dp_panel_handle_sink_request(struct dp_panel *dp_panel);
>>>>    void dp_panel_tpg_config(struct dp_panel *dp_panel, bool enable);
>>>> +bool dp_panel_vsc_sdp_supported(struct dp_panel *dp_panel);
>>>>      /**
>>>>     * is_link_rate_valid() - validates the link rate
>
>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 14/17] drm/msm/dpu: modify encoder programming for CDM over DP
  2024-01-29  7:08                 ` Abhinav Kumar
@ 2024-01-29 23:44                   ` Dmitry Baryshkov
  2024-02-01  1:30                     ` Abhinav Kumar
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-29 23:44 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno

On Mon, 29 Jan 2024 at 09:08, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> On 1/28/2024 10:12 PM, Dmitry Baryshkov wrote:
> > On Mon, 29 Jan 2024 at 07:03, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >>
> >>
> >> On 1/28/2024 7:42 PM, Dmitry Baryshkov wrote:
> >>> On Mon, 29 Jan 2024 at 04:58, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>>>
> >>>>
> >>>>
> >>>> On 1/27/2024 9:55 PM, Dmitry Baryshkov wrote:
> >>>>> On Sun, 28 Jan 2024 at 07:48, Paloma Arellano <quic_parellan@quicinc.com> wrote:
> >>>>>>
> >>>>>>
> >>>>>> On 1/25/2024 1:57 PM, Dmitry Baryshkov wrote:
> >>>>>>> On 25/01/2024 21:38, Paloma Arellano wrote:
> >>>>>>>> Adjust the encoder format programming in the case of video mode for DP
> >>>>>>>> to accommodate CDM related changes.
> >>>>>>>>
> >>>>>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >>>>>>>> ---
> >>>>>>>>      drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 16 +++++++++
> >>>>>>>>      drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |  8 +++++
> >>>>>>>>      .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 35 ++++++++++++++++---
> >>>>>>>>      drivers/gpu/drm/msm/dp/dp_display.c           | 12 +++++++
> >>>>>>>>      drivers/gpu/drm/msm/msm_drv.h                 |  9 ++++-
> >>>>>>>>      5 files changed, 75 insertions(+), 5 deletions(-)
> >>>>>>>>
> >>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >>>>>>>> index b0896814c1562..99ec53446ad21 100644
> >>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >>>>>>>> @@ -222,6 +222,22 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = {
> >>>>>>>>          15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10
> >>>>>>>>      };
> >>>>>>>>      +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
> >>>>>>>> const struct drm_display_mode *mode)
> >>>>>>>> +{
> >>>>>>>> +    const struct dpu_encoder_virt *dpu_enc;
> >>>>>>>> +    const struct msm_display_info *disp_info;
> >>>>>>>> +    struct msm_drm_private *priv;
> >>>>>>>> +
> >>>>>>>> +    dpu_enc = to_dpu_encoder_virt(drm_enc);
> >>>>>>>> +    disp_info = &dpu_enc->disp_info;
> >>>>>>>> +    priv = drm_enc->dev->dev_private;
> >>>>>>>> +
> >>>>>>>> +    if (disp_info->intf_type == INTF_DP &&
> >>>>>>>> + msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]],
> >>>>>>>> mode))
> >>>>>>>
> >>>>>>> This should not require interacting with DP. If we got here, we must
> >>>>>>> be sure that 4:2:0 is supported and can be configured.
> >>>>>> Ack. Will drop this function and only check for if the mode is YUV420.
> >>>>>>>
> >>>>>>>> +        return DRM_FORMAT_YUV420;
> >>>>>>>> +
> >>>>>>>> +    return DRM_FORMAT_RGB888;
> >>>>>>>> +}
> >>>>>>>>        bool dpu_encoder_is_widebus_enabled(const struct drm_encoder
> >>>>>>>> *drm_enc)
> >>>>>>>>      {
> >>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> >>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> >>>>>>>> index 7b4afa71f1f96..62255d0aa4487 100644
> >>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> >>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> >>>>>>>> @@ -162,6 +162,14 @@ int dpu_encoder_get_vsync_count(struct
> >>>>>>>> drm_encoder *drm_enc);
> >>>>>>>>       */
> >>>>>>>>      bool dpu_encoder_is_widebus_enabled(const struct drm_encoder
> >>>>>>>> *drm_enc);
> >>>>>>>>      +/**
> >>>>>>>> + * dpu_encoder_get_drm_fmt - return DRM fourcc format
> >>>>>>>> + * @drm_enc:    Pointer to previously created drm encoder structure
> >>>>>>>> + * @mode:    Corresponding drm_display_mode for dpu encoder
> >>>>>>>> + */
> >>>>>>>> +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
> >>>>>>>> +                const struct drm_display_mode *mode);
> >>>>>>>> +
> >>>>>>>>      /**
> >>>>>>>>       * dpu_encoder_get_crc_values_cnt - get number of physical encoders
> >>>>>>>> contained
> >>>>>>>>       *    in virtual encoder that can collect CRC values
> >>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >>>>>>>> index e284bf448bdda..a1dde0ff35dc8 100644
> >>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >>>>>>>> @@ -234,6 +234,7 @@ static void
> >>>>>>>> dpu_encoder_phys_vid_setup_timing_engine(
> >>>>>>>>      {
> >>>>>>>>          struct drm_display_mode mode;
> >>>>>>>>          struct dpu_hw_intf_timing_params timing_params = { 0 };
> >>>>>>>> +    struct dpu_hw_cdm *hw_cdm;
> >>>>>>>>          const struct dpu_format *fmt = NULL;
> >>>>>>>>          u32 fmt_fourcc = DRM_FORMAT_RGB888;
> >>>>>>>>          unsigned long lock_flags;
> >>>>>>>> @@ -254,17 +255,26 @@ static void
> >>>>>>>> dpu_encoder_phys_vid_setup_timing_engine(
> >>>>>>>>          DPU_DEBUG_VIDENC(phys_enc, "enabling mode:\n");
> >>>>>>>>          drm_mode_debug_printmodeline(&mode);
> >>>>>>>>      -    if (phys_enc->split_role != ENC_ROLE_SOLO) {
> >>>>>>>> +    hw_cdm = phys_enc->hw_cdm;
> >>>>>>>> +    if (hw_cdm) {
> >>>>>>>> +        intf_cfg.cdm = hw_cdm->idx;
> >>>>>>>> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent, &mode);
> >>>>>>>> +    }
> >>>>>>>> +
> >>>>>>>> +    if (phys_enc->split_role != ENC_ROLE_SOLO ||
> >>>>>>>> +        dpu_encoder_get_drm_fmt(phys_enc->parent, &mode) ==
> >>>>>>>> DRM_FORMAT_YUV420) {
> >>>>>>>>              mode.hdisplay >>= 1;
> >>>>>>>>              mode.htotal >>= 1;
> >>>>>>>>              mode.hsync_start >>= 1;
> >>>>>>>>              mode.hsync_end >>= 1;
> >>>>>>>> +        mode.hskew >>= 1;
> >>>>>>>
> >>>>>>> Separate patch.
> >>>>>> Ack.
> >>>>>>>
> >>>>>>>>                DPU_DEBUG_VIDENC(phys_enc,
> >>>>>>>> -            "split_role %d, halve horizontal %d %d %d %d\n",
> >>>>>>>> +            "split_role %d, halve horizontal %d %d %d %d %d\n",
> >>>>>>>>                  phys_enc->split_role,
> >>>>>>>>                  mode.hdisplay, mode.htotal,
> >>>>>>>> -            mode.hsync_start, mode.hsync_end);
> >>>>>>>> +            mode.hsync_start, mode.hsync_end,
> >>>>>>>> +            mode.hskew);
> >>>>>>>>          }
> >>>>>>>>            drm_mode_to_intf_timing_params(phys_enc, &mode, &timing_params);
> >>>>>>>> @@ -412,8 +422,15 @@ static int dpu_encoder_phys_vid_control_vblank_irq(
> >>>>>>>>      static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys
> >>>>>>>> *phys_enc)
> >>>>>>>>      {
> >>>>>>>>          struct dpu_hw_ctl *ctl;
> >>>>>>>> +    struct dpu_hw_cdm *hw_cdm;
> >>>>>>>> +    const struct dpu_format *fmt = NULL;
> >>>>>>>> +    u32 fmt_fourcc = DRM_FORMAT_RGB888;
> >>>>>>>>            ctl = phys_enc->hw_ctl;
> >>>>>>>> +    hw_cdm = phys_enc->hw_cdm;
> >>>>>>>> +    if (hw_cdm)
> >>>>>>>> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent,
> >>>>>>>> &phys_enc->cached_mode);
> >>>>>>>> +    fmt = dpu_get_dpu_format(fmt_fourcc);
> >>>>>>>>            DPU_DEBUG_VIDENC(phys_enc, "\n");
> >>>>>>>>      @@ -422,6 +439,8 @@ static void dpu_encoder_phys_vid_enable(struct
> >>>>>>>> dpu_encoder_phys *phys_enc)
> >>>>>>>>            dpu_encoder_helper_split_config(phys_enc,
> >>>>>>>> phys_enc->hw_intf->idx);
> >>>>>>>>      +    dpu_encoder_helper_phys_setup_cdm(phys_enc, fmt,
> >>>>>>>> CDM_CDWN_OUTPUT_HDMI);
> >>>>>>>
> >>>>>>> If there is no CDM, why do we need to call this?
> >>>>>> Inside of dpu_encoder_helper_phys_setup_cdm(), there's a check to see if
> >>>>>> there is a hw_cdm. If there is not, then it immediately exits the function.
> >>>>>>>
> >>>>>>>> +
> >>>>>>>>          dpu_encoder_phys_vid_setup_timing_engine(phys_enc);
> >>>>>>>>            /*
> >>>>>>>> @@ -437,7 +456,15 @@ static void dpu_encoder_phys_vid_enable(struct
> >>>>>>>> dpu_encoder_phys *phys_enc)
> >>>>>>>>          if (ctl->ops.update_pending_flush_merge_3d &&
> >>>>>>>> phys_enc->hw_pp->merge_3d)
> >>>>>>>>              ctl->ops.update_pending_flush_merge_3d(ctl,
> >>>>>>>> phys_enc->hw_pp->merge_3d->idx);
> >>>>>>>>      -    if (ctl->ops.update_pending_flush_periph &&
> >>>>>>>> phys_enc->hw_intf->cap->type == INTF_DP)
> >>>>>>>> +    if (ctl->ops.update_pending_flush_cdm && phys_enc->hw_cdm)
> >>>>>>>> +        ctl->ops.update_pending_flush_cdm(ctl, hw_cdm->idx);
> >>>>>>>> +
> >>>>>>>> +    /*
> >>>>>>>> +     * Peripheral flush must be updated whenever flushing SDP
> >>>>>>>> packets is needed.
> >>>>>>>> +     * SDP packets are required for any YUV format (YUV420, YUV422,
> >>>>>>>> YUV444).
> >>>>>>>> +     */
> >>>>>>>> +    if (ctl->ops.update_pending_flush_periph &&
> >>>>>>>> phys_enc->hw_intf->cap->type == INTF_DP &&
> >>>>>>>> +        phys_enc->hw_cdm)
> >>>>>>>>              ctl->ops.update_pending_flush_periph(ctl,
> >>>>>>>> phys_enc->hw_intf->idx);
> >>>>>>>
> >>>>>>> Should there be a flush if we are switching from YUV 420 to RGB mode?
> >>>>>> We only need to flush for the sdp packet, but for msa we do not need to
> >>>>>> flush.
> >>>>>
> >>>>> What about having SDP with RGB as colorimetry? In other words, if
> >>>>> there is a decision point, this one looks incorrect.
> >>>>>
> >>>>
> >>>> There are two ways to do it:
> >>>>
> >>>> 1) Use SDP for both RGB and YUV as that supports both. If we implement
> >>>> this policy, then what you are asking for is correct that we will need
> >>>> SDP even to switch back to RGB. But to implement this we will also need
> >>>> to have some sort of state management in the encoder layer about what is
> >>>> the current encoder fmt Vs what is the prev fmt and then trigger
> >>>> peripheral flush only during transitions from RGB to YUV and vice-versa
> >>>>
> >>>> 2) Use SDP only for YUV because MSA does not support YUV formats and use
> >>>> MSA for RGB
> >>>>
> >>>> We decided to implement (2) and there is no significant impact of
> >>>> switching between MSA and SDPs but state management becomes easier.
> >>>
> >>> Yes. However as you wrote, there might be other usecases concerning
> >>> SDP. Having this in mind, it sounds like the driver should decide
> >>> whether to flush peripheral at a different place (when the SDP
> >>> infoframe is being updated?). And the dpu_encoder_phys_vid_enable()
> >>> should use this previous decision. Maybe this should be a part of
> >>> msm_dp_ API, something like msm_dp_needs_peripheral_flush()?
> >>>
> >>
> >> Correct. The decision to flush peripheral or not certainly comes from
> >> the peripheral itself . In this case its DP.
> >>
> >> I think perhaps the usage of hw_cdm here makes it hard to understand
> >> that but the idea behind this was that in the change "drm/msm/dpu:
> >> reserve CDM blocks for DP if mode is YUV420 ", hw_cdm is assigned only
> >> if msm_dp_is_yuv_420_enabled() returns true.
> >
> > Yes.
> >
> >>
> >> So in some sense, the API you are asking for is already
> >> msm_dp_is_yuv_420_enabled() but we can rename that to
> >> msm_dp_needs_periph_flush().
> >
> > No. This leaks details. We might need peripheral flush for other
> > reasons. So this decision should be made inside the DP driver.
> > BTW, is there a need to flush-peripheral each time the INTF gets
> > enabled? When some bits of configuration were updated (like SDP
> > infoframe or CDM config)?
> >
>
> Not really leaking any details. Interface decides when DPU's flush bit
> needs to be invoked. All the conditions needing the flush can be
> absorbed within msm_dp_needs_periph_flush() which will be within DP
> driver. So I dont see any issue with that.

As long as we have two distinct functions: msm_dp_needs_periph_flush()
and msm_dp_is_yuv420_enabled(), it's fine with me.

>
> The peripheral flush needs to be invoked whenever SDP/PPS packets need
> to be sent out at the very least. Those are the two main use-cases so far.
>
> Not necessarily each time the INTF is enabled.
>
> But ....
>
> For PPS, we would typically enable DSC from the first frame itself and
> we dont support dynamically turning DSC ON/OFF so its a fair assumption
> that we need to the peripheral flush for DSC only during enable.
>
> For SDP, so today we enforce a modeset when we switch from a case of
> needing cdm / not needing cdm and vice-versa. So even this use-case
> should be accompanied by a disable()/enable().

My point was that there might be other changes to the SDP infoframe.

>
> So are you suggesting that we unconditionally just do peripheral_flush
> from enable()?
>
> I need to do some checking but maybe ....

This might be an option too. I don't know what delays / issues it can cause.

>
> >>
> >> The issue here is the phys layer cannot call msm_dp_is_yuv_420_enabled()
> >> so its kind of round-about by checking hw_cdm.
> >
> > Which maybe means that I should finish phys / encoder rework.
> >
>
> Ugh no. Not another rework just for this.

It is pending for the CTL flush story.

>
> >>
> >> The check is not entirely wrong because for DP, we need hw_cdm for all
> >> YUV formats and not just 420 but the relationship is maybe not clear but
> >> I thought the comment above that would help a bit:
> >>
> >> /*
> >>           * Peripheral flush must be updated whenever flushing SDP packets is
> >> needed.
> >>           * SDP packets are required for any YUV format (YUV420, YUV422, YUV444).
> >>           */
> >>
> >> The only other way I can think of is maybe we need to introduce a new
> >> phys variable called phys_enc->needs_update_periph_flush and we can set
> >> that in dpu_encoder.c as that can call msm_dp_needs_periph_flush().
> >>
> >> What do you think of this way?
> >
> > Let me understand first the requirements for peripheral flush (see the
> > questions above).
> >
> >>
> >>>>
> >>>>>>>
> >>>>>>> Also, I'd say, we should move update_pending_flush_periph invocation
> >>>>>>> to this patch.
> >>>>>> Ack
> >>>>>>>
> >>>>>>>>        skip_flush:
> >>>>>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
> >>>>>>>> b/drivers/gpu/drm/msm/dp/dp_display.c
> >>>>>>>> index 6d764f5b08727..4329435518351 100644
> >>>>>>>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> >>>>>>>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> >>>>>>>> @@ -1399,6 +1399,18 @@ void __exit msm_dp_unregister(void)
> >>>>>>>>          platform_driver_unregister(&dp_display_driver);
> >>>>>>>>      }
> >>>>>>>>      +bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
> >>>>>>>> +                   const struct drm_display_mode *mode)
> >>>>>>>> +{
> >>>>>>>> +    struct dp_display_private *dp;
> >>>>>>>> +    const struct drm_display_info *info;
> >>>>>>>> +
> >>>>>>>> +    dp = container_of(dp_display, struct dp_display_private,
> >>>>>>>> dp_display);
> >>>>>>>> +    info = &dp_display->connector->display_info;
> >>>>>>>> +
> >>>>>>>> +    return dp_panel_vsc_sdp_supported(dp->panel) &&
> >>>>>>>> drm_mode_is_420_only(info, mode);
> >>>>>>>
> >>>>>>> YUV 420 modes should be filtered out in mode_valid if VSC SDP is not
> >>>>>>> supported.
> >>>>>> Ack. Will change
> >>>>>>>
> >>>>>>>> +}
> >>>>>>>> +
> >>>>>>>>      bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)
> >>>>>>>>      {
> >>>>>>>>          struct dp_display_private *dp;
> >>>>>>>> diff --git a/drivers/gpu/drm/msm/msm_drv.h
> >>>>>>>> b/drivers/gpu/drm/msm/msm_drv.h
> >>>>>>>> index 16a7cbc0b7dd8..b9581bd934e9e 100644
> >>>>>>>> --- a/drivers/gpu/drm/msm/msm_drv.h
> >>>>>>>> +++ b/drivers/gpu/drm/msm/msm_drv.h
> >>>>>>>> @@ -387,7 +387,8 @@ void __exit msm_dp_unregister(void);
> >>>>>>>>      int msm_dp_modeset_init(struct msm_dp *dp_display, struct
> >>>>>>>> drm_device *dev,
> >>>>>>>>                   struct drm_encoder *encoder);
> >>>>>>>>      void msm_dp_snapshot(struct msm_disp_state *disp_state, struct
> >>>>>>>> msm_dp *dp_display);
> >>>>>>>> -
> >>>>>>>> +bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
> >>>>>>>> +                   const struct drm_display_mode *mode);
> >>>>>>>>      bool msm_dp_wide_bus_available(const struct msm_dp *dp_display);
> >>>>>>>>        #else
> >>>>>>>> @@ -409,6 +410,12 @@ static inline void msm_dp_snapshot(struct
> >>>>>>>> msm_disp_state *disp_state, struct msm
> >>>>>>>>      {
> >>>>>>>>      }
> >>>>>>>>      +static inline bool msm_dp_is_yuv_420_enabled(const struct msm_dp
> >>>>>>>> *dp_display,
> >>>>>>>> +                         const struct drm_display_mode *mode)
> >>>>>>>> +{
> >>>>>>>> +    return false;
> >>>>>>>> +}
> >>>>>>>> +
> >>>>>>>>      static inline bool msm_dp_wide_bus_available(const struct msm_dp
> >>>>>>>> *dp_display)
> >>>>>>>>      {
> >>>>>>>>          return false;
> >>>>>>>
> >>>>>
> >>>>>
> >>>>>
> >>>>> --
> >>>>> With best wishes
> >>>>> Dmitry
> >>>
> >>>
> >>>
> >
> >
> >



--
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/17] drm/msm/dpu: disallow widebus en in INTF_CONFIG2 when DP is YUV420
  2024-01-28  5:33       ` Dmitry Baryshkov
@ 2024-01-29 23:51         ` Abhinav Kumar
  2024-01-30  0:03           ` Dmitry Baryshkov
  0 siblings, 1 reply; 95+ messages in thread
From: Abhinav Kumar @ 2024-01-29 23:51 UTC (permalink / raw)
  To: Dmitry Baryshkov, Paloma Arellano
  Cc: neil.armstrong, linux-arm-msm, dri-devel, swboyd, seanpaul,
	marijn.suijten, quic_jesszhan, quic_khsieh, freedreno



On 1/27/2024 9:33 PM, Dmitry Baryshkov wrote:
> On Sun, 28 Jan 2024 at 07:16, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>>
>>
>> On 1/25/2024 1:26 PM, Dmitry Baryshkov wrote:
>>> On 25/01/2024 21:38, Paloma Arellano wrote:
>>>> INTF_CONFIG2 register cannot have widebus enabled when DP format is
>>>> YUV420. Therefore, program the INTF to send 1 ppc.
>>>
>>> I think this is handled in the DP driver, where we disallow wide bus
>>> for YUV 4:2:0 modes.
>> Yes we do disallow wide bus for YUV420 modes, but we still need to
>> program the INTF_CFG2_DATA_HCTL_EN. Therefore, it is necessary to add
>> this check.
> 
> As I wrote in my second email, I'd prefer to have one if which guards
> HCTL_EN and another one for WIDEN
> 
Its hard to separate out the conditions just for HCTL_EN . Its more 
about handling the various pixel per clock combinations.

But, here is how I can best summarize it.

Lets consider DSI and DP separately:

1) For DSI, for anything > DSI version 2.5 ( DPU version 7 ).

This is same the same condition as widebus today in 
msm_dsi_host_is_wide_bus_enabled().

Hence no changes needed for DSI.

2) For DP, whenever widebus is enabled AND YUV420 uncompressed case
as they are independent cases. We dont support YUV420 + DSC case.

There are other cases which fall outside of this bucket but they are 
optional ones. We only follow the "required" ones.

With this summary in mind, I am fine with what we have except perhaps 
better documentation above this block.

When DSC over DP gets added, I am expecting no changes to this block as 
it will fall under the widebus_en case.

With this information, how else would you like the check?

>>>
>>>>
>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>>> ---
>>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 4 +++-
>>>>    1 file changed, 3 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>>>> index 6bba531d6dc41..bfb93f02fe7c1 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>>>> @@ -168,7 +168,9 @@ static void
>>>> dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
>>>>         * video timing. It is recommended to enable it for all cases,
>>>> except
>>>>         * if compression is enabled in 1 pixel per clock mode
>>>>         */
>>>> -    if (p->wide_bus_en)
>>>> +    if (dp_intf && fmt->base.pixel_format == DRM_FORMAT_YUV420)
>>>> +        intf_cfg2 |= INTF_CFG2_DATA_HCTL_EN;
>>>> +    else if (p->wide_bus_en)
>>>>            intf_cfg2 |= INTF_CFG2_DATABUS_WIDEN | INTF_CFG2_DATA_HCTL_EN;
>>>>          data_width = p->width;
>>>
> 
> 
> 

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/17] drm/msm/dpu: disallow widebus en in INTF_CONFIG2 when DP is YUV420
  2024-01-29 23:51         ` Abhinav Kumar
@ 2024-01-30  0:03           ` Dmitry Baryshkov
  2024-01-30  1:07             ` Abhinav Kumar
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-30  0:03 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno

On Tue, 30 Jan 2024 at 01:51, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 1/27/2024 9:33 PM, Dmitry Baryshkov wrote:
> > On Sun, 28 Jan 2024 at 07:16, Paloma Arellano <quic_parellan@quicinc.com> wrote:
> >>
> >>
> >> On 1/25/2024 1:26 PM, Dmitry Baryshkov wrote:
> >>> On 25/01/2024 21:38, Paloma Arellano wrote:
> >>>> INTF_CONFIG2 register cannot have widebus enabled when DP format is
> >>>> YUV420. Therefore, program the INTF to send 1 ppc.
> >>>
> >>> I think this is handled in the DP driver, where we disallow wide bus
> >>> for YUV 4:2:0 modes.
> >> Yes we do disallow wide bus for YUV420 modes, but we still need to
> >> program the INTF_CFG2_DATA_HCTL_EN. Therefore, it is necessary to add
> >> this check.
> >
> > As I wrote in my second email, I'd prefer to have one if which guards
> > HCTL_EN and another one for WIDEN
> >
> Its hard to separate out the conditions just for HCTL_EN . Its more
> about handling the various pixel per clock combinations.
>
> But, here is how I can best summarize it.
>
> Lets consider DSI and DP separately:
>
> 1) For DSI, for anything > DSI version 2.5 ( DPU version 7 ).
>
> This is same the same condition as widebus today in
> msm_dsi_host_is_wide_bus_enabled().
>
> Hence no changes needed for DSI.

Not quite. msm_dsi_host_is_wide_bus_enabled() checks for the DSC being
enabled, while you have written that HCTL_EN should be set in all
cases on a corresponding platform.

>
> 2) For DP, whenever widebus is enabled AND YUV420 uncompressed case
> as they are independent cases. We dont support YUV420 + DSC case.
>
> There are other cases which fall outside of this bucket but they are
> optional ones. We only follow the "required" ones.
>
> With this summary in mind, I am fine with what we have except perhaps
> better documentation above this block.
>
> When DSC over DP gets added, I am expecting no changes to this block as
> it will fall under the widebus_en case.
>
> With this information, how else would you like the check?

What does this bit really change?

>
> >>>
> >>>>
> >>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >>>> ---
> >>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 4 +++-
> >>>>    1 file changed, 3 insertions(+), 1 deletion(-)
> >>>>
> >>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> >>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> >>>> index 6bba531d6dc41..bfb93f02fe7c1 100644
> >>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> >>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> >>>> @@ -168,7 +168,9 @@ static void
> >>>> dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
> >>>>         * video timing. It is recommended to enable it for all cases,
> >>>> except
> >>>>         * if compression is enabled in 1 pixel per clock mode
> >>>>         */
> >>>> -    if (p->wide_bus_en)
> >>>> +    if (dp_intf && fmt->base.pixel_format == DRM_FORMAT_YUV420)
> >>>> +        intf_cfg2 |= INTF_CFG2_DATA_HCTL_EN;
> >>>> +    else if (p->wide_bus_en)
> >>>>            intf_cfg2 |= INTF_CFG2_DATABUS_WIDEN | INTF_CFG2_DATA_HCTL_EN;
> >>>>          data_width = p->width;
> >>>
> >
> >
> >



-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/17] drm/msm/dpu: disallow widebus en in INTF_CONFIG2 when DP is YUV420
  2024-01-30  0:03           ` Dmitry Baryshkov
@ 2024-01-30  1:07             ` Abhinav Kumar
  2024-01-30  1:43               ` Dmitry Baryshkov
  0 siblings, 1 reply; 95+ messages in thread
From: Abhinav Kumar @ 2024-01-30  1:07 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno



On 1/29/2024 4:03 PM, Dmitry Baryshkov wrote:
> On Tue, 30 Jan 2024 at 01:51, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 1/27/2024 9:33 PM, Dmitry Baryshkov wrote:
>>> On Sun, 28 Jan 2024 at 07:16, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>>>>
>>>>
>>>> On 1/25/2024 1:26 PM, Dmitry Baryshkov wrote:
>>>>> On 25/01/2024 21:38, Paloma Arellano wrote:
>>>>>> INTF_CONFIG2 register cannot have widebus enabled when DP format is
>>>>>> YUV420. Therefore, program the INTF to send 1 ppc.
>>>>>
>>>>> I think this is handled in the DP driver, where we disallow wide bus
>>>>> for YUV 4:2:0 modes.
>>>> Yes we do disallow wide bus for YUV420 modes, but we still need to
>>>> program the INTF_CFG2_DATA_HCTL_EN. Therefore, it is necessary to add
>>>> this check.
>>>
>>> As I wrote in my second email, I'd prefer to have one if which guards
>>> HCTL_EN and another one for WIDEN
>>>
>> Its hard to separate out the conditions just for HCTL_EN . Its more
>> about handling the various pixel per clock combinations.
>>
>> But, here is how I can best summarize it.
>>
>> Lets consider DSI and DP separately:
>>
>> 1) For DSI, for anything > DSI version 2.5 ( DPU version 7 ).
>>
>> This is same the same condition as widebus today in
>> msm_dsi_host_is_wide_bus_enabled().
>>
>> Hence no changes needed for DSI.
> 
> Not quite. msm_dsi_host_is_wide_bus_enabled() checks for the DSC being
> enabled, while you have written that HCTL_EN should be set in all
> cases on a corresponding platform.
> 

Agreed. This is true, we should enable HCTL_EN for DSI irrespective of 
widebus for the versions I wrote.

Basically for the non-compressed case.

I will write something up to fix this for DSI. I think this can go as a 
bug fix.

But that does not change the DP conditions OR in other words, I dont see 
anything wrong with this patch yet.

>>
>> 2) For DP, whenever widebus is enabled AND YUV420 uncompressed case
>> as they are independent cases. We dont support YUV420 + DSC case.
>>
>> There are other cases which fall outside of this bucket but they are
>> optional ones. We only follow the "required" ones.
>>
>> With this summary in mind, I am fine with what we have except perhaps
>> better documentation above this block.
>>
>> When DSC over DP gets added, I am expecting no changes to this block as
>> it will fall under the widebus_en case.
>>
>> With this information, how else would you like the check?
> 
> What does this bit really change?
> 

This bit basically just tells that the data sent per line is programmed 
with INTF_DISPLAY_DATA_HCTL like this cap is suggesting.

         if (ctx->cap->features & BIT(DPU_DATA_HCTL_EN)) {
                 DPU_REG_WRITE(c, INTF_CONFIG2, intf_cfg2);
                 DPU_REG_WRITE(c, INTF_DISPLAY_DATA_HCTL, 
display_data_hctl);
                 DPU_REG_WRITE(c, INTF_ACTIVE_DATA_HCTL, active_data_hctl);
         }

Prior to that it was programmed with INTF_DISPLAY_HCTL in the same function.

>>
>>>>>
>>>>>>
>>>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>>>>> ---
>>>>>>     drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 4 +++-
>>>>>>     1 file changed, 3 insertions(+), 1 deletion(-)
>>>>>>
>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>>>>>> index 6bba531d6dc41..bfb93f02fe7c1 100644
>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>>>>>> @@ -168,7 +168,9 @@ static void
>>>>>> dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
>>>>>>          * video timing. It is recommended to enable it for all cases,
>>>>>> except
>>>>>>          * if compression is enabled in 1 pixel per clock mode
>>>>>>          */
>>>>>> -    if (p->wide_bus_en)
>>>>>> +    if (dp_intf && fmt->base.pixel_format == DRM_FORMAT_YUV420)
>>>>>> +        intf_cfg2 |= INTF_CFG2_DATA_HCTL_EN;
>>>>>> +    else if (p->wide_bus_en)
>>>>>>             intf_cfg2 |= INTF_CFG2_DATABUS_WIDEN | INTF_CFG2_DATA_HCTL_EN;
>>>>>>           data_width = p->width;
>>>>>
>>>
>>>
>>>
> 
> 
> 

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/17] drm/msm/dpu: disallow widebus en in INTF_CONFIG2 when DP is YUV420
  2024-01-30  1:07             ` Abhinav Kumar
@ 2024-01-30  1:43               ` Dmitry Baryshkov
  2024-01-30  4:10                 ` Abhinav Kumar
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-30  1:43 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno

On Tue, 30 Jan 2024 at 03:07, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 1/29/2024 4:03 PM, Dmitry Baryshkov wrote:
> > On Tue, 30 Jan 2024 at 01:51, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >>
> >>
> >> On 1/27/2024 9:33 PM, Dmitry Baryshkov wrote:
> >>> On Sun, 28 Jan 2024 at 07:16, Paloma Arellano <quic_parellan@quicinc.com> wrote:
> >>>>
> >>>>
> >>>> On 1/25/2024 1:26 PM, Dmitry Baryshkov wrote:
> >>>>> On 25/01/2024 21:38, Paloma Arellano wrote:
> >>>>>> INTF_CONFIG2 register cannot have widebus enabled when DP format is
> >>>>>> YUV420. Therefore, program the INTF to send 1 ppc.
> >>>>>
> >>>>> I think this is handled in the DP driver, where we disallow wide bus
> >>>>> for YUV 4:2:0 modes.
> >>>> Yes we do disallow wide bus for YUV420 modes, but we still need to
> >>>> program the INTF_CFG2_DATA_HCTL_EN. Therefore, it is necessary to add
> >>>> this check.
> >>>
> >>> As I wrote in my second email, I'd prefer to have one if which guards
> >>> HCTL_EN and another one for WIDEN
> >>>
> >> Its hard to separate out the conditions just for HCTL_EN . Its more
> >> about handling the various pixel per clock combinations.
> >>
> >> But, here is how I can best summarize it.
> >>
> >> Lets consider DSI and DP separately:
> >>
> >> 1) For DSI, for anything > DSI version 2.5 ( DPU version 7 ).
> >>
> >> This is same the same condition as widebus today in
> >> msm_dsi_host_is_wide_bus_enabled().
> >>
> >> Hence no changes needed for DSI.
> >
> > Not quite. msm_dsi_host_is_wide_bus_enabled() checks for the DSC being
> > enabled, while you have written that HCTL_EN should be set in all
> > cases on a corresponding platform.
> >
>
> Agreed. This is true, we should enable HCTL_EN for DSI irrespective of
> widebus for the versions I wrote.
>
> Basically for the non-compressed case.
>
> I will write something up to fix this for DSI. I think this can go as a
> bug fix.
>
> But that does not change the DP conditions OR in other words, I dont see
> anything wrong with this patch yet.
>
> >>
> >> 2) For DP, whenever widebus is enabled AND YUV420 uncompressed case
> >> as they are independent cases. We dont support YUV420 + DSC case.
> >>
> >> There are other cases which fall outside of this bucket but they are
> >> optional ones. We only follow the "required" ones.
> >>
> >> With this summary in mind, I am fine with what we have except perhaps
> >> better documentation above this block.
> >>
> >> When DSC over DP gets added, I am expecting no changes to this block as
> >> it will fall under the widebus_en case.
> >>
> >> With this information, how else would you like the check?
> >
> > What does this bit really change?
> >
>
> This bit basically just tells that the data sent per line is programmed
> with INTF_DISPLAY_DATA_HCTL like this cap is suggesting.
>
>          if (ctx->cap->features & BIT(DPU_DATA_HCTL_EN)) {
>                  DPU_REG_WRITE(c, INTF_CONFIG2, intf_cfg2);
>                  DPU_REG_WRITE(c, INTF_DISPLAY_DATA_HCTL,
> display_data_hctl);
>                  DPU_REG_WRITE(c, INTF_ACTIVE_DATA_HCTL, active_data_hctl);
>          }
>
> Prior to that it was programmed with INTF_DISPLAY_HCTL in the same function.

Can we enable it unconditionally for DPU >= 5.0?

>
> >>
> >>>>>
> >>>>>>
> >>>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >>>>>> ---
> >>>>>>     drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 4 +++-
> >>>>>>     1 file changed, 3 insertions(+), 1 deletion(-)
> >>>>>>
> >>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> >>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> >>>>>> index 6bba531d6dc41..bfb93f02fe7c1 100644
> >>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> >>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> >>>>>> @@ -168,7 +168,9 @@ static void
> >>>>>> dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
> >>>>>>          * video timing. It is recommended to enable it for all cases,
> >>>>>> except
> >>>>>>          * if compression is enabled in 1 pixel per clock mode
> >>>>>>          */
> >>>>>> -    if (p->wide_bus_en)
> >>>>>> +    if (dp_intf && fmt->base.pixel_format == DRM_FORMAT_YUV420)
> >>>>>> +        intf_cfg2 |= INTF_CFG2_DATA_HCTL_EN;
> >>>>>> +    else if (p->wide_bus_en)
> >>>>>>             intf_cfg2 |= INTF_CFG2_DATABUS_WIDEN | INTF_CFG2_DATA_HCTL_EN;
> >>>>>>           data_width = p->width;
> >>>>>
> >>>
> >>>
> >>>
> >
> >
> >



-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/17] drm/msm/dpu: disallow widebus en in INTF_CONFIG2 when DP is YUV420
  2024-01-30  1:43               ` Dmitry Baryshkov
@ 2024-01-30  4:10                 ` Abhinav Kumar
  2024-01-30  5:28                   ` Dmitry Baryshkov
  0 siblings, 1 reply; 95+ messages in thread
From: Abhinav Kumar @ 2024-01-30  4:10 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno



On 1/29/2024 5:43 PM, Dmitry Baryshkov wrote:
> On Tue, 30 Jan 2024 at 03:07, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 1/29/2024 4:03 PM, Dmitry Baryshkov wrote:
>>> On Tue, 30 Jan 2024 at 01:51, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>>>
>>>>
>>>>
>>>> On 1/27/2024 9:33 PM, Dmitry Baryshkov wrote:
>>>>> On Sun, 28 Jan 2024 at 07:16, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>>>>>>
>>>>>>
>>>>>> On 1/25/2024 1:26 PM, Dmitry Baryshkov wrote:
>>>>>>> On 25/01/2024 21:38, Paloma Arellano wrote:
>>>>>>>> INTF_CONFIG2 register cannot have widebus enabled when DP format is
>>>>>>>> YUV420. Therefore, program the INTF to send 1 ppc.
>>>>>>>
>>>>>>> I think this is handled in the DP driver, where we disallow wide bus
>>>>>>> for YUV 4:2:0 modes.
>>>>>> Yes we do disallow wide bus for YUV420 modes, but we still need to
>>>>>> program the INTF_CFG2_DATA_HCTL_EN. Therefore, it is necessary to add
>>>>>> this check.
>>>>>
>>>>> As I wrote in my second email, I'd prefer to have one if which guards
>>>>> HCTL_EN and another one for WIDEN
>>>>>
>>>> Its hard to separate out the conditions just for HCTL_EN . Its more
>>>> about handling the various pixel per clock combinations.
>>>>
>>>> But, here is how I can best summarize it.
>>>>
>>>> Lets consider DSI and DP separately:
>>>>
>>>> 1) For DSI, for anything > DSI version 2.5 ( DPU version 7 ).
>>>>
>>>> This is same the same condition as widebus today in
>>>> msm_dsi_host_is_wide_bus_enabled().
>>>>
>>>> Hence no changes needed for DSI.
>>>
>>> Not quite. msm_dsi_host_is_wide_bus_enabled() checks for the DSC being
>>> enabled, while you have written that HCTL_EN should be set in all
>>> cases on a corresponding platform.
>>>
>>
>> Agreed. This is true, we should enable HCTL_EN for DSI irrespective of
>> widebus for the versions I wrote.
>>
>> Basically for the non-compressed case.
>>
>> I will write something up to fix this for DSI. I think this can go as a
>> bug fix.
>>
>> But that does not change the DP conditions OR in other words, I dont see
>> anything wrong with this patch yet.
>>
>>>>
>>>> 2) For DP, whenever widebus is enabled AND YUV420 uncompressed case
>>>> as they are independent cases. We dont support YUV420 + DSC case.
>>>>
>>>> There are other cases which fall outside of this bucket but they are
>>>> optional ones. We only follow the "required" ones.
>>>>
>>>> With this summary in mind, I am fine with what we have except perhaps
>>>> better documentation above this block.
>>>>
>>>> When DSC over DP gets added, I am expecting no changes to this block as
>>>> it will fall under the widebus_en case.
>>>>
>>>> With this information, how else would you like the check?
>>>
>>> What does this bit really change?
>>>
>>
>> This bit basically just tells that the data sent per line is programmed
>> with INTF_DISPLAY_DATA_HCTL like this cap is suggesting.
>>
>>           if (ctx->cap->features & BIT(DPU_DATA_HCTL_EN)) {
>>                   DPU_REG_WRITE(c, INTF_CONFIG2, intf_cfg2);
>>                   DPU_REG_WRITE(c, INTF_DISPLAY_DATA_HCTL,
>> display_data_hctl);
>>                   DPU_REG_WRITE(c, INTF_ACTIVE_DATA_HCTL, active_data_hctl);
>>           }
>>
>> Prior to that it was programmed with INTF_DISPLAY_HCTL in the same function.
> 
> Can we enable it unconditionally for DPU >= 5.0?
> 

There is a corner-case that we should not enable it when compression is 
enabled without widebus as per the docs :(

For DP there will not be a case like that because compression and 
widebus go together but for DSI, it is possible.

So I found that the reset value of this register does cover all cases 
for DPU >= 7.0 so below fix will address the DSI concern and will fix 
the issue even for YUV420 cases such as this one for DPU >= 7.0

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
index 6bba531d6dc4..cbd5ebd516cd 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
@@ -168,6 +168,8 @@ static void dpu_hw_intf_setup_timing_engine(struct 
dpu_hw_intf *ctx,
          * video timing. It is recommended to enable it for all cases, 
except
          * if compression is enabled in 1 pixel per clock mode
          */
+
+       intf_cfg2 = DPU_REG_READ(c, INTF_CONFIG2);
         if (p->wide_bus_en)
                 intf_cfg2 |= INTF_CFG2_DATABUS_WIDEN | 
INTF_CFG2_DATA_HCTL_EN;


But, this does not still work for DPU < 7.0 such as sc7180 if we try 
YUV420 over DP on that because its DPU version is 6.2 so we will have to 
keep this patch for those cases.

>>
>>>>
>>>>>>>
>>>>>>>>
>>>>>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>>>>>>> ---
>>>>>>>>      drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 4 +++-
>>>>>>>>      1 file changed, 3 insertions(+), 1 deletion(-)
>>>>>>>>
>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>>>>>>>> index 6bba531d6dc41..bfb93f02fe7c1 100644
>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>>>>>>>> @@ -168,7 +168,9 @@ static void
>>>>>>>> dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
>>>>>>>>           * video timing. It is recommended to enable it for all cases,
>>>>>>>> except
>>>>>>>>           * if compression is enabled in 1 pixel per clock mode
>>>>>>>>           */
>>>>>>>> -    if (p->wide_bus_en)
>>>>>>>> +    if (dp_intf && fmt->base.pixel_format == DRM_FORMAT_YUV420)
>>>>>>>> +        intf_cfg2 |= INTF_CFG2_DATA_HCTL_EN;
>>>>>>>> +    else if (p->wide_bus_en)
>>>>>>>>              intf_cfg2 |= INTF_CFG2_DATABUS_WIDEN | INTF_CFG2_DATA_HCTL_EN;
>>>>>>>>            data_width = p->width;
>>>>>>>
>>>>>
>>>>>
>>>>>
>>>
>>>
>>>
> 
> 
> 

^ permalink raw reply related	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/17] drm/msm/dpu: disallow widebus en in INTF_CONFIG2 when DP is YUV420
  2024-01-30  4:10                 ` Abhinav Kumar
@ 2024-01-30  5:28                   ` Dmitry Baryshkov
  2024-01-30  6:03                     ` Abhinav Kumar
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-01-30  5:28 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno

On Tue, 30 Jan 2024 at 06:10, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 1/29/2024 5:43 PM, Dmitry Baryshkov wrote:
> > On Tue, 30 Jan 2024 at 03:07, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >>
> >>
> >> On 1/29/2024 4:03 PM, Dmitry Baryshkov wrote:
> >>> On Tue, 30 Jan 2024 at 01:51, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>>>
> >>>>
> >>>>
> >>>> On 1/27/2024 9:33 PM, Dmitry Baryshkov wrote:
> >>>>> On Sun, 28 Jan 2024 at 07:16, Paloma Arellano <quic_parellan@quicinc.com> wrote:
> >>>>>>
> >>>>>>
> >>>>>> On 1/25/2024 1:26 PM, Dmitry Baryshkov wrote:
> >>>>>>> On 25/01/2024 21:38, Paloma Arellano wrote:
> >>>>>>>> INTF_CONFIG2 register cannot have widebus enabled when DP format is
> >>>>>>>> YUV420. Therefore, program the INTF to send 1 ppc.
> >>>>>>>
> >>>>>>> I think this is handled in the DP driver, where we disallow wide bus
> >>>>>>> for YUV 4:2:0 modes.
> >>>>>> Yes we do disallow wide bus for YUV420 modes, but we still need to
> >>>>>> program the INTF_CFG2_DATA_HCTL_EN. Therefore, it is necessary to add
> >>>>>> this check.
> >>>>>
> >>>>> As I wrote in my second email, I'd prefer to have one if which guards
> >>>>> HCTL_EN and another one for WIDEN
> >>>>>
> >>>> Its hard to separate out the conditions just for HCTL_EN . Its more
> >>>> about handling the various pixel per clock combinations.
> >>>>
> >>>> But, here is how I can best summarize it.
> >>>>
> >>>> Lets consider DSI and DP separately:
> >>>>
> >>>> 1) For DSI, for anything > DSI version 2.5 ( DPU version 7 ).
> >>>>
> >>>> This is same the same condition as widebus today in
> >>>> msm_dsi_host_is_wide_bus_enabled().
> >>>>
> >>>> Hence no changes needed for DSI.
> >>>
> >>> Not quite. msm_dsi_host_is_wide_bus_enabled() checks for the DSC being
> >>> enabled, while you have written that HCTL_EN should be set in all
> >>> cases on a corresponding platform.
> >>>
> >>
> >> Agreed. This is true, we should enable HCTL_EN for DSI irrespective of
> >> widebus for the versions I wrote.
> >>
> >> Basically for the non-compressed case.
> >>
> >> I will write something up to fix this for DSI. I think this can go as a
> >> bug fix.
> >>
> >> But that does not change the DP conditions OR in other words, I dont see
> >> anything wrong with this patch yet.
> >>
> >>>>
> >>>> 2) For DP, whenever widebus is enabled AND YUV420 uncompressed case
> >>>> as they are independent cases. We dont support YUV420 + DSC case.
> >>>>
> >>>> There are other cases which fall outside of this bucket but they are
> >>>> optional ones. We only follow the "required" ones.
> >>>>
> >>>> With this summary in mind, I am fine with what we have except perhaps
> >>>> better documentation above this block.
> >>>>
> >>>> When DSC over DP gets added, I am expecting no changes to this block as
> >>>> it will fall under the widebus_en case.
> >>>>
> >>>> With this information, how else would you like the check?
> >>>
> >>> What does this bit really change?
> >>>
> >>
> >> This bit basically just tells that the data sent per line is programmed
> >> with INTF_DISPLAY_DATA_HCTL like this cap is suggesting.
> >>
> >>           if (ctx->cap->features & BIT(DPU_DATA_HCTL_EN)) {
> >>                   DPU_REG_WRITE(c, INTF_CONFIG2, intf_cfg2);
> >>                   DPU_REG_WRITE(c, INTF_DISPLAY_DATA_HCTL,
> >> display_data_hctl);
> >>                   DPU_REG_WRITE(c, INTF_ACTIVE_DATA_HCTL, active_data_hctl);
> >>           }
> >>
> >> Prior to that it was programmed with INTF_DISPLAY_HCTL in the same function.
> >
> > Can we enable it unconditionally for DPU >= 5.0?
> >
>
> There is a corner-case that we should not enable it when compression is
> enabled without widebus as per the docs :(

What about explicitly disabling it in such a case?
I mean something like:

if (dpu_core_rev >= 5.0 && !(enc->hw_dsc && !enc->wide_bus_en))
   intf_cfg |= INTF_CFG2_HCTL_EN;


>
> For DP there will not be a case like that because compression and
> widebus go together but for DSI, it is possible.
>
> So I found that the reset value of this register does cover all cases
> for DPU >= 7.0 so below fix will address the DSI concern and will fix
> the issue even for YUV420 cases such as this one for DPU >= 7.0
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> index 6bba531d6dc4..cbd5ebd516cd 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> @@ -168,6 +168,8 @@ static void dpu_hw_intf_setup_timing_engine(struct
> dpu_hw_intf *ctx,
>           * video timing. It is recommended to enable it for all cases,
> except
>           * if compression is enabled in 1 pixel per clock mode
>           */
> +
> +       intf_cfg2 = DPU_REG_READ(c, INTF_CONFIG2);
>          if (p->wide_bus_en)
>                  intf_cfg2 |= INTF_CFG2_DATABUS_WIDEN |
> INTF_CFG2_DATA_HCTL_EN;
>
>
> But, this does not still work for DPU < 7.0 such as sc7180 if we try
> YUV420 over DP on that because its DPU version is 6.2 so we will have to
> keep this patch for those cases.
>
> >>
> >>>>
> >>>>>>>
> >>>>>>>>
> >>>>>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >>>>>>>> ---
> >>>>>>>>      drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 4 +++-
> >>>>>>>>      1 file changed, 3 insertions(+), 1 deletion(-)
> >>>>>>>>
> >>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> >>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> >>>>>>>> index 6bba531d6dc41..bfb93f02fe7c1 100644
> >>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> >>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
> >>>>>>>> @@ -168,7 +168,9 @@ static void
> >>>>>>>> dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
> >>>>>>>>           * video timing. It is recommended to enable it for all cases,
> >>>>>>>> except
> >>>>>>>>           * if compression is enabled in 1 pixel per clock mode
> >>>>>>>>           */
> >>>>>>>> -    if (p->wide_bus_en)
> >>>>>>>> +    if (dp_intf && fmt->base.pixel_format == DRM_FORMAT_YUV420)
> >>>>>>>> +        intf_cfg2 |= INTF_CFG2_DATA_HCTL_EN;
> >>>>>>>> +    else if (p->wide_bus_en)
> >>>>>>>>              intf_cfg2 |= INTF_CFG2_DATABUS_WIDEN | INTF_CFG2_DATA_HCTL_EN;
> >>>>>>>>            data_width = p->width;
> >>>>>>>
> >>>>>
> >>>>>
> >>>>>
> >>>
> >>>
> >>>
> >
> >
> >



-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 07/17] drm/msm/dpu: disallow widebus en in INTF_CONFIG2 when DP is YUV420
  2024-01-30  5:28                   ` Dmitry Baryshkov
@ 2024-01-30  6:03                     ` Abhinav Kumar
  0 siblings, 0 replies; 95+ messages in thread
From: Abhinav Kumar @ 2024-01-30  6:03 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno



On 1/29/2024 9:28 PM, Dmitry Baryshkov wrote:
> On Tue, 30 Jan 2024 at 06:10, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 1/29/2024 5:43 PM, Dmitry Baryshkov wrote:
>>> On Tue, 30 Jan 2024 at 03:07, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>>>
>>>>
>>>>
>>>> On 1/29/2024 4:03 PM, Dmitry Baryshkov wrote:
>>>>> On Tue, 30 Jan 2024 at 01:51, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> On 1/27/2024 9:33 PM, Dmitry Baryshkov wrote:
>>>>>>> On Sun, 28 Jan 2024 at 07:16, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>> On 1/25/2024 1:26 PM, Dmitry Baryshkov wrote:
>>>>>>>>> On 25/01/2024 21:38, Paloma Arellano wrote:
>>>>>>>>>> INTF_CONFIG2 register cannot have widebus enabled when DP format is
>>>>>>>>>> YUV420. Therefore, program the INTF to send 1 ppc.
>>>>>>>>>
>>>>>>>>> I think this is handled in the DP driver, where we disallow wide bus
>>>>>>>>> for YUV 4:2:0 modes.
>>>>>>>> Yes we do disallow wide bus for YUV420 modes, but we still need to
>>>>>>>> program the INTF_CFG2_DATA_HCTL_EN. Therefore, it is necessary to add
>>>>>>>> this check.
>>>>>>>
>>>>>>> As I wrote in my second email, I'd prefer to have one if which guards
>>>>>>> HCTL_EN and another one for WIDEN
>>>>>>>
>>>>>> Its hard to separate out the conditions just for HCTL_EN . Its more
>>>>>> about handling the various pixel per clock combinations.
>>>>>>
>>>>>> But, here is how I can best summarize it.
>>>>>>
>>>>>> Lets consider DSI and DP separately:
>>>>>>
>>>>>> 1) For DSI, for anything > DSI version 2.5 ( DPU version 7 ).
>>>>>>
>>>>>> This is same the same condition as widebus today in
>>>>>> msm_dsi_host_is_wide_bus_enabled().
>>>>>>
>>>>>> Hence no changes needed for DSI.
>>>>>
>>>>> Not quite. msm_dsi_host_is_wide_bus_enabled() checks for the DSC being
>>>>> enabled, while you have written that HCTL_EN should be set in all
>>>>> cases on a corresponding platform.
>>>>>
>>>>
>>>> Agreed. This is true, we should enable HCTL_EN for DSI irrespective of
>>>> widebus for the versions I wrote.
>>>>
>>>> Basically for the non-compressed case.
>>>>
>>>> I will write something up to fix this for DSI. I think this can go as a
>>>> bug fix.
>>>>
>>>> But that does not change the DP conditions OR in other words, I dont see
>>>> anything wrong with this patch yet.
>>>>
>>>>>>
>>>>>> 2) For DP, whenever widebus is enabled AND YUV420 uncompressed case
>>>>>> as they are independent cases. We dont support YUV420 + DSC case.
>>>>>>
>>>>>> There are other cases which fall outside of this bucket but they are
>>>>>> optional ones. We only follow the "required" ones.
>>>>>>
>>>>>> With this summary in mind, I am fine with what we have except perhaps
>>>>>> better documentation above this block.
>>>>>>
>>>>>> When DSC over DP gets added, I am expecting no changes to this block as
>>>>>> it will fall under the widebus_en case.
>>>>>>
>>>>>> With this information, how else would you like the check?
>>>>>
>>>>> What does this bit really change?
>>>>>
>>>>
>>>> This bit basically just tells that the data sent per line is programmed
>>>> with INTF_DISPLAY_DATA_HCTL like this cap is suggesting.
>>>>
>>>>            if (ctx->cap->features & BIT(DPU_DATA_HCTL_EN)) {
>>>>                    DPU_REG_WRITE(c, INTF_CONFIG2, intf_cfg2);
>>>>                    DPU_REG_WRITE(c, INTF_DISPLAY_DATA_HCTL,
>>>> display_data_hctl);
>>>>                    DPU_REG_WRITE(c, INTF_ACTIVE_DATA_HCTL, active_data_hctl);
>>>>            }
>>>>
>>>> Prior to that it was programmed with INTF_DISPLAY_HCTL in the same function.
>>>
>>> Can we enable it unconditionally for DPU >= 5.0?
>>>
>>
>> There is a corner-case that we should not enable it when compression is
>> enabled without widebus as per the docs :(
> 
> What about explicitly disabling it in such a case?
> I mean something like:
> 
> if (dpu_core_rev >= 5.0 && !(enc->hw_dsc && !enc->wide_bus_en))
>     intf_cfg |= INTF_CFG2_HCTL_EN;
> 

Condition is correct now. But we dont have enc or dpu version in this 
function.

We need to pass a new parameter called compression_en to 
dpu_hw_intf_timing_params and set it when dsc is used and then do this. 
We have widebus_en already in dpu_hw_intf_timing_params.

This was anyway part of the DSC over DP but we can add that here and 
then the if (ctx->cap->features & BIT(DPU_DATA_HCTL_EN)) is indicative 
of dpu version >=5 so we can move this setup there.

> 
>>
>> For DP there will not be a case like that because compression and
>> widebus go together but for DSI, it is possible.
>>
>> So I found that the reset value of this register does cover all cases
>> for DPU >= 7.0 so below fix will address the DSI concern and will fix
>> the issue even for YUV420 cases such as this one for DPU >= 7.0
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>> index 6bba531d6dc4..cbd5ebd516cd 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>> @@ -168,6 +168,8 @@ static void dpu_hw_intf_setup_timing_engine(struct
>> dpu_hw_intf *ctx,
>>            * video timing. It is recommended to enable it for all cases,
>> except
>>            * if compression is enabled in 1 pixel per clock mode
>>            */
>> +
>> +       intf_cfg2 = DPU_REG_READ(c, INTF_CONFIG2);
>>           if (p->wide_bus_en)
>>                   intf_cfg2 |= INTF_CFG2_DATABUS_WIDEN |
>> INTF_CFG2_DATA_HCTL_EN;
>>
>>
>> But, this does not still work for DPU < 7.0 such as sc7180 if we try
>> YUV420 over DP on that because its DPU version is 6.2 so we will have to
>> keep this patch for those cases.
>>
>>>>
>>>>>>
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>>>>>>>>> ---
>>>>>>>>>>       drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 4 +++-
>>>>>>>>>>       1 file changed, 3 insertions(+), 1 deletion(-)
>>>>>>>>>>
>>>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>>>>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>>>>>>>>>> index 6bba531d6dc41..bfb93f02fe7c1 100644
>>>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>>>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
>>>>>>>>>> @@ -168,7 +168,9 @@ static void
>>>>>>>>>> dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
>>>>>>>>>>            * video timing. It is recommended to enable it for all cases,
>>>>>>>>>> except
>>>>>>>>>>            * if compression is enabled in 1 pixel per clock mode
>>>>>>>>>>            */
>>>>>>>>>> -    if (p->wide_bus_en)
>>>>>>>>>> +    if (dp_intf && fmt->base.pixel_format == DRM_FORMAT_YUV420)
>>>>>>>>>> +        intf_cfg2 |= INTF_CFG2_DATA_HCTL_EN;
>>>>>>>>>> +    else if (p->wide_bus_en)
>>>>>>>>>>               intf_cfg2 |= INTF_CFG2_DATABUS_WIDEN | INTF_CFG2_DATA_HCTL_EN;
>>>>>>>>>>             data_width = p->width;
>>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>
>>>>>
>>>>>
>>>
>>>
>>>
> 
> 
> 

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 14/17] drm/msm/dpu: modify encoder programming for CDM over DP
  2024-01-29 23:44                   ` Dmitry Baryshkov
@ 2024-02-01  1:30                     ` Abhinav Kumar
  2024-02-01  3:17                       ` Dmitry Baryshkov
  0 siblings, 1 reply; 95+ messages in thread
From: Abhinav Kumar @ 2024-02-01  1:30 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno



On 1/29/2024 3:44 PM, Dmitry Baryshkov wrote:
> On Mon, 29 Jan 2024 at 09:08, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> On 1/28/2024 10:12 PM, Dmitry Baryshkov wrote:
>>> On Mon, 29 Jan 2024 at 07:03, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>>>
>>>>
>>>>
>>>> On 1/28/2024 7:42 PM, Dmitry Baryshkov wrote:
>>>>> On Mon, 29 Jan 2024 at 04:58, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> On 1/27/2024 9:55 PM, Dmitry Baryshkov wrote:
>>>>>>> On Sun, 28 Jan 2024 at 07:48, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>> On 1/25/2024 1:57 PM, Dmitry Baryshkov wrote:
>>>>>>>>> On 25/01/2024 21:38, Paloma Arellano wrote:
>>>>>>>>>> Adjust the encoder format programming in the case of video mode for DP
>>>>>>>>>> to accommodate CDM related changes.
>>>>>>>>>>
>>>>>>>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>>>>>>>>> ---
>>>>>>>>>>       drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 16 +++++++++
>>>>>>>>>>       drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |  8 +++++
>>>>>>>>>>       .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 35 ++++++++++++++++---
>>>>>>>>>>       drivers/gpu/drm/msm/dp/dp_display.c           | 12 +++++++
>>>>>>>>>>       drivers/gpu/drm/msm/msm_drv.h                 |  9 ++++-
>>>>>>>>>>       5 files changed, 75 insertions(+), 5 deletions(-)
>>>>>>>>>>
>>>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>>>>>> index b0896814c1562..99ec53446ad21 100644
>>>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>>>>>> @@ -222,6 +222,22 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = {
>>>>>>>>>>           15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10
>>>>>>>>>>       };
>>>>>>>>>>       +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
>>>>>>>>>> const struct drm_display_mode *mode)
>>>>>>>>>> +{
>>>>>>>>>> +    const struct dpu_encoder_virt *dpu_enc;
>>>>>>>>>> +    const struct msm_display_info *disp_info;
>>>>>>>>>> +    struct msm_drm_private *priv;
>>>>>>>>>> +
>>>>>>>>>> +    dpu_enc = to_dpu_encoder_virt(drm_enc);
>>>>>>>>>> +    disp_info = &dpu_enc->disp_info;
>>>>>>>>>> +    priv = drm_enc->dev->dev_private;
>>>>>>>>>> +
>>>>>>>>>> +    if (disp_info->intf_type == INTF_DP &&
>>>>>>>>>> + msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]],
>>>>>>>>>> mode))
>>>>>>>>>
>>>>>>>>> This should not require interacting with DP. If we got here, we must
>>>>>>>>> be sure that 4:2:0 is supported and can be configured.
>>>>>>>> Ack. Will drop this function and only check for if the mode is YUV420.
>>>>>>>>>
>>>>>>>>>> +        return DRM_FORMAT_YUV420;
>>>>>>>>>> +
>>>>>>>>>> +    return DRM_FORMAT_RGB888;
>>>>>>>>>> +}
>>>>>>>>>>         bool dpu_encoder_is_widebus_enabled(const struct drm_encoder
>>>>>>>>>> *drm_enc)
>>>>>>>>>>       {
>>>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>>>>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>>>>>>>>>> index 7b4afa71f1f96..62255d0aa4487 100644
>>>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>>>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>>>>>>>>>> @@ -162,6 +162,14 @@ int dpu_encoder_get_vsync_count(struct
>>>>>>>>>> drm_encoder *drm_enc);
>>>>>>>>>>        */
>>>>>>>>>>       bool dpu_encoder_is_widebus_enabled(const struct drm_encoder
>>>>>>>>>> *drm_enc);
>>>>>>>>>>       +/**
>>>>>>>>>> + * dpu_encoder_get_drm_fmt - return DRM fourcc format
>>>>>>>>>> + * @drm_enc:    Pointer to previously created drm encoder structure
>>>>>>>>>> + * @mode:    Corresponding drm_display_mode for dpu encoder
>>>>>>>>>> + */
>>>>>>>>>> +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
>>>>>>>>>> +                const struct drm_display_mode *mode);
>>>>>>>>>> +
>>>>>>>>>>       /**
>>>>>>>>>>        * dpu_encoder_get_crc_values_cnt - get number of physical encoders
>>>>>>>>>> contained
>>>>>>>>>>        *    in virtual encoder that can collect CRC values
>>>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>>>>>>>> index e284bf448bdda..a1dde0ff35dc8 100644
>>>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>>>>>>>> @@ -234,6 +234,7 @@ static void
>>>>>>>>>> dpu_encoder_phys_vid_setup_timing_engine(
>>>>>>>>>>       {
>>>>>>>>>>           struct drm_display_mode mode;
>>>>>>>>>>           struct dpu_hw_intf_timing_params timing_params = { 0 };
>>>>>>>>>> +    struct dpu_hw_cdm *hw_cdm;
>>>>>>>>>>           const struct dpu_format *fmt = NULL;
>>>>>>>>>>           u32 fmt_fourcc = DRM_FORMAT_RGB888;
>>>>>>>>>>           unsigned long lock_flags;
>>>>>>>>>> @@ -254,17 +255,26 @@ static void
>>>>>>>>>> dpu_encoder_phys_vid_setup_timing_engine(
>>>>>>>>>>           DPU_DEBUG_VIDENC(phys_enc, "enabling mode:\n");
>>>>>>>>>>           drm_mode_debug_printmodeline(&mode);
>>>>>>>>>>       -    if (phys_enc->split_role != ENC_ROLE_SOLO) {
>>>>>>>>>> +    hw_cdm = phys_enc->hw_cdm;
>>>>>>>>>> +    if (hw_cdm) {
>>>>>>>>>> +        intf_cfg.cdm = hw_cdm->idx;
>>>>>>>>>> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent, &mode);
>>>>>>>>>> +    }
>>>>>>>>>> +
>>>>>>>>>> +    if (phys_enc->split_role != ENC_ROLE_SOLO ||
>>>>>>>>>> +        dpu_encoder_get_drm_fmt(phys_enc->parent, &mode) ==
>>>>>>>>>> DRM_FORMAT_YUV420) {
>>>>>>>>>>               mode.hdisplay >>= 1;
>>>>>>>>>>               mode.htotal >>= 1;
>>>>>>>>>>               mode.hsync_start >>= 1;
>>>>>>>>>>               mode.hsync_end >>= 1;
>>>>>>>>>> +        mode.hskew >>= 1;
>>>>>>>>>
>>>>>>>>> Separate patch.
>>>>>>>> Ack.
>>>>>>>>>
>>>>>>>>>>                 DPU_DEBUG_VIDENC(phys_enc,
>>>>>>>>>> -            "split_role %d, halve horizontal %d %d %d %d\n",
>>>>>>>>>> +            "split_role %d, halve horizontal %d %d %d %d %d\n",
>>>>>>>>>>                   phys_enc->split_role,
>>>>>>>>>>                   mode.hdisplay, mode.htotal,
>>>>>>>>>> -            mode.hsync_start, mode.hsync_end);
>>>>>>>>>> +            mode.hsync_start, mode.hsync_end,
>>>>>>>>>> +            mode.hskew);
>>>>>>>>>>           }
>>>>>>>>>>             drm_mode_to_intf_timing_params(phys_enc, &mode, &timing_params);
>>>>>>>>>> @@ -412,8 +422,15 @@ static int dpu_encoder_phys_vid_control_vblank_irq(
>>>>>>>>>>       static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys
>>>>>>>>>> *phys_enc)
>>>>>>>>>>       {
>>>>>>>>>>           struct dpu_hw_ctl *ctl;
>>>>>>>>>> +    struct dpu_hw_cdm *hw_cdm;
>>>>>>>>>> +    const struct dpu_format *fmt = NULL;
>>>>>>>>>> +    u32 fmt_fourcc = DRM_FORMAT_RGB888;
>>>>>>>>>>             ctl = phys_enc->hw_ctl;
>>>>>>>>>> +    hw_cdm = phys_enc->hw_cdm;
>>>>>>>>>> +    if (hw_cdm)
>>>>>>>>>> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent,
>>>>>>>>>> &phys_enc->cached_mode);
>>>>>>>>>> +    fmt = dpu_get_dpu_format(fmt_fourcc);
>>>>>>>>>>             DPU_DEBUG_VIDENC(phys_enc, "\n");
>>>>>>>>>>       @@ -422,6 +439,8 @@ static void dpu_encoder_phys_vid_enable(struct
>>>>>>>>>> dpu_encoder_phys *phys_enc)
>>>>>>>>>>             dpu_encoder_helper_split_config(phys_enc,
>>>>>>>>>> phys_enc->hw_intf->idx);
>>>>>>>>>>       +    dpu_encoder_helper_phys_setup_cdm(phys_enc, fmt,
>>>>>>>>>> CDM_CDWN_OUTPUT_HDMI);
>>>>>>>>>
>>>>>>>>> If there is no CDM, why do we need to call this?
>>>>>>>> Inside of dpu_encoder_helper_phys_setup_cdm(), there's a check to see if
>>>>>>>> there is a hw_cdm. If there is not, then it immediately exits the function.
>>>>>>>>>
>>>>>>>>>> +
>>>>>>>>>>           dpu_encoder_phys_vid_setup_timing_engine(phys_enc);
>>>>>>>>>>             /*
>>>>>>>>>> @@ -437,7 +456,15 @@ static void dpu_encoder_phys_vid_enable(struct
>>>>>>>>>> dpu_encoder_phys *phys_enc)
>>>>>>>>>>           if (ctl->ops.update_pending_flush_merge_3d &&
>>>>>>>>>> phys_enc->hw_pp->merge_3d)
>>>>>>>>>>               ctl->ops.update_pending_flush_merge_3d(ctl,
>>>>>>>>>> phys_enc->hw_pp->merge_3d->idx);
>>>>>>>>>>       -    if (ctl->ops.update_pending_flush_periph &&
>>>>>>>>>> phys_enc->hw_intf->cap->type == INTF_DP)
>>>>>>>>>> +    if (ctl->ops.update_pending_flush_cdm && phys_enc->hw_cdm)
>>>>>>>>>> +        ctl->ops.update_pending_flush_cdm(ctl, hw_cdm->idx);
>>>>>>>>>> +
>>>>>>>>>> +    /*
>>>>>>>>>> +     * Peripheral flush must be updated whenever flushing SDP
>>>>>>>>>> packets is needed.
>>>>>>>>>> +     * SDP packets are required for any YUV format (YUV420, YUV422,
>>>>>>>>>> YUV444).
>>>>>>>>>> +     */
>>>>>>>>>> +    if (ctl->ops.update_pending_flush_periph &&
>>>>>>>>>> phys_enc->hw_intf->cap->type == INTF_DP &&
>>>>>>>>>> +        phys_enc->hw_cdm)
>>>>>>>>>>               ctl->ops.update_pending_flush_periph(ctl,
>>>>>>>>>> phys_enc->hw_intf->idx);
>>>>>>>>>
>>>>>>>>> Should there be a flush if we are switching from YUV 420 to RGB mode?
>>>>>>>> We only need to flush for the sdp packet, but for msa we do not need to
>>>>>>>> flush.
>>>>>>>
>>>>>>> What about having SDP with RGB as colorimetry? In other words, if
>>>>>>> there is a decision point, this one looks incorrect.
>>>>>>>
>>>>>>
>>>>>> There are two ways to do it:
>>>>>>
>>>>>> 1) Use SDP for both RGB and YUV as that supports both. If we implement
>>>>>> this policy, then what you are asking for is correct that we will need
>>>>>> SDP even to switch back to RGB. But to implement this we will also need
>>>>>> to have some sort of state management in the encoder layer about what is
>>>>>> the current encoder fmt Vs what is the prev fmt and then trigger
>>>>>> peripheral flush only during transitions from RGB to YUV and vice-versa
>>>>>>
>>>>>> 2) Use SDP only for YUV because MSA does not support YUV formats and use
>>>>>> MSA for RGB
>>>>>>
>>>>>> We decided to implement (2) and there is no significant impact of
>>>>>> switching between MSA and SDPs but state management becomes easier.
>>>>>
>>>>> Yes. However as you wrote, there might be other usecases concerning
>>>>> SDP. Having this in mind, it sounds like the driver should decide
>>>>> whether to flush peripheral at a different place (when the SDP
>>>>> infoframe is being updated?). And the dpu_encoder_phys_vid_enable()
>>>>> should use this previous decision. Maybe this should be a part of
>>>>> msm_dp_ API, something like msm_dp_needs_peripheral_flush()?
>>>>>
>>>>
>>>> Correct. The decision to flush peripheral or not certainly comes from
>>>> the peripheral itself . In this case its DP.
>>>>
>>>> I think perhaps the usage of hw_cdm here makes it hard to understand
>>>> that but the idea behind this was that in the change "drm/msm/dpu:
>>>> reserve CDM blocks for DP if mode is YUV420 ", hw_cdm is assigned only
>>>> if msm_dp_is_yuv_420_enabled() returns true.
>>>
>>> Yes.
>>>
>>>>
>>>> So in some sense, the API you are asking for is already
>>>> msm_dp_is_yuv_420_enabled() but we can rename that to
>>>> msm_dp_needs_periph_flush().
>>>
>>> No. This leaks details. We might need peripheral flush for other
>>> reasons. So this decision should be made inside the DP driver.
>>> BTW, is there a need to flush-peripheral each time the INTF gets
>>> enabled? When some bits of configuration were updated (like SDP
>>> infoframe or CDM config)?
>>>
>>
>> Not really leaking any details. Interface decides when DPU's flush bit
>> needs to be invoked. All the conditions needing the flush can be
>> absorbed within msm_dp_needs_periph_flush() which will be within DP
>> driver. So I dont see any issue with that.
> 
> As long as we have two distinct functions: msm_dp_needs_periph_flush()
> and msm_dp_is_yuv420_enabled(), it's fine with me.
> 

I am okay with it being distinct but in this series and till DP DSC is 
posted, we have only YUV420 SDP use-case for peripheral flush.

So are you okay with the fact that the code will look something like

bool msm_dp_needs_periph_flush() {
	return msm_dp_is_yuv420_enabled();
}

>>
>> The peripheral flush needs to be invoked whenever SDP/PPS packets need
>> to be sent out at the very least. Those are the two main use-cases so far.
>>
>> Not necessarily each time the INTF is enabled.
>>
>> But ....
>>
>> For PPS, we would typically enable DSC from the first frame itself and
>> we dont support dynamically turning DSC ON/OFF so its a fair assumption
>> that we need to the peripheral flush for DSC only during enable.
>>
>> For SDP, so today we enforce a modeset when we switch from a case of
>> needing cdm / not needing cdm and vice-versa. So even this use-case
>> should be accompanied by a disable()/enable().
> 
> My point was that there might be other changes to the SDP infoframe.
> 
>>
>> So are you suggesting that we unconditionally just do peripheral_flush
>> from enable()?
>>
>> I need to do some checking but maybe ....
> 
> This might be an option too. I don't know what delays / issues it can cause.
> 

I will check this if the other option we discussed above does not work 
for you.

>>
>>>>
>>>> The issue here is the phys layer cannot call msm_dp_is_yuv_420_enabled()
>>>> so its kind of round-about by checking hw_cdm.
>>>
>>> Which maybe means that I should finish phys / encoder rework.
>>>
>>
>> Ugh no. Not another rework just for this.
> 
> It is pending for the CTL flush story.
> 
>>
>>>>
>>>> The check is not entirely wrong because for DP, we need hw_cdm for all
>>>> YUV formats and not just 420 but the relationship is maybe not clear but
>>>> I thought the comment above that would help a bit:
>>>>
>>>> /*
>>>>            * Peripheral flush must be updated whenever flushing SDP packets is
>>>> needed.
>>>>            * SDP packets are required for any YUV format (YUV420, YUV422, YUV444).
>>>>            */
>>>>
>>>> The only other way I can think of is maybe we need to introduce a new
>>>> phys variable called phys_enc->needs_update_periph_flush and we can set
>>>> that in dpu_encoder.c as that can call msm_dp_needs_periph_flush().
>>>>
>>>> What do you think of this way?
>>>
>>> Let me understand first the requirements for peripheral flush (see the
>>> questions above).
>>>
>>>>
>>>>>>
>>>>>>>>>
>>>>>>>>> Also, I'd say, we should move update_pending_flush_periph invocation
>>>>>>>>> to this patch.
>>>>>>>> Ack
>>>>>>>>>
>>>>>>>>>>         skip_flush:
>>>>>>>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c
>>>>>>>>>> b/drivers/gpu/drm/msm/dp/dp_display.c
>>>>>>>>>> index 6d764f5b08727..4329435518351 100644
>>>>>>>>>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
>>>>>>>>>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
>>>>>>>>>> @@ -1399,6 +1399,18 @@ void __exit msm_dp_unregister(void)
>>>>>>>>>>           platform_driver_unregister(&dp_display_driver);
>>>>>>>>>>       }
>>>>>>>>>>       +bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
>>>>>>>>>> +                   const struct drm_display_mode *mode)
>>>>>>>>>> +{
>>>>>>>>>> +    struct dp_display_private *dp;
>>>>>>>>>> +    const struct drm_display_info *info;
>>>>>>>>>> +
>>>>>>>>>> +    dp = container_of(dp_display, struct dp_display_private,
>>>>>>>>>> dp_display);
>>>>>>>>>> +    info = &dp_display->connector->display_info;
>>>>>>>>>> +
>>>>>>>>>> +    return dp_panel_vsc_sdp_supported(dp->panel) &&
>>>>>>>>>> drm_mode_is_420_only(info, mode);
>>>>>>>>>
>>>>>>>>> YUV 420 modes should be filtered out in mode_valid if VSC SDP is not
>>>>>>>>> supported.
>>>>>>>> Ack. Will change
>>>>>>>>>
>>>>>>>>>> +}
>>>>>>>>>> +
>>>>>>>>>>       bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)
>>>>>>>>>>       {
>>>>>>>>>>           struct dp_display_private *dp;
>>>>>>>>>> diff --git a/drivers/gpu/drm/msm/msm_drv.h
>>>>>>>>>> b/drivers/gpu/drm/msm/msm_drv.h
>>>>>>>>>> index 16a7cbc0b7dd8..b9581bd934e9e 100644
>>>>>>>>>> --- a/drivers/gpu/drm/msm/msm_drv.h
>>>>>>>>>> +++ b/drivers/gpu/drm/msm/msm_drv.h
>>>>>>>>>> @@ -387,7 +387,8 @@ void __exit msm_dp_unregister(void);
>>>>>>>>>>       int msm_dp_modeset_init(struct msm_dp *dp_display, struct
>>>>>>>>>> drm_device *dev,
>>>>>>>>>>                    struct drm_encoder *encoder);
>>>>>>>>>>       void msm_dp_snapshot(struct msm_disp_state *disp_state, struct
>>>>>>>>>> msm_dp *dp_display);
>>>>>>>>>> -
>>>>>>>>>> +bool msm_dp_is_yuv_420_enabled(const struct msm_dp *dp_display,
>>>>>>>>>> +                   const struct drm_display_mode *mode);
>>>>>>>>>>       bool msm_dp_wide_bus_available(const struct msm_dp *dp_display);
>>>>>>>>>>         #else
>>>>>>>>>> @@ -409,6 +410,12 @@ static inline void msm_dp_snapshot(struct
>>>>>>>>>> msm_disp_state *disp_state, struct msm
>>>>>>>>>>       {
>>>>>>>>>>       }
>>>>>>>>>>       +static inline bool msm_dp_is_yuv_420_enabled(const struct msm_dp
>>>>>>>>>> *dp_display,
>>>>>>>>>> +                         const struct drm_display_mode *mode)
>>>>>>>>>> +{
>>>>>>>>>> +    return false;
>>>>>>>>>> +}
>>>>>>>>>> +
>>>>>>>>>>       static inline bool msm_dp_wide_bus_available(const struct msm_dp
>>>>>>>>>> *dp_display)
>>>>>>>>>>       {
>>>>>>>>>>           return false;
>>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> With best wishes
>>>>>>> Dmitry
>>>>>
>>>>>
>>>>>
>>>
>>>
>>>
> 
> 
> 
> --
> With best wishes
> Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 11/17] drm/msm/dp: add VSC SDP support for YUV420 over DP
  2024-01-28  5:39       ` Dmitry Baryshkov
@ 2024-02-01  1:56         ` Abhinav Kumar
  2024-02-01  4:36           ` Dmitry Baryshkov
  0 siblings, 1 reply; 95+ messages in thread
From: Abhinav Kumar @ 2024-02-01  1:56 UTC (permalink / raw)
  To: Dmitry Baryshkov, Paloma Arellano
  Cc: neil.armstrong, linux-arm-msm, dri-devel, swboyd, seanpaul,
	marijn.suijten, quic_jesszhan, quic_khsieh, freedreno



On 1/27/2024 9:39 PM, Dmitry Baryshkov wrote:
> On Sun, 28 Jan 2024 at 07:34, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>>
>>
>> On 1/25/2024 1:48 PM, Dmitry Baryshkov wrote:
>>> On 25/01/2024 21:38, Paloma Arellano wrote:
>>>> Add support to pack and send the VSC SDP packet for DP. This therefore
>>>> allows the transmision of format information to the sinks which is
>>>> needed for YUV420 support over DP.
>>>>
>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>>> ---
>>>>    drivers/gpu/drm/msm/dp/dp_catalog.c | 147 ++++++++++++++++++++++++++++
>>>>    drivers/gpu/drm/msm/dp/dp_catalog.h |   4 +
>>>>    drivers/gpu/drm/msm/dp/dp_ctrl.c    |   4 +
>>>>    drivers/gpu/drm/msm/dp/dp_panel.c   |  47 +++++++++
>>>>    drivers/gpu/drm/msm/dp/dp_reg.h     |   3 +
>>>>    5 files changed, 205 insertions(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c
>>>> b/drivers/gpu/drm/msm/dp/dp_catalog.c
>>>> index c025786170ba5..7e4c68be23e56 100644
>>>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
>>>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
>>>> @@ -29,6 +29,9 @@
>>>>      #define DP_INTF_CONFIG_DATABUS_WIDEN     BIT(4)
>>>>    +#define DP_GENERIC0_6_YUV_8_BPC        BIT(0)
>>>> +#define DP_GENERIC0_6_YUV_10_BPC    BIT(1)
>>>> +
>>>>    #define DP_INTERRUPT_STATUS1 \
>>>>        (DP_INTR_AUX_XFER_DONE| \
>>>>        DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \
>>>> @@ -907,6 +910,150 @@ int dp_catalog_panel_timing_cfg(struct
>>>> dp_catalog *dp_catalog)
>>>>        return 0;
>>>>    }
>>>>    +static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog
>>>> *dp_catalog)
>>>> +{
>>>> +    struct dp_catalog_private *catalog;
>>>> +    u32 header, parity, data;
>>>> +    u8 bpc, off = 0;
>>>> +    u8 buf[SZ_128];
>>>> +
>>>> +    if (!dp_catalog) {
>>>> +        pr_err("invalid input\n");
>>>> +        return;
>>>> +    }
>>>> +
>>>> +    catalog = container_of(dp_catalog, struct dp_catalog_private,
>>>> dp_catalog);
>>>> +
>>>> +    /* HEADER BYTE 1 */
>>>> +    header = dp_catalog->sdp.sdp_header.HB1;
>>>> +    parity = dp_catalog_calculate_parity(header);
>>>> +    data   = ((header << HEADER_BYTE_1_BIT) | (parity <<
>>>> PARITY_BYTE_1_BIT));
>>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_0, data);
>>>> +    memcpy(buf + off, &data, sizeof(data));
>>>> +    off += sizeof(data);
>>>> +
>>>> +    /* HEADER BYTE 2 */
>>>> +    header = dp_catalog->sdp.sdp_header.HB2;
>>>> +    parity = dp_catalog_calculate_parity(header);
>>>> +    data   = ((header << HEADER_BYTE_2_BIT) | (parity <<
>>>> PARITY_BYTE_2_BIT));
>>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_1, data);
>>>> +
>>>> +    /* HEADER BYTE 3 */
>>>> +    header = dp_catalog->sdp.sdp_header.HB3;
>>>> +    parity = dp_catalog_calculate_parity(header);
>>>> +    data   = ((header << HEADER_BYTE_3_BIT) | (parity <<
>>>> PARITY_BYTE_3_BIT));
>>>> +    data |= dp_read_link(catalog, MMSS_DP_GENERIC0_1);
>>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_1, data);
>>>> +    memcpy(buf + off, &data, sizeof(data));
>>>> +    off += sizeof(data);
>>>
>>> This seems to be common with the dp_audio code. Please extract this
>>> header writing too.
>> These are two different sdp's. audio and vsc, are different with
>> different registers being written to and different amount of registers
>> being set. Can you please clarify since in audio we only need 3
>> registers to write to, and in vsc we need 10.
> 
> Bitmagic with the header is the same. Then the rest of the data is
> written one dword per register, if I'm not mistaken.
> 

We can generalize the MMSS_DP_GENERIC0 register writing by breaking it 
up to two things:

1) Add a function vsc_sdp_pack() similar to hdmi_avi_infoframe_pack_only()

2) dp_catalog_write_generic_pkt() which will just write the packed 
buffer byte-by-byte to these MMSS_DP_GENERIC0_xxx register

But audio seems a bit different. We use DP_AUDIO_STREAM_0/1.
More importantly, it uses this sdp_map and writes each header one by one 
with dp_catalog_audio_set_header().

Not sure if that entirely fits with this pack and then write model.

It can be simplified. But I dont think this effort is needed for this 
series.

So I would prefer to generalize audio SDP programming separately.

>>>
>>>> +
>>>> +    data = 0;
>>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_2, data);
>>>> +    memcpy(buf + off, &data, sizeof(data));
>>>> +    off += sizeof(data);
>>>
>>> Generally this is not how these functions are expected to be written.
>>> Please take a look at drivers/video/hdmi.c. It should be split into:
>>> - generic function that packs the C structure into a flat byte buffer,
>>> - driver-specific function that formats and writes the buffer to the
>>> hardware.
>>>
>>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_3, data);
>>>> +    memcpy(buf + off, &data, sizeof(data));
>>>> +    off += sizeof(data);
>>>> +
>>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_4, data);
>>>> +    memcpy(buf + off, &data, sizeof(data));
>>>> +    off += sizeof(data);
>>>> +
>>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_5, data);
>>>> +    memcpy(buf + off, &data, sizeof(data));
>>>> +    off += sizeof(data);
>>>> +
>>>> +    switch (dp_catalog->vsc_sdp_data.bpc) {
>>>> +    case 10:
>>>> +        bpc = DP_GENERIC0_6_YUV_10_BPC;
>>>> +        break;
>>>> +    case 8:
>>>> +    default:
>>>> +        bpc = DP_GENERIC0_6_YUV_8_BPC;
>>>> +        break;
>>>> +    }
>>>> +
>>>> +    /* VSC SDP payload as per table 2-117 of DP 1.4 specification */
>>>> +    data = (dp_catalog->vsc_sdp_data.colorimetry & 0xF) |
>>>> +           ((dp_catalog->vsc_sdp_data.pixelformat & 0xF) << 4) |
>>>> +           (bpc << 8) |
>>>> +           ((dp_catalog->vsc_sdp_data.dynamic_range & 0x1) << 15) |
>>>> +           ((dp_catalog->vsc_sdp_data.content_type & 0x7) << 16);
>>>> +
>>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_6, data);
>>>> +    memcpy(buf + off, &data, sizeof(data));
>>>> +    off += sizeof(data);
>>>> +
>>>> +    data = 0;
>>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_7, data);
>>>> +    memcpy(buf + off, &data, sizeof(data));
>>>> +    off += sizeof(data);
>>>> +
>>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_8, data);
>>>> +    memcpy(buf + off, &data, sizeof(data));
>>>> +    off += sizeof(data);
> 
> 

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 14/17] drm/msm/dpu: modify encoder programming for CDM over DP
  2024-02-01  1:30                     ` Abhinav Kumar
@ 2024-02-01  3:17                       ` Dmitry Baryshkov
  2024-02-01 19:01                         ` Abhinav Kumar
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-02-01  3:17 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno

On Thu, 1 Feb 2024 at 03:30, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 1/29/2024 3:44 PM, Dmitry Baryshkov wrote:
> > On Mon, 29 Jan 2024 at 09:08, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >> On 1/28/2024 10:12 PM, Dmitry Baryshkov wrote:
> >>> On Mon, 29 Jan 2024 at 07:03, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>>>
> >>>>
> >>>>
> >>>> On 1/28/2024 7:42 PM, Dmitry Baryshkov wrote:
> >>>>> On Mon, 29 Jan 2024 at 04:58, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>> On 1/27/2024 9:55 PM, Dmitry Baryshkov wrote:
> >>>>>>> On Sun, 28 Jan 2024 at 07:48, Paloma Arellano <quic_parellan@quicinc.com> wrote:
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> On 1/25/2024 1:57 PM, Dmitry Baryshkov wrote:
> >>>>>>>>> On 25/01/2024 21:38, Paloma Arellano wrote:
> >>>>>>>>>> Adjust the encoder format programming in the case of video mode for DP
> >>>>>>>>>> to accommodate CDM related changes.
> >>>>>>>>>>
> >>>>>>>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >>>>>>>>>> ---
> >>>>>>>>>>       drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 16 +++++++++
> >>>>>>>>>>       drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |  8 +++++
> >>>>>>>>>>       .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 35 ++++++++++++++++---
> >>>>>>>>>>       drivers/gpu/drm/msm/dp/dp_display.c           | 12 +++++++
> >>>>>>>>>>       drivers/gpu/drm/msm/msm_drv.h                 |  9 ++++-
> >>>>>>>>>>       5 files changed, 75 insertions(+), 5 deletions(-)
> >>>>>>>>>>
> >>>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >>>>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >>>>>>>>>> index b0896814c1562..99ec53446ad21 100644
> >>>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >>>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >>>>>>>>>> @@ -222,6 +222,22 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = {
> >>>>>>>>>>           15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10
> >>>>>>>>>>       };
> >>>>>>>>>>       +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
> >>>>>>>>>> const struct drm_display_mode *mode)
> >>>>>>>>>> +{
> >>>>>>>>>> +    const struct dpu_encoder_virt *dpu_enc;
> >>>>>>>>>> +    const struct msm_display_info *disp_info;
> >>>>>>>>>> +    struct msm_drm_private *priv;
> >>>>>>>>>> +
> >>>>>>>>>> +    dpu_enc = to_dpu_encoder_virt(drm_enc);
> >>>>>>>>>> +    disp_info = &dpu_enc->disp_info;
> >>>>>>>>>> +    priv = drm_enc->dev->dev_private;
> >>>>>>>>>> +
> >>>>>>>>>> +    if (disp_info->intf_type == INTF_DP &&
> >>>>>>>>>> + msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]],
> >>>>>>>>>> mode))
> >>>>>>>>>
> >>>>>>>>> This should not require interacting with DP. If we got here, we must
> >>>>>>>>> be sure that 4:2:0 is supported and can be configured.
> >>>>>>>> Ack. Will drop this function and only check for if the mode is YUV420.
> >>>>>>>>>
> >>>>>>>>>> +        return DRM_FORMAT_YUV420;
> >>>>>>>>>> +
> >>>>>>>>>> +    return DRM_FORMAT_RGB888;
> >>>>>>>>>> +}
> >>>>>>>>>>         bool dpu_encoder_is_widebus_enabled(const struct drm_encoder
> >>>>>>>>>> *drm_enc)
> >>>>>>>>>>       {
> >>>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> >>>>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> >>>>>>>>>> index 7b4afa71f1f96..62255d0aa4487 100644
> >>>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> >>>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> >>>>>>>>>> @@ -162,6 +162,14 @@ int dpu_encoder_get_vsync_count(struct
> >>>>>>>>>> drm_encoder *drm_enc);
> >>>>>>>>>>        */
> >>>>>>>>>>       bool dpu_encoder_is_widebus_enabled(const struct drm_encoder
> >>>>>>>>>> *drm_enc);
> >>>>>>>>>>       +/**
> >>>>>>>>>> + * dpu_encoder_get_drm_fmt - return DRM fourcc format
> >>>>>>>>>> + * @drm_enc:    Pointer to previously created drm encoder structure
> >>>>>>>>>> + * @mode:    Corresponding drm_display_mode for dpu encoder
> >>>>>>>>>> + */
> >>>>>>>>>> +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
> >>>>>>>>>> +                const struct drm_display_mode *mode);
> >>>>>>>>>> +
> >>>>>>>>>>       /**
> >>>>>>>>>>        * dpu_encoder_get_crc_values_cnt - get number of physical encoders
> >>>>>>>>>> contained
> >>>>>>>>>>        *    in virtual encoder that can collect CRC values
> >>>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >>>>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >>>>>>>>>> index e284bf448bdda..a1dde0ff35dc8 100644
> >>>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >>>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
> >>>>>>>>>> @@ -234,6 +234,7 @@ static void
> >>>>>>>>>> dpu_encoder_phys_vid_setup_timing_engine(
> >>>>>>>>>>       {
> >>>>>>>>>>           struct drm_display_mode mode;
> >>>>>>>>>>           struct dpu_hw_intf_timing_params timing_params = { 0 };
> >>>>>>>>>> +    struct dpu_hw_cdm *hw_cdm;
> >>>>>>>>>>           const struct dpu_format *fmt = NULL;
> >>>>>>>>>>           u32 fmt_fourcc = DRM_FORMAT_RGB888;
> >>>>>>>>>>           unsigned long lock_flags;
> >>>>>>>>>> @@ -254,17 +255,26 @@ static void
> >>>>>>>>>> dpu_encoder_phys_vid_setup_timing_engine(
> >>>>>>>>>>           DPU_DEBUG_VIDENC(phys_enc, "enabling mode:\n");
> >>>>>>>>>>           drm_mode_debug_printmodeline(&mode);
> >>>>>>>>>>       -    if (phys_enc->split_role != ENC_ROLE_SOLO) {
> >>>>>>>>>> +    hw_cdm = phys_enc->hw_cdm;
> >>>>>>>>>> +    if (hw_cdm) {
> >>>>>>>>>> +        intf_cfg.cdm = hw_cdm->idx;
> >>>>>>>>>> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent, &mode);
> >>>>>>>>>> +    }
> >>>>>>>>>> +
> >>>>>>>>>> +    if (phys_enc->split_role != ENC_ROLE_SOLO ||
> >>>>>>>>>> +        dpu_encoder_get_drm_fmt(phys_enc->parent, &mode) ==
> >>>>>>>>>> DRM_FORMAT_YUV420) {
> >>>>>>>>>>               mode.hdisplay >>= 1;
> >>>>>>>>>>               mode.htotal >>= 1;
> >>>>>>>>>>               mode.hsync_start >>= 1;
> >>>>>>>>>>               mode.hsync_end >>= 1;
> >>>>>>>>>> +        mode.hskew >>= 1;
> >>>>>>>>>
> >>>>>>>>> Separate patch.
> >>>>>>>> Ack.
> >>>>>>>>>
> >>>>>>>>>>                 DPU_DEBUG_VIDENC(phys_enc,
> >>>>>>>>>> -            "split_role %d, halve horizontal %d %d %d %d\n",
> >>>>>>>>>> +            "split_role %d, halve horizontal %d %d %d %d %d\n",
> >>>>>>>>>>                   phys_enc->split_role,
> >>>>>>>>>>                   mode.hdisplay, mode.htotal,
> >>>>>>>>>> -            mode.hsync_start, mode.hsync_end);
> >>>>>>>>>> +            mode.hsync_start, mode.hsync_end,
> >>>>>>>>>> +            mode.hskew);
> >>>>>>>>>>           }
> >>>>>>>>>>             drm_mode_to_intf_timing_params(phys_enc, &mode, &timing_params);
> >>>>>>>>>> @@ -412,8 +422,15 @@ static int dpu_encoder_phys_vid_control_vblank_irq(
> >>>>>>>>>>       static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys
> >>>>>>>>>> *phys_enc)
> >>>>>>>>>>       {
> >>>>>>>>>>           struct dpu_hw_ctl *ctl;
> >>>>>>>>>> +    struct dpu_hw_cdm *hw_cdm;
> >>>>>>>>>> +    const struct dpu_format *fmt = NULL;
> >>>>>>>>>> +    u32 fmt_fourcc = DRM_FORMAT_RGB888;
> >>>>>>>>>>             ctl = phys_enc->hw_ctl;
> >>>>>>>>>> +    hw_cdm = phys_enc->hw_cdm;
> >>>>>>>>>> +    if (hw_cdm)
> >>>>>>>>>> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent,
> >>>>>>>>>> &phys_enc->cached_mode);
> >>>>>>>>>> +    fmt = dpu_get_dpu_format(fmt_fourcc);
> >>>>>>>>>>             DPU_DEBUG_VIDENC(phys_enc, "\n");
> >>>>>>>>>>       @@ -422,6 +439,8 @@ static void dpu_encoder_phys_vid_enable(struct
> >>>>>>>>>> dpu_encoder_phys *phys_enc)
> >>>>>>>>>>             dpu_encoder_helper_split_config(phys_enc,
> >>>>>>>>>> phys_enc->hw_intf->idx);
> >>>>>>>>>>       +    dpu_encoder_helper_phys_setup_cdm(phys_enc, fmt,
> >>>>>>>>>> CDM_CDWN_OUTPUT_HDMI);
> >>>>>>>>>
> >>>>>>>>> If there is no CDM, why do we need to call this?
> >>>>>>>> Inside of dpu_encoder_helper_phys_setup_cdm(), there's a check to see if
> >>>>>>>> there is a hw_cdm. If there is not, then it immediately exits the function.
> >>>>>>>>>
> >>>>>>>>>> +
> >>>>>>>>>>           dpu_encoder_phys_vid_setup_timing_engine(phys_enc);
> >>>>>>>>>>             /*
> >>>>>>>>>> @@ -437,7 +456,15 @@ static void dpu_encoder_phys_vid_enable(struct
> >>>>>>>>>> dpu_encoder_phys *phys_enc)
> >>>>>>>>>>           if (ctl->ops.update_pending_flush_merge_3d &&
> >>>>>>>>>> phys_enc->hw_pp->merge_3d)
> >>>>>>>>>>               ctl->ops.update_pending_flush_merge_3d(ctl,
> >>>>>>>>>> phys_enc->hw_pp->merge_3d->idx);
> >>>>>>>>>>       -    if (ctl->ops.update_pending_flush_periph &&
> >>>>>>>>>> phys_enc->hw_intf->cap->type == INTF_DP)
> >>>>>>>>>> +    if (ctl->ops.update_pending_flush_cdm && phys_enc->hw_cdm)
> >>>>>>>>>> +        ctl->ops.update_pending_flush_cdm(ctl, hw_cdm->idx);
> >>>>>>>>>> +
> >>>>>>>>>> +    /*
> >>>>>>>>>> +     * Peripheral flush must be updated whenever flushing SDP
> >>>>>>>>>> packets is needed.
> >>>>>>>>>> +     * SDP packets are required for any YUV format (YUV420, YUV422,
> >>>>>>>>>> YUV444).
> >>>>>>>>>> +     */
> >>>>>>>>>> +    if (ctl->ops.update_pending_flush_periph &&
> >>>>>>>>>> phys_enc->hw_intf->cap->type == INTF_DP &&
> >>>>>>>>>> +        phys_enc->hw_cdm)
> >>>>>>>>>>               ctl->ops.update_pending_flush_periph(ctl,
> >>>>>>>>>> phys_enc->hw_intf->idx);
> >>>>>>>>>
> >>>>>>>>> Should there be a flush if we are switching from YUV 420 to RGB mode?
> >>>>>>>> We only need to flush for the sdp packet, but for msa we do not need to
> >>>>>>>> flush.
> >>>>>>>
> >>>>>>> What about having SDP with RGB as colorimetry? In other words, if
> >>>>>>> there is a decision point, this one looks incorrect.
> >>>>>>>
> >>>>>>
> >>>>>> There are two ways to do it:
> >>>>>>
> >>>>>> 1) Use SDP for both RGB and YUV as that supports both. If we implement
> >>>>>> this policy, then what you are asking for is correct that we will need
> >>>>>> SDP even to switch back to RGB. But to implement this we will also need
> >>>>>> to have some sort of state management in the encoder layer about what is
> >>>>>> the current encoder fmt Vs what is the prev fmt and then trigger
> >>>>>> peripheral flush only during transitions from RGB to YUV and vice-versa
> >>>>>>
> >>>>>> 2) Use SDP only for YUV because MSA does not support YUV formats and use
> >>>>>> MSA for RGB
> >>>>>>
> >>>>>> We decided to implement (2) and there is no significant impact of
> >>>>>> switching between MSA and SDPs but state management becomes easier.
> >>>>>
> >>>>> Yes. However as you wrote, there might be other usecases concerning
> >>>>> SDP. Having this in mind, it sounds like the driver should decide
> >>>>> whether to flush peripheral at a different place (when the SDP
> >>>>> infoframe is being updated?). And the dpu_encoder_phys_vid_enable()
> >>>>> should use this previous decision. Maybe this should be a part of
> >>>>> msm_dp_ API, something like msm_dp_needs_peripheral_flush()?
> >>>>>
> >>>>
> >>>> Correct. The decision to flush peripheral or not certainly comes from
> >>>> the peripheral itself . In this case its DP.
> >>>>
> >>>> I think perhaps the usage of hw_cdm here makes it hard to understand
> >>>> that but the idea behind this was that in the change "drm/msm/dpu:
> >>>> reserve CDM blocks for DP if mode is YUV420 ", hw_cdm is assigned only
> >>>> if msm_dp_is_yuv_420_enabled() returns true.
> >>>
> >>> Yes.
> >>>
> >>>>
> >>>> So in some sense, the API you are asking for is already
> >>>> msm_dp_is_yuv_420_enabled() but we can rename that to
> >>>> msm_dp_needs_periph_flush().
> >>>
> >>> No. This leaks details. We might need peripheral flush for other
> >>> reasons. So this decision should be made inside the DP driver.
> >>> BTW, is there a need to flush-peripheral each time the INTF gets
> >>> enabled? When some bits of configuration were updated (like SDP
> >>> infoframe or CDM config)?
> >>>
> >>
> >> Not really leaking any details. Interface decides when DPU's flush bit
> >> needs to be invoked. All the conditions needing the flush can be
> >> absorbed within msm_dp_needs_periph_flush() which will be within DP
> >> driver. So I dont see any issue with that.
> >
> > As long as we have two distinct functions: msm_dp_needs_periph_flush()
> > and msm_dp_is_yuv420_enabled(), it's fine with me.
> >
>
> I am okay with it being distinct but in this series and till DP DSC is
> posted, we have only YUV420 SDP use-case for peripheral flush.
>
> So are you okay with the fact that the code will look something like
>
> bool msm_dp_needs_periph_flush() {
>         return msm_dp_is_yuv420_enabled();
> }

Yes. The reason is that if at some point conditions for periph flush
get changed, you won't have to change the API between DPU and DP
drivers.

>
> >>
> >> The peripheral flush needs to be invoked whenever SDP/PPS packets need
> >> to be sent out at the very least. Those are the two main use-cases so far.
> >>
> >> Not necessarily each time the INTF is enabled.
> >>
> >> But ....
> >>
> >> For PPS, we would typically enable DSC from the first frame itself and
> >> we dont support dynamically turning DSC ON/OFF so its a fair assumption
> >> that we need to the peripheral flush for DSC only during enable.
> >>
> >> For SDP, so today we enforce a modeset when we switch from a case of
> >> needing cdm / not needing cdm and vice-versa. So even this use-case
> >> should be accompanied by a disable()/enable().
> >
> > My point was that there might be other changes to the SDP infoframe.
> >
> >>
> >> So are you suggesting that we unconditionally just do peripheral_flush
> >> from enable()?
> >>
> >> I need to do some checking but maybe ....
> >
> > This might be an option too. I don't know what delays / issues it can cause.
> >
>
> I will check this if the other option we discussed above does not work
> for you.
>
> >>
> >>>>
> >>>> The issue here is the phys layer cannot call msm_dp_is_yuv_420_enabled()
> >>>> so its kind of round-about by checking hw_cdm.
> >>>
> >>> Which maybe means that I should finish phys / encoder rework.
> >>>
> >>
> >> Ugh no. Not another rework just for this.
> >
> > It is pending for the CTL flush story.
> >
> >>
> >>>>
> >>>> The check is not entirely wrong because for DP, we need hw_cdm for all
> >>>> YUV formats and not just 420 but the relationship is maybe not clear but
> >>>> I thought the comment above that would help a bit:
> >>>>
> >>>> /*
> >>>>            * Peripheral flush must be updated whenever flushing SDP packets is
> >>>> needed.
> >>>>            * SDP packets are required for any YUV format (YUV420, YUV422, YUV444).
> >>>>            */
> >>>>
> >>>> The only other way I can think of is maybe we need to introduce a new
> >>>> phys variable called phys_enc->needs_update_periph_flush and we can set
> >>>> that in dpu_encoder.c as that can call msm_dp_needs_periph_flush().
> >>>>
> >>>> What do you think of this way?
> >>>
> >>> Let me understand first the requirements for peripheral flush (see the
> >>> questions above).



-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 11/17] drm/msm/dp: add VSC SDP support for YUV420 over DP
  2024-02-01  1:56         ` Abhinav Kumar
@ 2024-02-01  4:36           ` Dmitry Baryshkov
  2024-02-02  6:25             ` Abhinav Kumar
  0 siblings, 1 reply; 95+ messages in thread
From: Dmitry Baryshkov @ 2024-02-01  4:36 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: neil.armstrong, marijn.suijten, linux-arm-msm, dri-devel, swboyd,
	seanpaul, quic_jesszhan, Paloma Arellano, quic_khsieh, freedreno

On Thu, 1 Feb 2024 at 03:56, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 1/27/2024 9:39 PM, Dmitry Baryshkov wrote:
> > On Sun, 28 Jan 2024 at 07:34, Paloma Arellano <quic_parellan@quicinc.com> wrote:
> >>
> >>
> >> On 1/25/2024 1:48 PM, Dmitry Baryshkov wrote:
> >>> On 25/01/2024 21:38, Paloma Arellano wrote:
> >>>> Add support to pack and send the VSC SDP packet for DP. This therefore
> >>>> allows the transmision of format information to the sinks which is
> >>>> needed for YUV420 support over DP.
> >>>>
> >>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >>>> ---
> >>>>    drivers/gpu/drm/msm/dp/dp_catalog.c | 147 ++++++++++++++++++++++++++++
> >>>>    drivers/gpu/drm/msm/dp/dp_catalog.h |   4 +
> >>>>    drivers/gpu/drm/msm/dp/dp_ctrl.c    |   4 +
> >>>>    drivers/gpu/drm/msm/dp/dp_panel.c   |  47 +++++++++
> >>>>    drivers/gpu/drm/msm/dp/dp_reg.h     |   3 +
> >>>>    5 files changed, 205 insertions(+)
> >>>>
> >>>> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c
> >>>> b/drivers/gpu/drm/msm/dp/dp_catalog.c
> >>>> index c025786170ba5..7e4c68be23e56 100644
> >>>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
> >>>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
> >>>> @@ -29,6 +29,9 @@
> >>>>      #define DP_INTF_CONFIG_DATABUS_WIDEN     BIT(4)
> >>>>    +#define DP_GENERIC0_6_YUV_8_BPC        BIT(0)
> >>>> +#define DP_GENERIC0_6_YUV_10_BPC    BIT(1)
> >>>> +
> >>>>    #define DP_INTERRUPT_STATUS1 \
> >>>>        (DP_INTR_AUX_XFER_DONE| \
> >>>>        DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \
> >>>> @@ -907,6 +910,150 @@ int dp_catalog_panel_timing_cfg(struct
> >>>> dp_catalog *dp_catalog)
> >>>>        return 0;
> >>>>    }
> >>>>    +static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog
> >>>> *dp_catalog)
> >>>> +{
> >>>> +    struct dp_catalog_private *catalog;
> >>>> +    u32 header, parity, data;
> >>>> +    u8 bpc, off = 0;
> >>>> +    u8 buf[SZ_128];
> >>>> +
> >>>> +    if (!dp_catalog) {
> >>>> +        pr_err("invalid input\n");
> >>>> +        return;
> >>>> +    }
> >>>> +
> >>>> +    catalog = container_of(dp_catalog, struct dp_catalog_private,
> >>>> dp_catalog);
> >>>> +
> >>>> +    /* HEADER BYTE 1 */
> >>>> +    header = dp_catalog->sdp.sdp_header.HB1;
> >>>> +    parity = dp_catalog_calculate_parity(header);
> >>>> +    data   = ((header << HEADER_BYTE_1_BIT) | (parity <<
> >>>> PARITY_BYTE_1_BIT));
> >>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_0, data);
> >>>> +    memcpy(buf + off, &data, sizeof(data));
> >>>> +    off += sizeof(data);
> >>>> +
> >>>> +    /* HEADER BYTE 2 */
> >>>> +    header = dp_catalog->sdp.sdp_header.HB2;
> >>>> +    parity = dp_catalog_calculate_parity(header);
> >>>> +    data   = ((header << HEADER_BYTE_2_BIT) | (parity <<
> >>>> PARITY_BYTE_2_BIT));
> >>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_1, data);
> >>>> +
> >>>> +    /* HEADER BYTE 3 */
> >>>> +    header = dp_catalog->sdp.sdp_header.HB3;
> >>>> +    parity = dp_catalog_calculate_parity(header);
> >>>> +    data   = ((header << HEADER_BYTE_3_BIT) | (parity <<
> >>>> PARITY_BYTE_3_BIT));
> >>>> +    data |= dp_read_link(catalog, MMSS_DP_GENERIC0_1);
> >>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_1, data);
> >>>> +    memcpy(buf + off, &data, sizeof(data));
> >>>> +    off += sizeof(data);
> >>>
> >>> This seems to be common with the dp_audio code. Please extract this
> >>> header writing too.
> >> These are two different sdp's. audio and vsc, are different with
> >> different registers being written to and different amount of registers
> >> being set. Can you please clarify since in audio we only need 3
> >> registers to write to, and in vsc we need 10.
> >
> > Bitmagic with the header is the same. Then the rest of the data is
> > written one dword per register, if I'm not mistaken.
> >
>
> We can generalize the MMSS_DP_GENERIC0 register writing by breaking it
> up to two things:
>
> 1) Add a function vsc_sdp_pack() similar to hdmi_avi_infoframe_pack_only()

Note, there is already a hdmi_audio_infoframe_pack_for_dp() function.
I think this patchset can add hdmi_colorimetry_infoframe_pack_for_dp()
[you can choose any other similar name that suits from your POV].

Also please extract the function that inits the dp_sdp_header. It can
be reused as is for both existing hdmi_audio_infoframe_pack_for_dp(),
your new function and the dp_audio code.

>
> 2) dp_catalog_write_generic_pkt() which will just write the packed
> buffer byte-by-byte to these MMSS_DP_GENERIC0_xxx register
>
> But audio seems a bit different. We use DP_AUDIO_STREAM_0/1.
> More importantly, it uses this sdp_map and writes each header one by one
> with dp_catalog_audio_set_header().
>
> Not sure if that entirely fits with this pack and then write model.
>
> It can be simplified. But I dont think this effort is needed for this
> series.
>
> So I would prefer to generalize audio SDP programming separately.

I'd definitely ask to add a utility function that merges 4 header
bytes with the parity data. We already have 5 instances of that code
in dp_audio.c, which is already too much by the number of 4. Adding
the 6th copy is NAKed.

BTW, I see both in this path and in dp_audio that the driver reads a
register, ORs it with the value for the next header byte and writes it
back to the hardware. Shouldn't the driver clear the corresponding
data bits first? I see the clears in the techpack, but not in the
upstream code. If my assumption is correct, we should end up with the
utility function that packs dp_sdp_header into u32[2], which can then
be used by both YUV and dp_audio code to just write two corresponding
registers.

BTW2: where is the rest of the audio infoframe? I see that the old
fbdev driver was at least clearing the first 4 bytes of the frame.

>
> >>>
> >>>> +
> >>>> +    data = 0;
> >>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_2, data);
> >>>> +    memcpy(buf + off, &data, sizeof(data));
> >>>> +    off += sizeof(data);
> >>>
> >>> Generally this is not how these functions are expected to be written.
> >>> Please take a look at drivers/video/hdmi.c. It should be split into:
> >>> - generic function that packs the C structure into a flat byte buffer,
> >>> - driver-specific function that formats and writes the buffer to the
> >>> hardware.
> >>>
> >>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_3, data);
> >>>> +    memcpy(buf + off, &data, sizeof(data));
> >>>> +    off += sizeof(data);
> >>>> +
> >>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_4, data);
> >>>> +    memcpy(buf + off, &data, sizeof(data));
> >>>> +    off += sizeof(data);
> >>>> +
> >>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_5, data);
> >>>> +    memcpy(buf + off, &data, sizeof(data));
> >>>> +    off += sizeof(data);
> >>>> +
> >>>> +    switch (dp_catalog->vsc_sdp_data.bpc) {
> >>>> +    case 10:
> >>>> +        bpc = DP_GENERIC0_6_YUV_10_BPC;
> >>>> +        break;
> >>>> +    case 8:
> >>>> +    default:
> >>>> +        bpc = DP_GENERIC0_6_YUV_8_BPC;
> >>>> +        break;
> >>>> +    }
> >>>> +
> >>>> +    /* VSC SDP payload as per table 2-117 of DP 1.4 specification */
> >>>> +    data = (dp_catalog->vsc_sdp_data.colorimetry & 0xF) |
> >>>> +           ((dp_catalog->vsc_sdp_data.pixelformat & 0xF) << 4) |
> >>>> +           (bpc << 8) |
> >>>> +           ((dp_catalog->vsc_sdp_data.dynamic_range & 0x1) << 15) |
> >>>> +           ((dp_catalog->vsc_sdp_data.content_type & 0x7) << 16);
> >>>> +
> >>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_6, data);
> >>>> +    memcpy(buf + off, &data, sizeof(data));
> >>>> +    off += sizeof(data);
> >>>> +
> >>>> +    data = 0;
> >>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_7, data);
> >>>> +    memcpy(buf + off, &data, sizeof(data));
> >>>> +    off += sizeof(data);
> >>>> +
> >>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_8, data);
> >>>> +    memcpy(buf + off, &data, sizeof(data));
> >>>> +    off += sizeof(data);
> >
> >



-- 
With best wishes
Dmitry

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 14/17] drm/msm/dpu: modify encoder programming for CDM over DP
  2024-02-01  3:17                       ` Dmitry Baryshkov
@ 2024-02-01 19:01                         ` Abhinav Kumar
  0 siblings, 0 replies; 95+ messages in thread
From: Abhinav Kumar @ 2024-02-01 19:01 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Paloma Arellano, freedreno, linux-arm-msm, dri-devel, robdclark,
	seanpaul, swboyd, quic_jesszhan, quic_khsieh, marijn.suijten,
	neil.armstrong



On 1/31/2024 7:17 PM, Dmitry Baryshkov wrote:
> On Thu, 1 Feb 2024 at 03:30, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 1/29/2024 3:44 PM, Dmitry Baryshkov wrote:
>>> On Mon, 29 Jan 2024 at 09:08, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>>>
>>>> On 1/28/2024 10:12 PM, Dmitry Baryshkov wrote:
>>>>> On Mon, 29 Jan 2024 at 07:03, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>> On 1/28/2024 7:42 PM, Dmitry Baryshkov wrote:
>>>>>>> On Mon, 29 Jan 2024 at 04:58, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On 1/27/2024 9:55 PM, Dmitry Baryshkov wrote:
>>>>>>>>> On Sun, 28 Jan 2024 at 07:48, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On 1/25/2024 1:57 PM, Dmitry Baryshkov wrote:
>>>>>>>>>>> On 25/01/2024 21:38, Paloma Arellano wrote:
>>>>>>>>>>>> Adjust the encoder format programming in the case of video mode for DP
>>>>>>>>>>>> to accommodate CDM related changes.
>>>>>>>>>>>>
>>>>>>>>>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>>>>>>>>>>> ---
>>>>>>>>>>>>        drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 16 +++++++++
>>>>>>>>>>>>        drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |  8 +++++
>>>>>>>>>>>>        .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 35 ++++++++++++++++---
>>>>>>>>>>>>        drivers/gpu/drm/msm/dp/dp_display.c           | 12 +++++++
>>>>>>>>>>>>        drivers/gpu/drm/msm/msm_drv.h                 |  9 ++++-
>>>>>>>>>>>>        5 files changed, 75 insertions(+), 5 deletions(-)
>>>>>>>>>>>>
>>>>>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>>>>>>>> index b0896814c1562..99ec53446ad21 100644
>>>>>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>>>>>>>> @@ -222,6 +222,22 @@ static u32 dither_matrix[DITHER_MATRIX_SZ] = {
>>>>>>>>>>>>            15, 7, 13, 5, 3, 11, 1, 9, 12, 4, 14, 6, 0, 8, 2, 10
>>>>>>>>>>>>        };
>>>>>>>>>>>>        +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
>>>>>>>>>>>> const struct drm_display_mode *mode)
>>>>>>>>>>>> +{
>>>>>>>>>>>> +    const struct dpu_encoder_virt *dpu_enc;
>>>>>>>>>>>> +    const struct msm_display_info *disp_info;
>>>>>>>>>>>> +    struct msm_drm_private *priv;
>>>>>>>>>>>> +
>>>>>>>>>>>> +    dpu_enc = to_dpu_encoder_virt(drm_enc);
>>>>>>>>>>>> +    disp_info = &dpu_enc->disp_info;
>>>>>>>>>>>> +    priv = drm_enc->dev->dev_private;
>>>>>>>>>>>> +
>>>>>>>>>>>> +    if (disp_info->intf_type == INTF_DP &&
>>>>>>>>>>>> + msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]],
>>>>>>>>>>>> mode))
>>>>>>>>>>>
>>>>>>>>>>> This should not require interacting with DP. If we got here, we must
>>>>>>>>>>> be sure that 4:2:0 is supported and can be configured.
>>>>>>>>>> Ack. Will drop this function and only check for if the mode is YUV420.
>>>>>>>>>>>
>>>>>>>>>>>> +        return DRM_FORMAT_YUV420;
>>>>>>>>>>>> +
>>>>>>>>>>>> +    return DRM_FORMAT_RGB888;
>>>>>>>>>>>> +}
>>>>>>>>>>>>          bool dpu_encoder_is_widebus_enabled(const struct drm_encoder
>>>>>>>>>>>> *drm_enc)
>>>>>>>>>>>>        {
>>>>>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>>>>>>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>>>>>>>>>>>> index 7b4afa71f1f96..62255d0aa4487 100644
>>>>>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>>>>>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>>>>>>>>>>>> @@ -162,6 +162,14 @@ int dpu_encoder_get_vsync_count(struct
>>>>>>>>>>>> drm_encoder *drm_enc);
>>>>>>>>>>>>         */
>>>>>>>>>>>>        bool dpu_encoder_is_widebus_enabled(const struct drm_encoder
>>>>>>>>>>>> *drm_enc);
>>>>>>>>>>>>        +/**
>>>>>>>>>>>> + * dpu_encoder_get_drm_fmt - return DRM fourcc format
>>>>>>>>>>>> + * @drm_enc:    Pointer to previously created drm encoder structure
>>>>>>>>>>>> + * @mode:    Corresponding drm_display_mode for dpu encoder
>>>>>>>>>>>> + */
>>>>>>>>>>>> +u32 dpu_encoder_get_drm_fmt(const struct drm_encoder *drm_enc,
>>>>>>>>>>>> +                const struct drm_display_mode *mode);
>>>>>>>>>>>> +
>>>>>>>>>>>>        /**
>>>>>>>>>>>>         * dpu_encoder_get_crc_values_cnt - get number of physical encoders
>>>>>>>>>>>> contained
>>>>>>>>>>>>         *    in virtual encoder that can collect CRC values
>>>>>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>>>>>>>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>>>>>>>>>> index e284bf448bdda..a1dde0ff35dc8 100644
>>>>>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>>>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>>>>>>>>>> @@ -234,6 +234,7 @@ static void
>>>>>>>>>>>> dpu_encoder_phys_vid_setup_timing_engine(
>>>>>>>>>>>>        {
>>>>>>>>>>>>            struct drm_display_mode mode;
>>>>>>>>>>>>            struct dpu_hw_intf_timing_params timing_params = { 0 };
>>>>>>>>>>>> +    struct dpu_hw_cdm *hw_cdm;
>>>>>>>>>>>>            const struct dpu_format *fmt = NULL;
>>>>>>>>>>>>            u32 fmt_fourcc = DRM_FORMAT_RGB888;
>>>>>>>>>>>>            unsigned long lock_flags;
>>>>>>>>>>>> @@ -254,17 +255,26 @@ static void
>>>>>>>>>>>> dpu_encoder_phys_vid_setup_timing_engine(
>>>>>>>>>>>>            DPU_DEBUG_VIDENC(phys_enc, "enabling mode:\n");
>>>>>>>>>>>>            drm_mode_debug_printmodeline(&mode);
>>>>>>>>>>>>        -    if (phys_enc->split_role != ENC_ROLE_SOLO) {
>>>>>>>>>>>> +    hw_cdm = phys_enc->hw_cdm;
>>>>>>>>>>>> +    if (hw_cdm) {
>>>>>>>>>>>> +        intf_cfg.cdm = hw_cdm->idx;
>>>>>>>>>>>> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent, &mode);
>>>>>>>>>>>> +    }
>>>>>>>>>>>> +
>>>>>>>>>>>> +    if (phys_enc->split_role != ENC_ROLE_SOLO ||
>>>>>>>>>>>> +        dpu_encoder_get_drm_fmt(phys_enc->parent, &mode) ==
>>>>>>>>>>>> DRM_FORMAT_YUV420) {
>>>>>>>>>>>>                mode.hdisplay >>= 1;
>>>>>>>>>>>>                mode.htotal >>= 1;
>>>>>>>>>>>>                mode.hsync_start >>= 1;
>>>>>>>>>>>>                mode.hsync_end >>= 1;
>>>>>>>>>>>> +        mode.hskew >>= 1;
>>>>>>>>>>>
>>>>>>>>>>> Separate patch.
>>>>>>>>>> Ack.
>>>>>>>>>>>
>>>>>>>>>>>>                  DPU_DEBUG_VIDENC(phys_enc,
>>>>>>>>>>>> -            "split_role %d, halve horizontal %d %d %d %d\n",
>>>>>>>>>>>> +            "split_role %d, halve horizontal %d %d %d %d %d\n",
>>>>>>>>>>>>                    phys_enc->split_role,
>>>>>>>>>>>>                    mode.hdisplay, mode.htotal,
>>>>>>>>>>>> -            mode.hsync_start, mode.hsync_end);
>>>>>>>>>>>> +            mode.hsync_start, mode.hsync_end,
>>>>>>>>>>>> +            mode.hskew);
>>>>>>>>>>>>            }
>>>>>>>>>>>>              drm_mode_to_intf_timing_params(phys_enc, &mode, &timing_params);
>>>>>>>>>>>> @@ -412,8 +422,15 @@ static int dpu_encoder_phys_vid_control_vblank_irq(
>>>>>>>>>>>>        static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys
>>>>>>>>>>>> *phys_enc)
>>>>>>>>>>>>        {
>>>>>>>>>>>>            struct dpu_hw_ctl *ctl;
>>>>>>>>>>>> +    struct dpu_hw_cdm *hw_cdm;
>>>>>>>>>>>> +    const struct dpu_format *fmt = NULL;
>>>>>>>>>>>> +    u32 fmt_fourcc = DRM_FORMAT_RGB888;
>>>>>>>>>>>>              ctl = phys_enc->hw_ctl;
>>>>>>>>>>>> +    hw_cdm = phys_enc->hw_cdm;
>>>>>>>>>>>> +    if (hw_cdm)
>>>>>>>>>>>> +        fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc->parent,
>>>>>>>>>>>> &phys_enc->cached_mode);
>>>>>>>>>>>> +    fmt = dpu_get_dpu_format(fmt_fourcc);
>>>>>>>>>>>>              DPU_DEBUG_VIDENC(phys_enc, "\n");
>>>>>>>>>>>>        @@ -422,6 +439,8 @@ static void dpu_encoder_phys_vid_enable(struct
>>>>>>>>>>>> dpu_encoder_phys *phys_enc)
>>>>>>>>>>>>              dpu_encoder_helper_split_config(phys_enc,
>>>>>>>>>>>> phys_enc->hw_intf->idx);
>>>>>>>>>>>>        +    dpu_encoder_helper_phys_setup_cdm(phys_enc, fmt,
>>>>>>>>>>>> CDM_CDWN_OUTPUT_HDMI);
>>>>>>>>>>>
>>>>>>>>>>> If there is no CDM, why do we need to call this?
>>>>>>>>>> Inside of dpu_encoder_helper_phys_setup_cdm(), there's a check to see if
>>>>>>>>>> there is a hw_cdm. If there is not, then it immediately exits the function.
>>>>>>>>>>>
>>>>>>>>>>>> +
>>>>>>>>>>>>            dpu_encoder_phys_vid_setup_timing_engine(phys_enc);
>>>>>>>>>>>>              /*
>>>>>>>>>>>> @@ -437,7 +456,15 @@ static void dpu_encoder_phys_vid_enable(struct
>>>>>>>>>>>> dpu_encoder_phys *phys_enc)
>>>>>>>>>>>>            if (ctl->ops.update_pending_flush_merge_3d &&
>>>>>>>>>>>> phys_enc->hw_pp->merge_3d)
>>>>>>>>>>>>                ctl->ops.update_pending_flush_merge_3d(ctl,
>>>>>>>>>>>> phys_enc->hw_pp->merge_3d->idx);
>>>>>>>>>>>>        -    if (ctl->ops.update_pending_flush_periph &&
>>>>>>>>>>>> phys_enc->hw_intf->cap->type == INTF_DP)
>>>>>>>>>>>> +    if (ctl->ops.update_pending_flush_cdm && phys_enc->hw_cdm)
>>>>>>>>>>>> +        ctl->ops.update_pending_flush_cdm(ctl, hw_cdm->idx);
>>>>>>>>>>>> +
>>>>>>>>>>>> +    /*
>>>>>>>>>>>> +     * Peripheral flush must be updated whenever flushing SDP
>>>>>>>>>>>> packets is needed.
>>>>>>>>>>>> +     * SDP packets are required for any YUV format (YUV420, YUV422,
>>>>>>>>>>>> YUV444).
>>>>>>>>>>>> +     */
>>>>>>>>>>>> +    if (ctl->ops.update_pending_flush_periph &&
>>>>>>>>>>>> phys_enc->hw_intf->cap->type == INTF_DP &&
>>>>>>>>>>>> +        phys_enc->hw_cdm)
>>>>>>>>>>>>                ctl->ops.update_pending_flush_periph(ctl,
>>>>>>>>>>>> phys_enc->hw_intf->idx);
>>>>>>>>>>>
>>>>>>>>>>> Should there be a flush if we are switching from YUV 420 to RGB mode?
>>>>>>>>>> We only need to flush for the sdp packet, but for msa we do not need to
>>>>>>>>>> flush.
>>>>>>>>>
>>>>>>>>> What about having SDP with RGB as colorimetry? In other words, if
>>>>>>>>> there is a decision point, this one looks incorrect.
>>>>>>>>>
>>>>>>>>
>>>>>>>> There are two ways to do it:
>>>>>>>>
>>>>>>>> 1) Use SDP for both RGB and YUV as that supports both. If we implement
>>>>>>>> this policy, then what you are asking for is correct that we will need
>>>>>>>> SDP even to switch back to RGB. But to implement this we will also need
>>>>>>>> to have some sort of state management in the encoder layer about what is
>>>>>>>> the current encoder fmt Vs what is the prev fmt and then trigger
>>>>>>>> peripheral flush only during transitions from RGB to YUV and vice-versa
>>>>>>>>
>>>>>>>> 2) Use SDP only for YUV because MSA does not support YUV formats and use
>>>>>>>> MSA for RGB
>>>>>>>>
>>>>>>>> We decided to implement (2) and there is no significant impact of
>>>>>>>> switching between MSA and SDPs but state management becomes easier.
>>>>>>>
>>>>>>> Yes. However as you wrote, there might be other usecases concerning
>>>>>>> SDP. Having this in mind, it sounds like the driver should decide
>>>>>>> whether to flush peripheral at a different place (when the SDP
>>>>>>> infoframe is being updated?). And the dpu_encoder_phys_vid_enable()
>>>>>>> should use this previous decision. Maybe this should be a part of
>>>>>>> msm_dp_ API, something like msm_dp_needs_peripheral_flush()?
>>>>>>>
>>>>>>
>>>>>> Correct. The decision to flush peripheral or not certainly comes from
>>>>>> the peripheral itself . In this case its DP.
>>>>>>
>>>>>> I think perhaps the usage of hw_cdm here makes it hard to understand
>>>>>> that but the idea behind this was that in the change "drm/msm/dpu:
>>>>>> reserve CDM blocks for DP if mode is YUV420 ", hw_cdm is assigned only
>>>>>> if msm_dp_is_yuv_420_enabled() returns true.
>>>>>
>>>>> Yes.
>>>>>
>>>>>>
>>>>>> So in some sense, the API you are asking for is already
>>>>>> msm_dp_is_yuv_420_enabled() but we can rename that to
>>>>>> msm_dp_needs_periph_flush().
>>>>>
>>>>> No. This leaks details. We might need peripheral flush for other
>>>>> reasons. So this decision should be made inside the DP driver.
>>>>> BTW, is there a need to flush-peripheral each time the INTF gets
>>>>> enabled? When some bits of configuration were updated (like SDP
>>>>> infoframe or CDM config)?
>>>>>
>>>>
>>>> Not really leaking any details. Interface decides when DPU's flush bit
>>>> needs to be invoked. All the conditions needing the flush can be
>>>> absorbed within msm_dp_needs_periph_flush() which will be within DP
>>>> driver. So I dont see any issue with that.
>>>
>>> As long as we have two distinct functions: msm_dp_needs_periph_flush()
>>> and msm_dp_is_yuv420_enabled(), it's fine with me.
>>>
>>
>> I am okay with it being distinct but in this series and till DP DSC is
>> posted, we have only YUV420 SDP use-case for peripheral flush.
>>
>> So are you okay with the fact that the code will look something like
>>
>> bool msm_dp_needs_periph_flush() {
>>          return msm_dp_is_yuv420_enabled();
>> }
> 
> Yes. The reason is that if at some point conditions for periph flush
> get changed, you won't have to change the API between DPU and DP
> drivers.
> 

Ack, I am okay with this.

>>
>>>>
>>>> The peripheral flush needs to be invoked whenever SDP/PPS packets need
>>>> to be sent out at the very least. Those are the two main use-cases so far.
>>>>
>>>> Not necessarily each time the INTF is enabled.
>>>>
>>>> But ....
>>>>
>>>> For PPS, we would typically enable DSC from the first frame itself and
>>>> we dont support dynamically turning DSC ON/OFF so its a fair assumption
>>>> that we need to the peripheral flush for DSC only during enable.
>>>>
>>>> For SDP, so today we enforce a modeset when we switch from a case of
>>>> needing cdm / not needing cdm and vice-versa. So even this use-case
>>>> should be accompanied by a disable()/enable().
>>>
>>> My point was that there might be other changes to the SDP infoframe.
>>>
>>>>
>>>> So are you suggesting that we unconditionally just do peripheral_flush
>>>> from enable()?
>>>>
>>>> I need to do some checking but maybe ....
>>>
>>> This might be an option too. I don't know what delays / issues it can cause.
>>>
>>
>> I will check this if the other option we discussed above does not work
>> for you.
>>
>>>>
>>>>>>
>>>>>> The issue here is the phys layer cannot call msm_dp_is_yuv_420_enabled()
>>>>>> so its kind of round-about by checking hw_cdm.
>>>>>
>>>>> Which maybe means that I should finish phys / encoder rework.
>>>>>
>>>>
>>>> Ugh no. Not another rework just for this.
>>>
>>> It is pending for the CTL flush story.
>>>
>>>>
>>>>>>
>>>>>> The check is not entirely wrong because for DP, we need hw_cdm for all
>>>>>> YUV formats and not just 420 but the relationship is maybe not clear but
>>>>>> I thought the comment above that would help a bit:
>>>>>>
>>>>>> /*
>>>>>>             * Peripheral flush must be updated whenever flushing SDP packets is
>>>>>> needed.
>>>>>>             * SDP packets are required for any YUV format (YUV420, YUV422, YUV444).
>>>>>>             */
>>>>>>
>>>>>> The only other way I can think of is maybe we need to introduce a new
>>>>>> phys variable called phys_enc->needs_update_periph_flush and we can set
>>>>>> that in dpu_encoder.c as that can call msm_dp_needs_periph_flush().
>>>>>>
>>>>>> What do you think of this way?
>>>>>
>>>>> Let me understand first the requirements for peripheral flush (see the
>>>>> questions above).
> 
> 
> 

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 11/17] drm/msm/dp: add VSC SDP support for YUV420 over DP
  2024-02-01  4:36           ` Dmitry Baryshkov
@ 2024-02-02  6:25             ` Abhinav Kumar
  0 siblings, 0 replies; 95+ messages in thread
From: Abhinav Kumar @ 2024-02-02  6:25 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Paloma Arellano, freedreno, linux-arm-msm, dri-devel, robdclark,
	seanpaul, swboyd, quic_jesszhan, quic_khsieh, marijn.suijten,
	neil.armstrong



On 1/31/2024 8:36 PM, Dmitry Baryshkov wrote:
> On Thu, 1 Feb 2024 at 03:56, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 1/27/2024 9:39 PM, Dmitry Baryshkov wrote:
>>> On Sun, 28 Jan 2024 at 07:34, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>>>>
>>>>
>>>> On 1/25/2024 1:48 PM, Dmitry Baryshkov wrote:
>>>>> On 25/01/2024 21:38, Paloma Arellano wrote:
>>>>>> Add support to pack and send the VSC SDP packet for DP. This therefore
>>>>>> allows the transmision of format information to the sinks which is
>>>>>> needed for YUV420 support over DP.
>>>>>>
>>>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>>>>> ---
>>>>>>     drivers/gpu/drm/msm/dp/dp_catalog.c | 147 ++++++++++++++++++++++++++++
>>>>>>     drivers/gpu/drm/msm/dp/dp_catalog.h |   4 +
>>>>>>     drivers/gpu/drm/msm/dp/dp_ctrl.c    |   4 +
>>>>>>     drivers/gpu/drm/msm/dp/dp_panel.c   |  47 +++++++++
>>>>>>     drivers/gpu/drm/msm/dp/dp_reg.h     |   3 +
>>>>>>     5 files changed, 205 insertions(+)
>>>>>>
>>>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c
>>>>>> b/drivers/gpu/drm/msm/dp/dp_catalog.c
>>>>>> index c025786170ba5..7e4c68be23e56 100644
>>>>>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
>>>>>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
>>>>>> @@ -29,6 +29,9 @@
>>>>>>       #define DP_INTF_CONFIG_DATABUS_WIDEN     BIT(4)
>>>>>>     +#define DP_GENERIC0_6_YUV_8_BPC        BIT(0)
>>>>>> +#define DP_GENERIC0_6_YUV_10_BPC    BIT(1)
>>>>>> +
>>>>>>     #define DP_INTERRUPT_STATUS1 \
>>>>>>         (DP_INTR_AUX_XFER_DONE| \
>>>>>>         DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \
>>>>>> @@ -907,6 +910,150 @@ int dp_catalog_panel_timing_cfg(struct
>>>>>> dp_catalog *dp_catalog)
>>>>>>         return 0;
>>>>>>     }
>>>>>>     +static void dp_catalog_panel_setup_vsc_sdp(struct dp_catalog
>>>>>> *dp_catalog)
>>>>>> +{
>>>>>> +    struct dp_catalog_private *catalog;
>>>>>> +    u32 header, parity, data;
>>>>>> +    u8 bpc, off = 0;
>>>>>> +    u8 buf[SZ_128];
>>>>>> +
>>>>>> +    if (!dp_catalog) {
>>>>>> +        pr_err("invalid input\n");
>>>>>> +        return;
>>>>>> +    }
>>>>>> +
>>>>>> +    catalog = container_of(dp_catalog, struct dp_catalog_private,
>>>>>> dp_catalog);
>>>>>> +
>>>>>> +    /* HEADER BYTE 1 */
>>>>>> +    header = dp_catalog->sdp.sdp_header.HB1;
>>>>>> +    parity = dp_catalog_calculate_parity(header);
>>>>>> +    data   = ((header << HEADER_BYTE_1_BIT) | (parity <<
>>>>>> PARITY_BYTE_1_BIT));
>>>>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_0, data);
>>>>>> +    memcpy(buf + off, &data, sizeof(data));
>>>>>> +    off += sizeof(data);
>>>>>> +
>>>>>> +    /* HEADER BYTE 2 */
>>>>>> +    header = dp_catalog->sdp.sdp_header.HB2;
>>>>>> +    parity = dp_catalog_calculate_parity(header);
>>>>>> +    data   = ((header << HEADER_BYTE_2_BIT) | (parity <<
>>>>>> PARITY_BYTE_2_BIT));
>>>>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_1, data);
>>>>>> +
>>>>>> +    /* HEADER BYTE 3 */
>>>>>> +    header = dp_catalog->sdp.sdp_header.HB3;
>>>>>> +    parity = dp_catalog_calculate_parity(header);
>>>>>> +    data   = ((header << HEADER_BYTE_3_BIT) | (parity <<
>>>>>> PARITY_BYTE_3_BIT));
>>>>>> +    data |= dp_read_link(catalog, MMSS_DP_GENERIC0_1);
>>>>>> +    dp_write_link(catalog, MMSS_DP_GENERIC0_1, data);
>>>>>> +    memcpy(buf + off, &data, sizeof(data));
>>>>>> +    off += sizeof(data);
>>>>>
>>>>> This seems to be common with the dp_audio code. Please extract this
>>>>> header writing too.
>>>> These are two different sdp's. audio and vsc, are different with
>>>> different registers being written to and different amount of registers
>>>> being set. Can you please clarify since in audio we only need 3
>>>> registers to write to, and in vsc we need 10.
>>>
>>> Bitmagic with the header is the same. Then the rest of the data is
>>> written one dword per register, if I'm not mistaken.
>>>
>>
>> We can generalize the MMSS_DP_GENERIC0 register writing by breaking it
>> up to two things:
>>
>> 1) Add a function vsc_sdp_pack() similar to hdmi_avi_infoframe_pack_only()
> 
> Note, there is already a hdmi_audio_infoframe_pack_for_dp() function.
> I think this patchset can add hdmi_colorimetry_infoframe_pack_for_dp()
> [you can choose any other similar name that suits from your POV].
> 
> Also please extract the function that inits the dp_sdp_header. It can
> be reused as is for both existing hdmi_audio_infoframe_pack_for_dp(),
> your new function and the dp_audio code.
> 

Not sure if extracting the header will work as all other functions in 
hdmi.c pack the header too so its a half and half implementation.

I am going to start with keeping this pack function in msm/dp/dp_utils.c 
to start with.

If it gets to a form which is generic enough to keep in a helper which 
can be common we can consider it once posted in v2.

>>
>> 2) dp_catalog_write_generic_pkt() which will just write the packed
>> buffer byte-by-byte to these MMSS_DP_GENERIC0_xxx register
>>
>> But audio seems a bit different. We use DP_AUDIO_STREAM_0/1.
>> More importantly, it uses this sdp_map and writes each header one by one
>> with dp_catalog_audio_set_header().
>>
>> Not sure if that entirely fits with this pack and then write model.
>>
>> It can be simplified. But I dont think this effort is needed for this
>> series.
>>
>> So I would prefer to generalize audio SDP programming separately.
> 
> I'd definitely ask to add a utility function that merges 4 header
> bytes with the parity data. We already have 5 instances of that code
> in dp_audio.c, which is already too much by the number of 4. Adding
> the 6th copy is NAKed.
> 

I acknowledge the overlap but coupling them with this feature doesn't 
make sense as we have to individually test out audio after that change 
even if its another cleanup.

In case my previous response was not clear.

I will certainly add a sdp packing function and utils which pack the 4 
header/parity bytes so that they can be used by other sub-modules of DP 
but will still prefer to push them as a separate series for audio as I 
want to re-test audio with that.

As discussed, I will work on that and post it in parallel.

> BTW, I see both in this path and in dp_audio that the driver reads a
> register, ORs it with the value for the next header byte and writes it
> back to the hardware. Shouldn't the driver clear the corresponding
> data bits first? I see the clears in the techpack, but not in the
> upstream code. If my assumption is correct, we should end up with the
> utility function that packs dp_sdp_header into u32[2], which can then
> be used by both YUV and dp_audio code to just write two corresponding
> registers.
> 

Correct. Thats my goal too to have a common utility function which can 
be used by audio code as well but in this series i will only introduce 
the function. The audio usage will be another one. I will also 
incorporate the clearing part if applicable once I check it closely.

> BTW2: where is the rest of the audio infoframe? I see that the old
> fbdev driver was at least clearing the first 4 bytes of the frame.
> 

hmm .... in DP we use audio infoframe SDP to send the audio information.
IIRC, we only fill the header/parity but the payload is fully controlled 
by LPASS (audio side).


^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 12/17] drm/msm/dpu: add support of new peripheral flush mechanism
  2024-01-28  5:42       ` Dmitry Baryshkov
@ 2024-02-08 23:09         ` Paloma Arellano
  0 siblings, 0 replies; 95+ messages in thread
From: Paloma Arellano @ 2024-02-08 23:09 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, Kuogee Hsieh, linux-arm-msm, dri-devel, robdclark,
	seanpaul, swboyd, quic_abhinavk, quic_jesszhan, marijn.suijten,
	neil.armstrong


On 1/27/2024 9:42 PM, Dmitry Baryshkov wrote:
> On Sun, 28 Jan 2024 at 07:41, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>>
>> On 1/25/2024 1:49 PM, Dmitry Baryshkov wrote:
>>> On 25/01/2024 21:38, Paloma Arellano wrote:
>>>> From: Kuogee Hsieh <quic_khsieh@quicinc.com>
>>>>
>>>> Introduce a peripheral flushing mechanism to decouple peripheral
>>>> metadata flushing from timing engine related flush.
>>>>
>>>> Signed-off-by: Kuogee Hsieh <quic_khsieh@quicinc.com>
>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>>> ---
>>>>    .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c    |  3 +++
>>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c      | 17 +++++++++++++++++
>>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h      | 10 ++++++++++
>>>>    3 files changed, 30 insertions(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>> index d0f56c5c4cce9..e284bf448bdda 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
>>>> @@ -437,6 +437,9 @@ static void dpu_encoder_phys_vid_enable(struct
>>>> dpu_encoder_phys *phys_enc)
>>>>        if (ctl->ops.update_pending_flush_merge_3d &&
>>>> phys_enc->hw_pp->merge_3d)
>>>>            ctl->ops.update_pending_flush_merge_3d(ctl,
>>>> phys_enc->hw_pp->merge_3d->idx);
>>>>    +    if (ctl->ops.update_pending_flush_periph &&
>>>> phys_enc->hw_intf->cap->type == INTF_DP)
>>>> +        ctl->ops.update_pending_flush_periph(ctl,
>>>> phys_enc->hw_intf->idx);
>>>> +
>>>>    skip_flush:
>>>>        DPU_DEBUG_VIDENC(phys_enc,
>>>>            "update pending flush ctl %d intf %d\n",
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
>>>> index e76565c3e6a43..bf45afeb616d3 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
>>>> @@ -39,6 +39,7 @@
>>>>    #define   CTL_WB_FLUSH                  0x108
>>>>    #define   CTL_INTF_FLUSH                0x110
>>>>    #define   CTL_CDM_FLUSH                0x114
>>>> +#define   CTL_PERIPH_FLUSH              0x128
>>>>    #define   CTL_INTF_MASTER               0x134
>>>>    #define   CTL_DSPP_n_FLUSH(n)           ((0x13C) + ((n) * 4))
>>>>    @@ -49,6 +50,7 @@
>>>>    #define  MERGE_3D_IDX   23
>>>>    #define  DSC_IDX        22
>>>>    #define CDM_IDX         26
>>>> +#define  PERIPH_IDX     30
>>>>    #define  INTF_IDX       31
>>>>    #define WB_IDX          16
>>>>    #define  DSPP_IDX       29  /* From DPU hw rev 7.x.x */
>>>> @@ -151,6 +153,10 @@ static inline void
>>>> dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
>>>>                    ctx->pending_dspp_flush_mask[dspp - DSPP_0]);
>>>>            }
>>>>    +    if (ctx->pending_flush_mask & BIT(PERIPH_IDX))
>>>> +        DPU_REG_WRITE(&ctx->hw, CTL_PERIPH_FLUSH,
>>>> +                  ctx->pending_periph_flush_mask);
>>>> +
>>>>        if (ctx->pending_flush_mask & BIT(DSC_IDX))
>>>>            DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH,
>>>>                      ctx->pending_dsc_flush_mask);
>>>> @@ -311,6 +317,13 @@ static void
>>>> dpu_hw_ctl_update_pending_flush_intf_v1(struct dpu_hw_ctl *ctx,
>>>>        ctx->pending_flush_mask |= BIT(INTF_IDX);
>>>>    }
>>>>    +static void dpu_hw_ctl_update_pending_flush_periph(struct
>>>> dpu_hw_ctl *ctx,
>>>> +        enum dpu_intf intf)
>>> I assume this is _v1.
>>> Also the argument is misaligned.
>> Ack.

I noticed that the placement of the 'enum dpu_intf intf' argument aligns 
with the other dpu_hw_ctl_update_pending_flush_* functions argument 
position. Is this alright, or should I align the argument with the first 
parentheses?


>>>> +{
>>>> +    ctx->pending_periph_flush_mask |= BIT(intf - INTF_0);
>>>> +    ctx->pending_flush_mask |= BIT(PERIPH_IDX);
>>>> +}
>>>> +
>>>>    static void dpu_hw_ctl_update_pending_flush_merge_3d_v1(struct
>>>> dpu_hw_ctl *ctx,
>>>>            enum dpu_merge_3d merge_3d)
>>>>    {
>>>> @@ -680,6 +693,10 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops
>>>> *ops,
>>>>            ops->reset_intf_cfg = dpu_hw_ctl_reset_intf_cfg_v1;
>>>>            ops->update_pending_flush_intf =
>>>>                dpu_hw_ctl_update_pending_flush_intf_v1;
>>>> +
>>>> +        ops->update_pending_flush_periph =
>>>> +            dpu_hw_ctl_update_pending_flush_periph;
>>>> +
>>>>            ops->update_pending_flush_merge_3d =
>>>>                dpu_hw_ctl_update_pending_flush_merge_3d_v1;
>>>>            ops->update_pending_flush_wb =
>>>> dpu_hw_ctl_update_pending_flush_wb_v1;
>>> What about the pre-active platforms?
>> Pre-active does not need a peripheral flush.
> Ack.
>
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
>>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
>>>> index ff85b5ee0acf8..5d86c560b6d3f 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
>>>> @@ -122,6 +122,15 @@ struct dpu_hw_ctl_ops {
>>>>        void (*update_pending_flush_intf)(struct dpu_hw_ctl *ctx,
>>>>            enum dpu_intf blk);
>>>>    +    /**
>>>> +     * OR in the given flushbits to the cached
>>>> pending_(periph_)flush_mask
>>>> +     * No effect on hardware
>>>> +     * @ctx       : ctl path ctx pointer
>>>> +     * @blk       : interface block index
>>>> +     */
>>>> +    void (*update_pending_flush_periph)(struct dpu_hw_ctl *ctx,
>>>> +        enum dpu_intf blk);
>>>> +
>>>>        /**
>>>>         * OR in the given flushbits to the cached
>>>> pending_(merge_3d_)flush_mask
>>>>         * No effect on hardware
>>>> @@ -264,6 +273,7 @@ struct dpu_hw_ctl {
>>>>        u32 pending_flush_mask;
>>>>        u32 pending_intf_flush_mask;
>>>>        u32 pending_wb_flush_mask;
>>>> +    u32 pending_periph_flush_mask;
>>>>        u32 pending_merge_3d_flush_mask;
>>>>        u32 pending_dspp_flush_mask[DSPP_MAX - DSPP_0];
>>>>        u32 pending_dsc_flush_mask;
>
>

^ permalink raw reply	[flat|nested] 95+ messages in thread

* Re: [PATCH 15/17] drm/msm/dpu: allow certain formats for CDM for DP
  2024-01-25 21:58   ` Dmitry Baryshkov
@ 2024-02-08 23:19     ` Paloma Arellano
  0 siblings, 0 replies; 95+ messages in thread
From: Paloma Arellano @ 2024-02-08 23:19 UTC (permalink / raw)
  To: Dmitry Baryshkov, freedreno
  Cc: linux-arm-msm, dri-devel, robdclark, seanpaul, swboyd,
	quic_abhinavk, quic_jesszhan, quic_khsieh, marijn.suijten,
	neil.armstrong


On 1/25/2024 1:58 PM, Dmitry Baryshkov wrote:
> On 25/01/2024 21:38, Paloma Arellano wrote:
>> CDM block supports formats other than H1V2 for DP. Since we are now
>> adding support for CDM over DP, relax the checks to allow all other
>> formats for DP other than H1V2.
>>
>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
>> index e9cdc7934a499..9016b3ade6bc3 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
>> @@ -186,7 +186,7 @@ static int dpu_hw_cdm_enable(struct dpu_hw_cdm 
>> *ctx, struct dpu_hw_cdm_cfg *cdm)
>>       dpu_hw_cdm_setup_cdwn(ctx, cdm);
>>         if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
>> -        if (fmt->chroma_sample != DPU_CHROMA_H1V2)
>> +        if (fmt->chroma_sample == DPU_CHROMA_H1V2)
>>               return -EINVAL; /*unsupported format */
>
> This means that the original check was incorrect. Please add 
> corresponding Fixes tag and move to the top of the patchset.


Ack.


>
>>           opmode = CDM_HDMI_PACK_OP_MODE_EN;
>>           opmode |= (fmt->chroma_sample << 1);
>

^ permalink raw reply	[flat|nested] 95+ messages in thread

end of thread, other threads:[~2024-02-08 23:19 UTC | newest]

Thread overview: 95+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-25 19:38 [PATCH 00/17] Add support for CDM over DP Paloma Arellano
2024-01-25 19:38 ` [PATCH 01/17] drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP Paloma Arellano
2024-01-25 21:14   ` Dmitry Baryshkov
2024-01-27  0:39     ` Paloma Arellano
2024-01-29  3:06       ` Abhinav Kumar
2024-01-29  3:23         ` Dmitry Baryshkov
2024-01-29  4:00           ` Abhinav Kumar
2024-01-29  4:12             ` Dmitry Baryshkov
2024-01-29  4:33               ` Abhinav Kumar
2024-01-29  5:12                 ` Dmitry Baryshkov
2024-01-29 23:06                   ` Paloma Arellano
2024-01-25 19:38 ` [PATCH 02/17] drm/msm/dpu: move dpu_encoder_helper_phys_setup_cdm to dpu_encoder Paloma Arellano
2024-01-25 21:16   ` Dmitry Baryshkov
2024-01-27  0:43     ` Paloma Arellano
2024-01-27  2:26       ` Dmitry Baryshkov
2024-01-25 19:38 ` [PATCH 03/17] drm/msm/dp: rename wide_bus_en to wide_bus_supported Paloma Arellano
2024-01-25 21:17   ` Dmitry Baryshkov
2024-01-25 19:38 ` [PATCH 04/17] drm/msm/dp: store mode YUV420 information to be used by rest of DP Paloma Arellano
2024-01-25 21:20   ` Dmitry Baryshkov
2024-01-27  0:48     ` Paloma Arellano
2024-01-27  2:29       ` Dmitry Baryshkov
2024-01-25 19:38 ` [PATCH 05/17] drm/msm/dp: add an API to indicate if sink supports VSC SDP Paloma Arellano
2024-01-25 21:23   ` Dmitry Baryshkov
2024-01-27  0:58     ` Paloma Arellano
2024-01-27  2:40       ` Dmitry Baryshkov
2024-01-27  3:57         ` Abhinav Kumar
2024-01-27  5:31           ` Dmitry Baryshkov
2024-01-29 23:20         ` Paloma Arellano
2024-01-25 19:38 ` [PATCH 06/17] drm/msm/dpu: move widebus logic to its own API Paloma Arellano
2024-01-25 21:25   ` Dmitry Baryshkov
2024-01-25 19:38 ` [PATCH 07/17] drm/msm/dpu: disallow widebus en in INTF_CONFIG2 when DP is YUV420 Paloma Arellano
2024-01-25 21:26   ` Dmitry Baryshkov
2024-01-27  5:42     ` Dmitry Baryshkov
2024-01-28  5:16     ` Paloma Arellano
2024-01-28  5:33       ` Dmitry Baryshkov
2024-01-29 23:51         ` Abhinav Kumar
2024-01-30  0:03           ` Dmitry Baryshkov
2024-01-30  1:07             ` Abhinav Kumar
2024-01-30  1:43               ` Dmitry Baryshkov
2024-01-30  4:10                 ` Abhinav Kumar
2024-01-30  5:28                   ` Dmitry Baryshkov
2024-01-30  6:03                     ` Abhinav Kumar
2024-01-25 19:38 ` [PATCH 08/17] drm/msm/dp: change YUV420 related programming for DP Paloma Arellano
2024-01-25 21:29   ` Dmitry Baryshkov
2024-01-28  5:18     ` Paloma Arellano
2024-01-25 19:38 ` [PATCH 09/17] drm/msm/dp: move parity calculation to dp_catalog Paloma Arellano
2024-01-25 21:32   ` Dmitry Baryshkov
2024-01-28  5:18     ` Paloma Arellano
2024-01-25 19:38 ` [PATCH 10/17] drm/msm/dp: modify dp_catalog_hw_revision to show major and minor val Paloma Arellano
2024-01-25 22:07   ` Dmitry Baryshkov
2024-01-28  5:30     ` Paloma Arellano
2024-01-28  5:35       ` Dmitry Baryshkov
2024-01-27 23:43   ` kernel test robot
2024-01-28 14:02   ` kernel test robot
2024-01-25 19:38 ` [PATCH 11/17] drm/msm/dp: add VSC SDP support for YUV420 over DP Paloma Arellano
2024-01-25 21:48   ` Dmitry Baryshkov
2024-01-28  5:34     ` Paloma Arellano
2024-01-28  5:39       ` Dmitry Baryshkov
2024-02-01  1:56         ` Abhinav Kumar
2024-02-01  4:36           ` Dmitry Baryshkov
2024-02-02  6:25             ` Abhinav Kumar
2024-01-25 19:38 ` [PATCH 12/17] drm/msm/dpu: add support of new peripheral flush mechanism Paloma Arellano
2024-01-25 21:49   ` Dmitry Baryshkov
2024-01-28  5:40     ` Paloma Arellano
2024-01-28  5:42       ` Dmitry Baryshkov
2024-02-08 23:09         ` Paloma Arellano
2024-01-25 19:38 ` [PATCH 13/17] drm/msm/dp: enable SDP and SDE periph flush update Paloma Arellano
2024-01-25 21:50   ` Dmitry Baryshkov
2024-01-28  5:42     ` Paloma Arellano
2024-01-25 19:38 ` [PATCH 14/17] drm/msm/dpu: modify encoder programming for CDM over DP Paloma Arellano
2024-01-25 21:57   ` Dmitry Baryshkov
2024-01-28  5:48     ` Paloma Arellano
2024-01-28  5:55       ` Dmitry Baryshkov
2024-01-29  2:58         ` Abhinav Kumar
2024-01-29  3:42           ` Dmitry Baryshkov
2024-01-29  5:03             ` Abhinav Kumar
2024-01-29  6:12               ` Dmitry Baryshkov
2024-01-29  7:08                 ` Abhinav Kumar
2024-01-29 23:44                   ` Dmitry Baryshkov
2024-02-01  1:30                     ` Abhinav Kumar
2024-02-01  3:17                       ` Dmitry Baryshkov
2024-02-01 19:01                         ` Abhinav Kumar
2024-01-25 19:38 ` [PATCH 15/17] drm/msm/dpu: allow certain formats for CDM for DP Paloma Arellano
2024-01-25 21:58   ` Dmitry Baryshkov
2024-02-08 23:19     ` Paloma Arellano
2024-01-25 19:38 ` [PATCH 16/17] drm/msm/dpu: reserve CDM blocks for DP if mode is YUV420 Paloma Arellano
2024-01-25 22:01   ` Dmitry Baryshkov
2024-01-28  5:48     ` Paloma Arellano
2024-01-25 19:38 ` [PATCH 17/17] drm/msm/dp: allow YUV420 mode for DP connector when VSC SDP supported Paloma Arellano
2024-01-25 22:05   ` Dmitry Baryshkov
2024-01-29  3:17     ` Abhinav Kumar
2024-01-29  3:52       ` Dmitry Baryshkov
2024-01-29  4:30         ` Abhinav Kumar
2024-01-29  5:05           ` Dmitry Baryshkov
2024-01-29  5:36             ` Abhinav Kumar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).