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

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 is dependent on [1], [2], and [3]:
[1] https://patchwork.freedesktop.org/series/118831/
[2] https://patchwork.freedesktop.org/series/129395/
[3] https://patchwork.freedesktop.org/series/129864/

Changes in v3:
	- Change ordering of the header byte macros in dp_utils.h
	- Create a new struct, msm_dp_sdp_with_parity
 	- Utilize drm_dp_vsc_sdp_pack() from a new added dependency of
	  series [3] to pack the VSC SDP data into the new
	  msm_dp_sdp_with_parity struct instead of packing only for
	  YUV420
	- Modify dp_catalog_panel_send_vsc_sdp() so that it sends the VSC SDP data
	  using the new msm_dp_sdp_with_parity struct
	- Clear up that the DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE macro is setting
	  multiple bits and not just one
	- Move the connector's ycbcr_420_allowed parameter so it is no longer
	  dependent on if the dp_display is not eDP

Changes in v2:
	- Minor formatting changes throughout
	- Move 'fixes' patch to the top
	- Move VSC SDP support check API from dp_panel.c to drm_dp_helper.c
	- Create a separate patch for modifying the dimensions for CDM setup to be
	  non-WB specific
	- Remove a patch that modified the INTF_CONFIG2 register in favor of having
	  this series be dependent on [2]
	- Separate configuration ctrl programming from clock related programming into
	  two patches
	- Add a VSC SDP check in dp_bridge_mode_valid()
	- Move parity calculation functions to new files dp_utils.c and dp_utils.h
	- Remove dp_catalog_hw_revision() changes and utilize the original version of
	  the function when checking the DP hardware version
	- Create separate packing and programming functions for the VSC SDP
	- Make the packing header bytes function generic so it can be used with
	  dp_audio.c
	- Create two separate enable/disable VSC SDP functions instead of having one
	  with the ability to do both
	- Move timing engine programming to a separate patch from original encoder
	  programming patch
	- Move update_pending_flush_periph() code to be in the same patch as the
	  encoder programming
	- Create new API's to check if the dpu encoder needs a peripheral flush
	- Allow YUV420 modes for the DP connector when there's a CDM block available
	  instead of checking if VSC SDP is supported

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

Paloma Arellano (18):
  drm/msm/dpu: allow certain formats for CDM for DP
  drm/msm/dpu: add division of drm_display_mode's hskew parameter
  drm/msm/dpu: pass mode dimensions instead of fb size in CDM setup
  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: check if VSC SDP is supported in DP programming
  drm/msm/dpu: move widebus logic to its own API
  drm/msm/dp: program config ctrl for YUV420 over DP
  drm/msm/dp: change clock related programming for YUV420 over DP
  drm/msm/dp: move parity calculation to dp_utils
  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: modify timing engine programming for YUV420 over DP
  drm/msm/dpu: reserve CDM blocks for DP if mode is YUV420
  drm/msm/dp: allow YUV420 mode for DP connector when CDM available

 drivers/gpu/drm/msm/Makefile                  |   3 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 164 +++++++++++++++---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h   |   4 +
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  26 ++-
 .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  |  33 +++-
 .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 100 +----------
 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_kms.c       |   4 +-
 drivers/gpu/drm/msm/dp/dp_audio.c             | 101 ++---------
 drivers/gpu/drm/msm/dp/dp_catalog.c           | 135 +++++++++++++-
 drivers/gpu/drm/msm/dp/dp_catalog.h           |  10 +-
 drivers/gpu/drm/msm/dp/dp_ctrl.c              |  17 +-
 drivers/gpu/drm/msm/dp/dp_display.c           |  82 ++++++---
 drivers/gpu/drm/msm/dp/dp_drm.c               |   6 +-
 drivers/gpu/drm/msm/dp/dp_drm.h               |   3 +-
 drivers/gpu/drm/msm/dp/dp_panel.c             |  56 ++++++
 drivers/gpu/drm/msm/dp/dp_panel.h             |   2 +
 drivers/gpu/drm/msm/dp/dp_reg.h               |   8 +
 drivers/gpu/drm/msm/dp/dp_utils.c             | 121 +++++++++++++
 drivers/gpu/drm/msm/dp/dp_utils.h             |  40 +++++
 drivers/gpu/drm/msm/msm_drv.h                 |  22 ++-
 23 files changed, 725 insertions(+), 241 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/dp/dp_utils.c
 create mode 100644 drivers/gpu/drm/msm/dp/dp_utils.h

-- 
2.39.2


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

* [PATCH v3 01/19] drm/msm/dpu: allow certain formats for CDM for DP
  2024-02-14 18:03 [PATCH v3 00/19] Add support for CDM over DP Paloma Arellano
@ 2024-02-14 18:03 ` Paloma Arellano
  2024-02-14 18:03 ` [PATCH v3 02/19] drm/msm/dpu: add division of drm_display_mode's hskew parameter Paloma Arellano
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 33+ messages in thread
From: Paloma Arellano @ 2024-02-14 18:03 UTC (permalink / raw)
  To: freedreno
  Cc: Paloma Arellano, linux-arm-msm, dri-devel, robdclark, seanpaul,
	swboyd, dmitry.baryshkov, quic_abhinavk, quic_jesszhan,
	quic_khsieh, marijn.suijten, neil.armstrong

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.

Changes in v2:
	- Add fixes tag
	- Move patch to top of series

Fixes: 0afac0ba6024 ("drm/msm/dpu: add dpu_hw_cdm abstraction for CDM block")
Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 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] 33+ messages in thread

* [PATCH v3 02/19] drm/msm/dpu: add division of drm_display_mode's hskew parameter
  2024-02-14 18:03 [PATCH v3 00/19] Add support for CDM over DP Paloma Arellano
  2024-02-14 18:03 ` [PATCH v3 01/19] drm/msm/dpu: allow certain formats for CDM for DP Paloma Arellano
@ 2024-02-14 18:03 ` Paloma Arellano
  2024-02-15  8:56   ` Dmitry Baryshkov
  2024-02-14 18:03 ` [PATCH v3 03/19] drm/msm/dpu: pass mode dimensions instead of fb size in CDM setup Paloma Arellano
                   ` (16 subsequent siblings)
  18 siblings, 1 reply; 33+ messages in thread
From: Paloma Arellano @ 2024-02-14 18:03 UTC (permalink / raw)
  To: freedreno
  Cc: Paloma Arellano, linux-arm-msm, dri-devel, robdclark, seanpaul,
	swboyd, dmitry.baryshkov, quic_abhinavk, quic_jesszhan,
	quic_khsieh, marijn.suijten, neil.armstrong

Setting up the timing engine when the physical encoder has a split role
neglects dividing the drm_display_mode's hskew parameter. Let's fix this
since this must also be done in preparation for implementing YUV420 over
DP.

Fixes: 25fdd5933e4c ("drm/msm: Add SDM845 DPU support")
Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

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 f562beb6f7971..f02411b062c4c 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
@@ -260,12 +260,14 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
 		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);
-- 
2.39.2


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

* [PATCH v3 03/19] drm/msm/dpu: pass mode dimensions instead of fb size in CDM setup
  2024-02-14 18:03 [PATCH v3 00/19] Add support for CDM over DP Paloma Arellano
  2024-02-14 18:03 ` [PATCH v3 01/19] drm/msm/dpu: allow certain formats for CDM for DP Paloma Arellano
  2024-02-14 18:03 ` [PATCH v3 02/19] drm/msm/dpu: add division of drm_display_mode's hskew parameter Paloma Arellano
@ 2024-02-14 18:03 ` Paloma Arellano
  2024-02-14 18:03 ` [PATCH v3 04/19] drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP Paloma Arellano
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 33+ messages in thread
From: Paloma Arellano @ 2024-02-14 18:03 UTC (permalink / raw)
  To: freedreno
  Cc: Paloma Arellano, linux-arm-msm, dri-devel, robdclark, seanpaul,
	swboyd, dmitry.baryshkov, quic_abhinavk, quic_jesszhan,
	quic_khsieh, marijn.suijten, neil.armstrong

Modify the output width and height parameters of hw_cdm to utilize the
physical encoder's data instead of obtaining the information from the
framebuffer. CDM is to be set up to utilize the actual output data since
at CDM setup, there is no difference between the two sources.

Changes in v2:
	- Move the modification of the dimensions for CDM setup to this
	  new patch

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

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..ec9e053d3947d 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
@@ -306,8 +306,8 @@ 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_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
-- 
2.39.2


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

* [PATCH v3 04/19] drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP
  2024-02-14 18:03 [PATCH v3 00/19] Add support for CDM over DP Paloma Arellano
                   ` (2 preceding siblings ...)
  2024-02-14 18:03 ` [PATCH v3 03/19] drm/msm/dpu: pass mode dimensions instead of fb size in CDM setup Paloma Arellano
@ 2024-02-14 18:03 ` Paloma Arellano
  2024-02-14 18:03 ` [PATCH v3 05/19] drm/msm/dpu: move dpu_encoder_helper_phys_setup_cdm to dpu_encoder Paloma Arellano
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 33+ messages in thread
From: Paloma Arellano @ 2024-02-14 18:03 UTC (permalink / raw)
  To: freedreno
  Cc: Paloma Arellano, linux-arm-msm, dri-devel, robdclark, seanpaul,
	swboyd, dmitry.baryshkov, quic_abhinavk, quic_jesszhan,
	quic_khsieh, marijn.suijten, neil.armstrong

Generalize dpu_encoder_helper_phys_setup_cdm to be compatible with DP.

Changes in v2:
	- Minor formatting changes
	- Move the modification of the dimensions for CDM setup to a new
	  patch

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  4 +--
 .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 27 ++++++++++---------
 2 files changed, 16 insertions(+), 15 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..204d7cc3c1de8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -154,6 +154,7 @@ enum dpu_intr_idx {
  * @hw_wb:		Hardware interface to the wb registers
  * @hw_cdm:		Hardware interface to the CDM registers
  * @dpu_kms:		Pointer to the dpu_kms top level
+ * @cdm_cfg:		CDM block config needed to store WB/DP block's CDM configuration
  * @cached_mode:	DRM mode cached at mode_set time, acted on in enable
  * @vblank_ctl_lock:	Vblank ctl mutex lock to protect vblank_refcount
  * @enabled:		Whether the encoder has enabled and running a mode
@@ -184,6 +185,7 @@ struct dpu_encoder_phys {
 	struct dpu_hw_wb *hw_wb;
 	struct dpu_hw_cdm *hw_cdm;
 	struct dpu_kms *dpu_kms;
+	struct dpu_hw_cdm_cfg cdm_cfg;
 	struct drm_display_mode cached_mode;
 	struct mutex vblank_ctl_lock;
 	enum dpu_enc_split_role split_role;
@@ -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 ec9e053d3947d..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;
@@ -309,7 +302,7 @@ static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
 	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] 33+ messages in thread

* [PATCH v3 05/19] drm/msm/dpu: move dpu_encoder_helper_phys_setup_cdm to dpu_encoder
  2024-02-14 18:03 [PATCH v3 00/19] Add support for CDM over DP Paloma Arellano
                   ` (3 preceding siblings ...)
  2024-02-14 18:03 ` [PATCH v3 04/19] drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP Paloma Arellano
@ 2024-02-14 18:03 ` Paloma Arellano
  2024-02-14 18:03 ` [PATCH v3 06/19] drm/msm/dp: rename wide_bus_en to wide_bus_supported Paloma Arellano
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 33+ messages in thread
From: Paloma Arellano @ 2024-02-14 18:03 UTC (permalink / raw)
  To: freedreno
  Cc: Paloma Arellano, linux-arm-msm, dri-devel, robdclark, seanpaul,
	swboyd, dmitry.baryshkov, quic_abhinavk, quic_jesszhan,
	quic_khsieh, marijn.suijten, neil.armstrong

Move dpu_encoder_helper_phys_setup_cdm to dpu_encoder in preparation for
implementing YUV420 over DP, which requires CDM compatibility.

Changes in v2:
	- Slightly change the wording of the commit text to make clear
	  that YUV over DP requires CDM

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 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   | 83 -------------------
 3 files changed, 87 insertions(+), 83 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 467f874979d5c..3c55d6290b708 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2121,6 +2121,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 204d7cc3c1de8..f43d57d9c74e1 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..32a7a31b667be 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
-- 
2.39.2


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

* [PATCH v3 06/19] drm/msm/dp: rename wide_bus_en to wide_bus_supported
  2024-02-14 18:03 [PATCH v3 00/19] Add support for CDM over DP Paloma Arellano
                   ` (4 preceding siblings ...)
  2024-02-14 18:03 ` [PATCH v3 05/19] drm/msm/dpu: move dpu_encoder_helper_phys_setup_cdm to dpu_encoder Paloma Arellano
@ 2024-02-14 18:03 ` Paloma Arellano
  2024-02-14 18:03 ` [PATCH v3 07/19] drm/msm/dp: store mode YUV420 information to be used by rest of DP Paloma Arellano
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 33+ messages in thread
From: Paloma Arellano @ 2024-02-14 18:03 UTC (permalink / raw)
  To: freedreno
  Cc: Paloma Arellano, linux-arm-msm, dri-devel, robdclark, seanpaul,
	swboyd, dmitry.baryshkov, quic_abhinavk, quic_jesszhan,
	quic_khsieh, marijn.suijten, neil.armstrong

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>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 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] 33+ messages in thread

* [PATCH v3 07/19] drm/msm/dp: store mode YUV420 information to be used by rest of DP
  2024-02-14 18:03 [PATCH v3 00/19] Add support for CDM over DP Paloma Arellano
                   ` (5 preceding siblings ...)
  2024-02-14 18:03 ` [PATCH v3 06/19] drm/msm/dp: rename wide_bus_en to wide_bus_supported Paloma Arellano
@ 2024-02-14 18:03 ` Paloma Arellano
  2024-02-14 18:03 ` [PATCH v3 08/19] drm/msm/dp: check if VSC SDP is supported in DP programming Paloma Arellano
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 33+ messages in thread
From: Paloma Arellano @ 2024-02-14 18:03 UTC (permalink / raw)
  To: freedreno
  Cc: Paloma Arellano, linux-arm-msm, dri-devel, robdclark, seanpaul,
	swboyd, dmitry.baryshkov, quic_abhinavk, quic_jesszhan,
	quic_khsieh, marijn.suijten, neil.armstrong

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>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 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] 33+ messages in thread

* [PATCH v3 08/19] drm/msm/dp: check if VSC SDP is supported in DP programming
  2024-02-14 18:03 [PATCH v3 00/19] Add support for CDM over DP Paloma Arellano
                   ` (6 preceding siblings ...)
  2024-02-14 18:03 ` [PATCH v3 07/19] drm/msm/dp: store mode YUV420 information to be used by rest of DP Paloma Arellano
@ 2024-02-14 18:03 ` Paloma Arellano
  2024-02-14 18:03 ` [PATCH v3 09/19] drm/msm/dpu: move widebus logic to its own API Paloma Arellano
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 33+ messages in thread
From: Paloma Arellano @ 2024-02-14 18:03 UTC (permalink / raw)
  To: freedreno
  Cc: Paloma Arellano, linux-arm-msm, dri-devel, robdclark, seanpaul,
	swboyd, dmitry.baryshkov, quic_abhinavk, quic_jesszhan,
	quic_khsieh, marijn.suijten, neil.armstrong

In the DP driver, check if VSC SDP is supported and propagate this value
to dp_panel. In dp_display's dp_mode, the out_fmt_is_yuv_420 parameter
must also utilize this value since YUV420 is only allowed when VSC SDP
is supported.

Changes in v2:
	- Move DP programming when VSC SDP is supported to this patch

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/gpu/drm/msm/dp/dp_display.c | 5 ++++-
 drivers/gpu/drm/msm/dp/dp_panel.c   | 1 +
 drivers/gpu/drm/msm/dp/dp_panel.h   | 1 +
 3 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index ddac55f45a722..6323dc08d5eb8 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1595,8 +1595,10 @@ void dp_bridge_mode_set(struct drm_bridge *drm_bridge,
 	struct msm_dp_bridge *dp_bridge = to_dp_bridge(drm_bridge);
 	struct msm_dp *dp = dp_bridge->dp_display;
 	struct dp_display_private *dp_display;
+	struct dp_panel *dp_panel;
 
 	dp_display = container_of(dp, struct dp_display_private, dp_display);
+	dp_panel = dp_display->panel;
 
 	memset(&dp_display->dp_mode, 0x0, sizeof(struct dp_display_mode));
 
@@ -1617,7 +1619,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;
 
 	/* 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..db1942794f1a4 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
@@ -53,6 +53,7 @@ static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
 	if (rc)
 		return rc;
 
+	dp_panel->vsc_sdp_supported = drm_dp_vsc_sdp_supported(panel->aux, dpcd);
 	link_info = &dp_panel->link_info;
 	link_info->revision = dpcd[DP_DPCD_REV];
 	major = (link_info->revision >> 4) & 0x0f;
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h
index 6ec68be9f2366..e843f5062d1f6 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.h
+++ b/drivers/gpu/drm/msm/dp/dp_panel.h
@@ -46,6 +46,7 @@ struct dp_panel {
 	struct dp_display_mode dp_mode;
 	struct dp_panel_psr psr_cap;
 	bool video_test;
+	bool vsc_sdp_supported;
 
 	u32 vic;
 	u32 max_dp_lanes;
-- 
2.39.2


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

* [PATCH v3 09/19] drm/msm/dpu: move widebus logic to its own API
  2024-02-14 18:03 [PATCH v3 00/19] Add support for CDM over DP Paloma Arellano
                   ` (7 preceding siblings ...)
  2024-02-14 18:03 ` [PATCH v3 08/19] drm/msm/dp: check if VSC SDP is supported in DP programming Paloma Arellano
@ 2024-02-14 18:03 ` Paloma Arellano
  2024-02-14 18:03 ` [PATCH v3 10/19] drm/msm/dp: program config ctrl for YUV420 over DP Paloma Arellano
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 33+ messages in thread
From: Paloma Arellano @ 2024-02-14 18:03 UTC (permalink / raw)
  To: freedreno
  Cc: Paloma Arellano, linux-arm-msm, dri-devel, robdclark, seanpaul,
	swboyd, dmitry.baryshkov, quic_abhinavk, quic_jesszhan,
	quic_khsieh, marijn.suijten, neil.armstrong

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>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 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 3c55d6290b708..7e7796561009a 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];
+
+	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 dpu_enc->wide_bus_en;
+	return false;
 }
 
 bool dpu_encoder_is_dsc_enabled(const struct drm_encoder *drm_enc)
@@ -1199,26 +1211,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 fe6b1d312a742..67aef59c1f99c 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] 33+ messages in thread

* [PATCH v3 10/19] drm/msm/dp: program config ctrl for YUV420 over DP
  2024-02-14 18:03 [PATCH v3 00/19] Add support for CDM over DP Paloma Arellano
                   ` (8 preceding siblings ...)
  2024-02-14 18:03 ` [PATCH v3 09/19] drm/msm/dpu: move widebus logic to its own API Paloma Arellano
@ 2024-02-14 18:03 ` Paloma Arellano
  2024-02-14 18:03 ` [PATCH v3 11/19] drm/msm/dp: change clock related programming " Paloma Arellano
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 33+ messages in thread
From: Paloma Arellano @ 2024-02-14 18:03 UTC (permalink / raw)
  To: freedreno
  Cc: Paloma Arellano, linux-arm-msm, dri-devel, robdclark, seanpaul,
	swboyd, dmitry.baryshkov, quic_abhinavk, quic_jesszhan,
	quic_khsieh, marijn.suijten, neil.armstrong

Change relevant DP controller related programming for YUV420 cases.
Program the configuration control register to indicate YUV420.

Changes in v2:
	- Create a new patch only for configuration control programming

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/gpu/drm/msm/dp/dp_ctrl.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index 77a8d9366ed7b..da8f0d9f98718 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;
-- 
2.39.2


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

* [PATCH v3 11/19] drm/msm/dp: change clock related programming for YUV420 over DP
  2024-02-14 18:03 [PATCH v3 00/19] Add support for CDM over DP Paloma Arellano
                   ` (9 preceding siblings ...)
  2024-02-14 18:03 ` [PATCH v3 10/19] drm/msm/dp: program config ctrl for YUV420 over DP Paloma Arellano
@ 2024-02-14 18:03 ` Paloma Arellano
  2024-02-14 18:03 ` [PATCH v3 12/19] drm/msm/dp: move parity calculation to dp_utils Paloma Arellano
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 33+ messages in thread
From: Paloma Arellano @ 2024-02-14 18:03 UTC (permalink / raw)
  To: freedreno
  Cc: Paloma Arellano, linux-arm-msm, dri-devel, robdclark, seanpaul,
	swboyd, dmitry.baryshkov, quic_abhinavk, quic_jesszhan,
	quic_khsieh, marijn.suijten, neil.armstrong

Change all relevant DP controller related programming for YUV420 cases.
Namely, change the pixel clock math to consider YUV420 and modify the
MVID programming to consider YUV420.

Changes in v2:
	- Move configuration control programming to a different commit
	- Slight code simplification
	- Add VSC SDP check when doing mode_pclk_khz division in
	  dp_bridge_mode_valid

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 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    | 9 ++++++---
 drivers/gpu/drm/msm/dp/dp_display.c | 4 ++++
 4 files changed, 15 insertions(+), 5 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 da8f0d9f98718..209cf2a35642f 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -960,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;
@@ -1766,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",
@@ -1881,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",
@@ -1920,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 6323dc08d5eb8..4b04388719363 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -933,6 +933,10 @@ 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) &&
+	    dp_display->panel->vsc_sdp_supported)
+		mode_pclk_khz /= 2;
+
 	mode_bpp = dp->connector->display_info.bpc * num_components;
 	if (!mode_bpp)
 		mode_bpp = default_bpp;
-- 
2.39.2


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

* [PATCH v3 12/19] drm/msm/dp: move parity calculation to dp_utils
  2024-02-14 18:03 [PATCH v3 00/19] Add support for CDM over DP Paloma Arellano
                   ` (10 preceding siblings ...)
  2024-02-14 18:03 ` [PATCH v3 11/19] drm/msm/dp: change clock related programming " Paloma Arellano
@ 2024-02-14 18:03 ` Paloma Arellano
  2024-02-14 18:03 ` [PATCH v3 13/19] drm/msm/dp: add VSC SDP support for YUV420 over DP Paloma Arellano
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 33+ messages in thread
From: Paloma Arellano @ 2024-02-14 18:03 UTC (permalink / raw)
  To: freedreno
  Cc: Paloma Arellano, linux-arm-msm, dri-devel, robdclark, seanpaul,
	swboyd, dmitry.baryshkov, quic_abhinavk, quic_jesszhan,
	quic_khsieh, marijn.suijten, neil.armstrong

Parity calculation is necessary for VSC SDP implementation. Therefore
create new files dp_utils.c and dp_utils.h and move the parity
calculating functions here. This ensures that they are usable by SDP
programming in both dp_catalog.c and dp_audio.c

Changes in v3:
	- Change ordering of the header byte macros

Changes in v2:
	- Create new files dp_utils.c and dp_utils.h
	- Move the parity calculation to these new files instead of
	  having them in dp_catalog.c and dp_catalog.h

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/gpu/drm/msm/Makefile      |   3 +-
 drivers/gpu/drm/msm/dp/dp_audio.c | 101 +++++-------------------------
 drivers/gpu/drm/msm/dp/dp_utils.c |  73 +++++++++++++++++++++
 drivers/gpu/drm/msm/dp/dp_utils.h |  22 +++++++
 4 files changed, 112 insertions(+), 87 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/dp/dp_utils.c
 create mode 100644 drivers/gpu/drm/msm/dp/dp_utils.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index b1173128b5b97..998b155e4a979 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -129,7 +129,8 @@ msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \
 	dp/dp_panel.o \
 	dp/dp_parser.o \
 	dp/dp_power.o \
-	dp/dp_audio.o
+	dp/dp_audio.o \
+	dp/dp_utils.o
 
 msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o
 
diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c
index 4a2e479723a85..7634e4b742084 100644
--- a/drivers/gpu/drm/msm/dp/dp_audio.c
+++ b/drivers/gpu/drm/msm/dp/dp_audio.c
@@ -15,13 +15,7 @@
 #include "dp_audio.h"
 #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
+#include "dp_utils.h"
 
 struct dp_audio_private {
 	struct platform_device *audio_pdev;
@@ -36,71 +30,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 +63,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_utils_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 +76,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_utils_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 +91,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_utils_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 +113,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_utils_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 +127,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_utils_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 +141,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_utils_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 +162,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_utils_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 +176,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_utils_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 +190,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_utils_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 +211,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_utils_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 +225,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_utils_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 +239,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_utils_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 +260,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_utils_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 +274,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_utils_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_utils.c b/drivers/gpu/drm/msm/dp/dp_utils.c
new file mode 100644
index 0000000000000..3a44fe738c004
--- /dev/null
+++ b/drivers/gpu/drm/msm/dp/dp_utils.c
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2024, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/types.h>
+
+#include "dp_utils.h"
+
+u8 dp_utils_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;
+}
+
+u8 dp_utils_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;
+}
+
+u8 dp_utils_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_utils_get_g1_value(ci);
+		x0 = dp_utils_get_g0_value(ci);
+	}
+
+	parity_byte = x1 | (x0 << 4);
+
+	return parity_byte;
+}
diff --git a/drivers/gpu/drm/msm/dp/dp_utils.h b/drivers/gpu/drm/msm/dp/dp_utils.h
new file mode 100644
index 0000000000000..5a505cbf3432b
--- /dev/null
+++ b/drivers/gpu/drm/msm/dp/dp_utils.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2024, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DP_UTILS_H_
+#define _DP_UTILS_H_
+
+#define HEADER_BYTE_0_BIT	 0
+#define PARITY_BYTE_0_BIT	 8
+#define HEADER_BYTE_1_BIT	16
+#define PARITY_BYTE_1_BIT	24
+#define HEADER_BYTE_2_BIT	 0
+#define PARITY_BYTE_2_BIT	 8
+#define HEADER_BYTE_3_BIT	16
+#define PARITY_BYTE_3_BIT	24
+
+u8 dp_utils_get_g0_value(u8 data);
+u8 dp_utils_get_g1_value(u8 data);
+u8 dp_utils_calculate_parity(u32 data);
+
+#endif /* _DP_UTILS_H_ */
-- 
2.39.2


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

* [PATCH v3 13/19] drm/msm/dp: add VSC SDP support for YUV420 over DP
  2024-02-14 18:03 [PATCH v3 00/19] Add support for CDM over DP Paloma Arellano
                   ` (11 preceding siblings ...)
  2024-02-14 18:03 ` [PATCH v3 12/19] drm/msm/dp: move parity calculation to dp_utils Paloma Arellano
@ 2024-02-14 18:03 ` Paloma Arellano
  2024-02-14 19:39   ` Dmitry Baryshkov
  2024-02-14 18:03 ` [PATCH v3 14/19] drm/msm/dpu: add support of new peripheral flush mechanism Paloma Arellano
                   ` (5 subsequent siblings)
  18 siblings, 1 reply; 33+ messages in thread
From: Paloma Arellano @ 2024-02-14 18:03 UTC (permalink / raw)
  To: freedreno
  Cc: Paloma Arellano, linux-arm-msm, dri-devel, robdclark, seanpaul,
	swboyd, dmitry.baryshkov, quic_abhinavk, quic_jesszhan,
	quic_khsieh, marijn.suijten, neil.armstrong

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.

Changes in v3:
	- Create a new struct, msm_dp_sdp_with_parity, which holds the
	  packing information for VSC SDP
	- Use drm_dp_vsc_sdp_pack() to pack the data into the new
	  msm_dp_sdp_with_parity struct instead of specifically packing
	  for YUV420 format
	- Modify dp_catalog_panel_send_vsc_sdp() to send the VSC SDP
	  data using the new msm_dp_sdp_with_parity struct

Changes in v2:
	- Rename GENERIC0_SDPSIZE macro to GENERIC0_SDPSIZE_VALID
	- Remove dp_sdp from the dp_catalog struct since this data is
	  being allocated at the point used
	- Create a new function in dp_utils to pack the VSC SDP data
	  into a buffer
	- Create a new function that packs the SDP header bytes into a
	  buffer. This function is made generic so that it can be
	  utilized by dp_audio
	  header bytes into a buffer
	- Create a new function in dp_utils that takes the packed buffer
	  and writes to the DP_GENERIC0_* registers
	- Split the dp_catalog_panel_config_vsc_sdp() function into two
	  to disable/enable sending VSC SDP packets
	- Check the DP HW version using the original useage of
	  dp_catalog_hw_revision() and correct the version checking
	  logic
	- Rename dp_panel_setup_vsc_sdp() to
	  dp_panel_setup_vsc_sdp_yuv_420() to explicitly state that
	  currently VSC SDP is only being set up to support YUV420 modes

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 drivers/gpu/drm/msm/dp/dp_catalog.c | 113 ++++++++++++++++++++++++++++
 drivers/gpu/drm/msm/dp/dp_catalog.h |   7 ++
 drivers/gpu/drm/msm/dp/dp_ctrl.c    |   4 +
 drivers/gpu/drm/msm/dp/dp_panel.c   |  55 ++++++++++++++
 drivers/gpu/drm/msm/dp/dp_reg.h     |   3 +
 drivers/gpu/drm/msm/dp/dp_utils.c   |  48 ++++++++++++
 drivers/gpu/drm/msm/dp/dp_utils.h   |  18 +++++
 7 files changed, 248 insertions(+)

diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 5d84c089e520a..61d5317efe683 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -901,6 +901,119 @@ int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog)
 	return 0;
 }
 
+static void dp_catalog_panel_send_vsc_sdp(struct dp_catalog *dp_catalog,
+					  struct msm_dp_sdp_with_parity *msm_dp_sdp)
+{
+	struct dp_catalog_private *catalog;
+	u32 val;
+
+	if (!dp_catalog) {
+		DRM_ERROR("invalid input\n");
+		return;
+	}
+
+	catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
+
+	val = ((msm_dp_sdp->vsc_sdp.sdp_header.HB0) << HEADER_BYTE_0_BIT |
+	       (msm_dp_sdp->pb.PB0 << PARITY_BYTE_0_BIT) |
+	       (msm_dp_sdp->vsc_sdp.sdp_header.HB1) << HEADER_BYTE_1_BIT |
+	       (msm_dp_sdp->pb.PB1 << PARITY_BYTE_1_BIT));
+	dp_write_link(catalog, MMSS_DP_GENERIC0_0, val);
+
+	val = ((msm_dp_sdp->vsc_sdp.sdp_header.HB2) << HEADER_BYTE_2_BIT |
+	       (msm_dp_sdp->pb.PB2 << PARITY_BYTE_2_BIT) |
+	       (msm_dp_sdp->vsc_sdp.sdp_header.HB3) << HEADER_BYTE_3_BIT |
+	       (msm_dp_sdp->pb.PB3 << PARITY_BYTE_3_BIT));
+	dp_write_link(catalog, MMSS_DP_GENERIC0_1, val);
+
+	val = ((msm_dp_sdp->vsc_sdp.db[16]) | (msm_dp_sdp->vsc_sdp.db[17] << 8) |
+	       (msm_dp_sdp->vsc_sdp.db[18] << 16));
+	dp_write_link(catalog, MMSS_DP_GENERIC0_6, val);
+}
+
+static void dp_catalog_panel_update_sdp(struct dp_catalog *dp_catalog)
+{
+	struct dp_catalog_private *catalog;
+	u32 hw_revision;
+
+	catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
+
+	hw_revision = dp_catalog_hw_revision(dp_catalog);
+	if (hw_revision < DP_HW_VERSION_1_2 && hw_revision >= DP_HW_VERSION_1_0) {
+		dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x01);
+		dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x00);
+	}
+}
+
+void dp_catalog_panel_enable_vsc_sdp(struct dp_catalog *dp_catalog,
+				     struct msm_dp_sdp_with_parity *msm_dp_sdp)
+{
+	struct dp_catalog_private *catalog;
+	u32 cfg, cfg2, misc;
+
+	if (!dp_catalog) {
+		DRM_ERROR("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);
+
+	cfg |= GEN0_SDP_EN;
+	dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
+
+	cfg2 |= GENERIC0_SDPSIZE_VALID;
+	dp_write_link(catalog, MMSS_DP_SDP_CFG2, cfg2);
+
+	dp_catalog_panel_send_vsc_sdp(dp_catalog, msm_dp_sdp);
+
+	/* indicates presence of VSC (BIT(6) of MISC1) */
+	misc |= DP_MISC1_VSC_SDP;
+
+	drm_dbg_dp(catalog->drm_dev, "vsc sdp enable=1\n");
+
+	pr_debug("misc settings = 0x%x\n", misc);
+	dp_write_link(catalog, REG_DP_MISC1_MISC0, misc);
+
+	dp_catalog_panel_update_sdp(dp_catalog);
+}
+
+void dp_catalog_panel_disable_vsc_sdp(struct dp_catalog *dp_catalog)
+{
+	struct dp_catalog_private *catalog;
+	u32 cfg, cfg2, misc;
+
+	if (!dp_catalog) {
+		DRM_ERROR("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);
+
+	cfg &= ~GEN0_SDP_EN;
+	dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
+
+	cfg2 &= ~GENERIC0_SDPSIZE_VALID;
+	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=0\n");
+
+	pr_debug("misc settings = 0x%x\n", misc);
+	dp_write_link(catalog, REG_DP_MISC1_MISC0, misc);
+
+	dp_catalog_panel_update_sdp(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_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
index 6cb5e2a243de2..4bf08c27a9bf3 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -9,6 +9,7 @@
 #include <drm/drm_modes.h>
 
 #include "dp_parser.h"
+#include "dp_utils.h"
 #include "disp/msm_disp_snapshot.h"
 
 /* interrupts */
@@ -30,6 +31,9 @@
 
 #define DP_AUX_CFG_MAX_VALUE_CNT 3
 
+#define DP_HW_VERSION_1_0	0x10000000
+#define DP_HW_VERSION_1_2	0x10020000
+
 /* PHY AUX config registers */
 enum dp_phy_aux_config_type {
 	PHY_AUX_CFG0,
@@ -124,6 +128,9 @@ 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_enable_vsc_sdp(struct dp_catalog *dp_catalog,
+				     struct msm_dp_sdp_with_parity *msm_dp_sdp);
+void dp_catalog_panel_disable_vsc_sdp(struct dp_catalog *dp_catalog);
 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..beef86b1aaf81 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_disable_vsc_sdp(ctrl->catalog);
+
 	/* 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_disable_vsc_sdp(ctrl->catalog);
+
 	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 db1942794f1a4..18420a7ba4ab3 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
@@ -4,6 +4,7 @@
  */
 
 #include "dp_panel.h"
+#include "dp_utils.h"
 
 #include <drm/drm_connector.h>
 #include <drm/drm_edid.h>
@@ -281,6 +282,56 @@ 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);
 }
 
+static int dp_panel_setup_vsc_sdp_yuv_420(struct dp_panel *dp_panel)
+{
+	struct dp_catalog *catalog;
+	struct dp_panel_private *panel;
+	struct dp_display_mode *dp_mode;
+	struct drm_dp_vsc_sdp vsc_sdp_data;
+	struct msm_dp_sdp_with_parity msm_dp_sdp;
+	ssize_t len;
+	int rc = 0;
+
+	if (!dp_panel) {
+		DRM_ERROR("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(&vsc_sdp_data, 0, sizeof(vsc_sdp_data));
+
+	/* VSC SDP header as per table 2-118 of DP 1.4 specification */
+	vsc_sdp_data.sdp_type = DP_SDP_VSC;
+	vsc_sdp_data.revision = 0x05;
+	vsc_sdp_data.length = 0x13;
+
+	/* VSC SDP Payload for DB16 */
+	vsc_sdp_data.pixelformat = DP_PIXELFORMAT_YUV420;
+	vsc_sdp_data.colorimetry = DP_COLORIMETRY_DEFAULT;
+
+	/* VSC SDP Payload for DB17 */
+	vsc_sdp_data.bpc = dp_mode->bpp / 3;
+	vsc_sdp_data.dynamic_range = DP_DYNAMIC_RANGE_CTA;
+
+	/* VSC SDP Payload for DB18 */
+	vsc_sdp_data.content_type = DP_CONTENT_TYPE_GRAPHICS;
+
+	// rc = dp_utils_pack_vsc_sdp(&vsc_sdp_data, &sdp_header, gen_buffer, buff_size);
+	len = dp_utils_pack_vsc_sdp(&vsc_sdp_data, &msm_dp_sdp);
+	if (len < 0) {
+		DRM_ERROR("unable to pack vsc sdp\n");
+		return len;
+	}
+
+	dp_catalog_panel_enable_vsc_sdp(catalog, &msm_dp_sdp);
+
+	return rc;
+}
+
 void dp_panel_dump_regs(struct dp_panel *dp_panel)
 {
 	struct dp_catalog *catalog;
@@ -344,6 +395,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_yuv_420(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..2983756c125cd 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_VALID			(0x00010000)
 
 #define MMSS_DP_AUDIO_STREAM_0			(0x00000240)
 #define MMSS_DP_AUDIO_STREAM_1			(0x00000244)
diff --git a/drivers/gpu/drm/msm/dp/dp_utils.c b/drivers/gpu/drm/msm/dp/dp_utils.c
index 3a44fe738c004..81601f3c414fc 100644
--- a/drivers/gpu/drm/msm/dp/dp_utils.c
+++ b/drivers/gpu/drm/msm/dp/dp_utils.c
@@ -4,6 +4,7 @@
  */
 
 #include <linux/types.h>
+#include <drm/drm_print.h>
 
 #include "dp_utils.h"
 
@@ -71,3 +72,50 @@ u8 dp_utils_calculate_parity(u32 data)
 
 	return parity_byte;
 }
+
+ssize_t dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, struct msm_dp_vsc_sdp_parity *pb,
+				 size_t size)
+{
+	u8 header;
+
+	size_t length = sizeof(struct msm_dp_vsc_sdp_parity);
+
+	if (size < length)
+		return -ENOSPC;
+
+	memset(pb, 0, size);
+
+	header = sdp_header->HB0;
+	pb->PB0 = dp_utils_calculate_parity(header);
+
+	header = sdp_header->HB1;
+	pb->PB1 = dp_utils_calculate_parity(header);
+
+	header = sdp_header->HB2;
+	pb->PB2 = dp_utils_calculate_parity(header);
+
+	header = sdp_header->HB3;
+	pb->PB3 = dp_utils_calculate_parity(header);
+
+	return length;
+}
+
+ssize_t dp_utils_pack_vsc_sdp(struct drm_dp_vsc_sdp *vsc, struct msm_dp_sdp_with_parity *msm_dp_sdp)
+{
+	ssize_t len;
+
+	len = drm_dp_vsc_sdp_pack(vsc, &msm_dp_sdp->vsc_sdp, sizeof(msm_dp_sdp->vsc_sdp));
+	if (len < 0) {
+		DRM_ERROR("unable to pack vsc sdp\n");
+		return len;
+	}
+
+	len = dp_utils_pack_sdp_header(&msm_dp_sdp->vsc_sdp.sdp_header, &msm_dp_sdp->pb,
+				       sizeof(msm_dp_sdp->pb));
+	if (len < 0) {
+		DRM_ERROR("unable to pack sdp header\n");
+		return len;
+	}
+
+	return len;
+}
diff --git a/drivers/gpu/drm/msm/dp/dp_utils.h b/drivers/gpu/drm/msm/dp/dp_utils.h
index 5a505cbf3432b..6946bc51cae97 100644
--- a/drivers/gpu/drm/msm/dp/dp_utils.h
+++ b/drivers/gpu/drm/msm/dp/dp_utils.h
@@ -6,6 +6,8 @@
 #ifndef _DP_UTILS_H_
 #define _DP_UTILS_H_
 
+#include <drm/display/drm_dp_helper.h>
+
 #define HEADER_BYTE_0_BIT	 0
 #define PARITY_BYTE_0_BIT	 8
 #define HEADER_BYTE_1_BIT	16
@@ -15,8 +17,24 @@
 #define HEADER_BYTE_3_BIT	16
 #define PARITY_BYTE_3_BIT	24
 
+struct msm_dp_vsc_sdp_parity {
+	u8 PB0;
+	u8 PB1;
+	u8 PB2;
+	u8 PB3;
+} __packed;
+
+struct msm_dp_sdp_with_parity {
+	struct dp_sdp vsc_sdp;
+	struct msm_dp_vsc_sdp_parity pb;
+};
+
 u8 dp_utils_get_g0_value(u8 data);
 u8 dp_utils_get_g1_value(u8 data);
 u8 dp_utils_calculate_parity(u32 data);
+ssize_t dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, struct msm_dp_vsc_sdp_parity *pb,
+				 size_t size);
+ssize_t dp_utils_pack_vsc_sdp(struct drm_dp_vsc_sdp *vsc,
+			      struct msm_dp_sdp_with_parity *msm_dp_sdp);
 
 #endif /* _DP_UTILS_H_ */
-- 
2.39.2


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

* [PATCH v3 14/19] drm/msm/dpu: add support of new peripheral flush mechanism
  2024-02-14 18:03 [PATCH v3 00/19] Add support for CDM over DP Paloma Arellano
                   ` (12 preceding siblings ...)
  2024-02-14 18:03 ` [PATCH v3 13/19] drm/msm/dp: add VSC SDP support for YUV420 over DP Paloma Arellano
@ 2024-02-14 18:03 ` Paloma Arellano
  2024-02-14 18:03 ` [PATCH v3 15/19] drm/msm/dp: enable SDP and SDE periph flush update Paloma Arellano
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 33+ messages in thread
From: Paloma Arellano @ 2024-02-14 18:03 UTC (permalink / raw)
  To: freedreno
  Cc: Kuogee Hsieh, linux-arm-msm, dri-devel, robdclark, seanpaul,
	swboyd, dmitry.baryshkov, quic_abhinavk, quic_jesszhan,
	marijn.suijten, neil.armstrong, Paloma Arellano

From: Kuogee Hsieh <quic_khsieh@quicinc.com>

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

Changes in v2:
	- Fixed some misalignment issues

Signed-off-by: Kuogee Hsieh <quic_khsieh@quicinc.com>
Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 17 +++++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 10 ++++++++++
 2 files changed, 27 insertions(+)

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..a06f69d0b257d 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_v1(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_v1;
+
 		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..ef56280bea932 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] 33+ messages in thread

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

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

Changes in v3:
	- Clear up that the DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE
	  macro is setting bits [24:23] to a value of 3

Changes in v2:
	- Use the original dp_catalog_hw_revision() function to
	  correctly check the DP HW version

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 drivers/gpu/drm/msm/dp/dp_catalog.c | 17 +++++++++++++++++
 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     |  5 +++++
 4 files changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 61d5317efe683..823eeba7e71d3 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -440,6 +440,23 @@ 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, hw_revision;
+	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);
+
+	hw_revision = dp_catalog_hw_revision(dp_catalog);
+	if (hw_revision >= DP_HW_VERSION_1_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 4bf08c27a9bf3..eb05a37837beb 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -98,6 +98,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 beef86b1aaf81..f1e7b0a5ee5d1 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 2983756c125cd..d4fb8572cd1e4 100644
--- a/drivers/gpu/drm/msm/dp/dp_reg.h
+++ b/drivers/gpu/drm/msm/dp/dp_reg.h
@@ -6,6 +6,9 @@
 #ifndef _DP_REG_H_
 #define _DP_REG_H_
 
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+
 /* DP_TX Registers */
 #define REG_DP_HW_VERSION			(0x00000000)
 
@@ -102,6 +105,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	FIELD_PREP(GENMASK(24, 23), 3)
 #define DP_MAINLINK_FB_BOUNDARY_SEL		(0x02000000)
 
 #define REG_DP_STATE_CTRL			(0x00000004)
-- 
2.39.2


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

* [PATCH v3 16/19] drm/msm/dpu: modify encoder programming for CDM over DP
  2024-02-14 18:03 [PATCH v3 00/19] Add support for CDM over DP Paloma Arellano
                   ` (14 preceding siblings ...)
  2024-02-14 18:03 ` [PATCH v3 15/19] drm/msm/dp: enable SDP and SDE periph flush update Paloma Arellano
@ 2024-02-14 18:03 ` Paloma Arellano
  2024-02-15  8:45   ` Dmitry Baryshkov
  2024-02-14 18:03 ` [PATCH v3 17/19] drm/msm/dpu: modify timing engine programming for YUV420 " Paloma Arellano
                   ` (2 subsequent siblings)
  18 siblings, 1 reply; 33+ messages in thread
From: Paloma Arellano @ 2024-02-14 18:03 UTC (permalink / raw)
  To: freedreno
  Cc: Paloma Arellano, linux-arm-msm, dri-devel, robdclark, seanpaul,
	swboyd, dmitry.baryshkov, quic_abhinavk, quic_jesszhan,
	quic_khsieh, marijn.suijten, neil.armstrong

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

Changes in v2:
	- Move timing engine programming to a separate patch from this
	  one
	- Move update_pending_flush_periph() invocation completely to
	  this patch
	- Change the logic of dpu_encoder_get_drm_fmt() so that it only
	  calls drm_mode_is_420_only() instead of doing additional
	  unnecessary checks
	- Create new functions msm_dp_needs_periph_flush() and it's
	  supporting function dpu_encoder_needs_periph_flush() to check
	  if the mode is YUV420 and VSC SDP is enabled before doing a
	  peripheral flush

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 35 +++++++++++++++++++
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  | 13 +++++++
 .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 19 ++++++++++
 drivers/gpu/drm/msm/dp/dp_display.c           | 18 ++++++++++
 drivers/gpu/drm/msm/msm_drv.h                 | 17 ++++++++-
 5 files changed, 101 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 7e7796561009a..6280c6be6dca9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -222,6 +222,41 @@ 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(struct dpu_encoder_phys *phys_enc)
+{
+	struct drm_encoder *drm_enc;
+	struct dpu_encoder_virt *dpu_enc;
+	struct drm_display_info *info;
+	struct drm_display_mode *mode;
+
+	drm_enc = phys_enc->parent;
+	dpu_enc = to_dpu_encoder_virt(drm_enc);
+	info = &dpu_enc->connector->display_info;
+	mode = &phys_enc->cached_mode;
+
+	if (drm_mode_is_420_only(info, mode))
+		return DRM_FORMAT_YUV420;
+
+	return DRM_FORMAT_RGB888;
+}
+
+bool dpu_encoder_needs_periph_flush(struct dpu_encoder_phys *phys_enc)
+{
+	struct drm_encoder *drm_enc;
+	struct dpu_encoder_virt *dpu_enc;
+	struct msm_display_info *disp_info;
+	struct msm_drm_private *priv;
+	struct drm_display_mode *mode;
+
+	drm_enc = phys_enc->parent;
+	dpu_enc = to_dpu_encoder_virt(drm_enc);
+	disp_info = &dpu_enc->disp_info;
+	priv = drm_enc->dev->dev_private;
+	mode = &phys_enc->cached_mode;
+
+	return phys_enc->hw_intf->cap->type == INTF_DP && phys_enc->hw_cdm &&
+	       msm_dp_needs_periph_flush(priv->dp[disp_info->h_tile_instance[0]], mode);
+}
 
 bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc)
 {
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 f43d57d9c74e1..211a3d90eb690 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -341,6 +341,19 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
  */
 unsigned int dpu_encoder_helper_get_dsc(struct dpu_encoder_phys *phys_enc);
 
+/**
+ * dpu_encoder_get_drm_fmt - return DRM fourcc format
+ * @phys_enc: Pointer to physical encoder structure
+ */
+u32 dpu_encoder_get_drm_fmt(struct dpu_encoder_phys *phys_enc);
+
+/**
+ * dpu_encoder_needs_periph_flush - return true if physical encoder requires
+ *	peripheral flush
+ * @phys_enc: Pointer to physical encoder structure
+ */
+bool dpu_encoder_needs_periph_flush(struct dpu_encoder_phys *phys_enc);
+
 /**
  * dpu_encoder_helper_split_config - split display configuration helper function
  *	This helper function may be used by physical encoders to configure
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 f02411b062c4c..e29bc4bd39208 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
@@ -415,8 +415,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);
+	fmt = dpu_get_dpu_format(fmt_fourcc);
 
 	DPU_DEBUG_VIDENC(phys_enc, "\n");
 
@@ -425,6 +432,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);
 
 	/*
@@ -440,6 +449,16 @@ 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_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 && dpu_encoder_needs_periph_flush(phys_enc))
+		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/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 4b04388719363..ebcc76ef1d590 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1397,6 +1397,24 @@ 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 && drm_mode_is_420_only(info, mode);
+}
+
+bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display,
+			       const struct drm_display_mode *mode)
+{
+	return msm_dp_is_yuv_420_enabled(dp_display, 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..b876ebd48effe 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -387,7 +387,10 @@ 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_needs_periph_flush(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 +412,18 @@ 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_needs_periph_flush(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] 33+ messages in thread

* [PATCH v3 17/19] drm/msm/dpu: modify timing engine programming for YUV420 over DP
  2024-02-14 18:03 [PATCH v3 00/19] Add support for CDM over DP Paloma Arellano
                   ` (15 preceding siblings ...)
  2024-02-14 18:03 ` [PATCH v3 16/19] drm/msm/dpu: modify encoder programming for CDM over DP Paloma Arellano
@ 2024-02-14 18:03 ` Paloma Arellano
  2024-02-15  8:55   ` Dmitry Baryshkov
  2024-02-14 18:03 ` [PATCH v3 18/19] drm/msm/dpu: reserve CDM blocks for DP if mode is YUV420 Paloma Arellano
  2024-02-14 18:03 ` [PATCH v3 19/19] drm/msm/dp: allow YUV420 mode for DP connector when CDM available Paloma Arellano
  18 siblings, 1 reply; 33+ messages in thread
From: Paloma Arellano @ 2024-02-14 18:03 UTC (permalink / raw)
  To: freedreno
  Cc: Paloma Arellano, linux-arm-msm, dri-devel, robdclark, seanpaul,
	swboyd, dmitry.baryshkov, quic_abhinavk, quic_jesszhan,
	quic_khsieh, marijn.suijten, neil.armstrong

Adjust the encoder timing engine setup programming in the case of video
mode for YUV420 over DP to accommodate CDM.

Changes in v3:
	- Move drm_display_mode's hskew division to another patch
	- Minor cleanup

Changes in v2:
	- Move timing engine programming to this patch

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

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 e29bc4bd39208..04df501d23bfa 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
@@ -236,7 +236,7 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
 	struct drm_display_mode mode;
 	struct dpu_hw_intf_timing_params timing_params = { 0 };
 	const struct dpu_format *fmt = NULL;
-	u32 fmt_fourcc = DRM_FORMAT_RGB888;
+	u32 fmt_fourcc;
 	unsigned long lock_flags;
 	struct dpu_hw_intf_cfg intf_cfg = { 0 };
 
@@ -255,7 +255,9 @@ 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) {
+	fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc);
+
+	if (phys_enc->split_role != ENC_ROLE_SOLO || fmt_fourcc == DRM_FORMAT_YUV420) {
 		mode.hdisplay >>= 1;
 		mode.htotal >>= 1;
 		mode.hsync_start >>= 1;
@@ -275,6 +277,8 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
 	fmt = dpu_get_dpu_format(fmt_fourcc);
 	DPU_DEBUG_VIDENC(phys_enc, "fmt_fourcc 0x%X\n", fmt_fourcc);
 
+	if (phys_enc->hw_cdm)
+		intf_cfg.cdm = phys_enc->hw_cdm->idx;
 	intf_cfg.intf = phys_enc->hw_intf->idx;
 	intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_VID;
 	intf_cfg.stream_sel = 0; /* Don't care value for video mode */
-- 
2.39.2


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

* [PATCH v3 18/19] drm/msm/dpu: reserve CDM blocks for DP if mode is YUV420
  2024-02-14 18:03 [PATCH v3 00/19] Add support for CDM over DP Paloma Arellano
                   ` (16 preceding siblings ...)
  2024-02-14 18:03 ` [PATCH v3 17/19] drm/msm/dpu: modify timing engine programming for YUV420 " Paloma Arellano
@ 2024-02-14 18:03 ` Paloma Arellano
  2024-02-14 18:03 ` [PATCH v3 19/19] drm/msm/dp: allow YUV420 mode for DP connector when CDM available Paloma Arellano
  18 siblings, 0 replies; 33+ messages in thread
From: Paloma Arellano @ 2024-02-14 18:03 UTC (permalink / raw)
  To: freedreno
  Cc: Paloma Arellano, linux-arm-msm, dri-devel, robdclark, seanpaul,
	swboyd, dmitry.baryshkov, quic_abhinavk, quic_jesszhan,
	quic_khsieh, marijn.suijten, neil.armstrong

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.

Changes in v2:
	- Minor code simplification

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 22 +++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 6280c6be6dca9..ec53e5f4a696d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -639,6 +639,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;
@@ -655,6 +656,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);
@@ -682,21 +684,24 @@ 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) {
+	if (disp_info->intf_type == INTF_WB && conn_state->writeback_job) {
 		fb = conn_state->writeback_job->fb;
 
 		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 (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.
@@ -1137,7 +1142,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] 33+ messages in thread

* [PATCH v3 19/19] drm/msm/dp: allow YUV420 mode for DP connector when CDM available
  2024-02-14 18:03 [PATCH v3 00/19] Add support for CDM over DP Paloma Arellano
                   ` (17 preceding siblings ...)
  2024-02-14 18:03 ` [PATCH v3 18/19] drm/msm/dpu: reserve CDM blocks for DP if mode is YUV420 Paloma Arellano
@ 2024-02-14 18:03 ` Paloma Arellano
  2024-02-15  8:57   ` Dmitry Baryshkov
  18 siblings, 1 reply; 33+ messages in thread
From: Paloma Arellano @ 2024-02-14 18:03 UTC (permalink / raw)
  To: freedreno
  Cc: Paloma Arellano, linux-arm-msm, dri-devel, robdclark, seanpaul,
	swboyd, dmitry.baryshkov, quic_abhinavk, quic_jesszhan,
	quic_khsieh, marijn.suijten, neil.armstrong

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 there is a CDM block available.

Changes in v3:
	- Move setting the connector's ycbcr_420_allowed parameter so
	  that it is not dependent on if the dp_display is not eDP

Changes in v2:
	- Check for if dp_catalog has a CDM block available instead of
	  checking if VSC SDP is allowed when setting the dp connector's
	  ycbcr_420_allowed parameter

Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 4 +++-
 drivers/gpu/drm/msm/dp/dp_display.c     | 4 ++--
 drivers/gpu/drm/msm/dp/dp_drm.c         | 6 +++++-
 drivers/gpu/drm/msm/dp/dp_drm.h         | 3 ++-
 drivers/gpu/drm/msm/msm_drv.h           | 5 +++--
 5 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 723cc1d821431..8d326fb36550a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -565,6 +565,7 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev,
 {
 	struct drm_encoder *encoder = NULL;
 	struct msm_display_info info;
+	bool yuv_supported;
 	int rc;
 	int i;
 
@@ -583,7 +584,8 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev,
 			return PTR_ERR(encoder);
 		}
 
-		rc = msm_dp_modeset_init(priv->dp[i], dev, encoder);
+		yuv_supported = !!dpu_kms->catalog->cdm;
+		rc = msm_dp_modeset_init(priv->dp[i], dev, encoder, yuv_supported);
 		if (rc) {
 			DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc);
 			return rc;
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index ebcc76ef1d590..9b9f5f2921903 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1471,7 +1471,7 @@ static int dp_display_get_next_bridge(struct msm_dp *dp)
 }
 
 int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
-			struct drm_encoder *encoder)
+			struct drm_encoder *encoder, bool yuv_supported)
 {
 	struct dp_display_private *dp_priv;
 	int ret;
@@ -1487,7 +1487,7 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
 		return ret;
 	}
 
-	dp_display->connector = dp_drm_connector_init(dp_display, encoder);
+	dp_display->connector = dp_drm_connector_init(dp_display, encoder, yuv_supported);
 	if (IS_ERR(dp_display->connector)) {
 		ret = PTR_ERR(dp_display->connector);
 		DRM_DEV_ERROR(dev->dev,
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index 46e6889037e88..a819a4ff76a9f 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -353,7 +353,8 @@ int dp_bridge_init(struct msm_dp *dp_display, struct drm_device *dev,
 }
 
 /* connector initialization */
-struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display, struct drm_encoder *encoder)
+struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display, struct drm_encoder *encoder,
+					    bool yuv_supported)
 {
 	struct drm_connector *connector = NULL;
 
@@ -364,6 +365,9 @@ struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display, struct dr
 	if (!dp_display->is_edp)
 		drm_connector_attach_dp_subconnector_property(connector);
 
+	if (yuv_supported)
+		connector->ycbcr_420_allowed = true;
+
 	drm_connector_attach_encoder(connector, encoder);
 
 	return connector;
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.h b/drivers/gpu/drm/msm/dp/dp_drm.h
index b3d684db2383b..45e57ac25a4d9 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.h
+++ b/drivers/gpu/drm/msm/dp/dp_drm.h
@@ -19,7 +19,8 @@ struct msm_dp_bridge {
 
 #define to_dp_bridge(x)     container_of((x), struct msm_dp_bridge, bridge)
 
-struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display, struct drm_encoder *encoder);
+struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display, struct drm_encoder *encoder,
+					    bool yuv_supported);
 int dp_bridge_init(struct msm_dp *dp_display, struct drm_device *dev,
 			struct drm_encoder *encoder);
 
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index b876ebd48effe..37335777f5c09 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -385,7 +385,7 @@ static inline struct drm_dsc_config *msm_dsi_get_dsc_config(struct msm_dsi *msm_
 int __init msm_dp_register(void);
 void __exit msm_dp_unregister(void);
 int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
-			 struct drm_encoder *encoder);
+			 struct drm_encoder *encoder, bool yuv_supported);
 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);
@@ -403,7 +403,8 @@ static inline void __exit msm_dp_unregister(void)
 }
 static inline int msm_dp_modeset_init(struct msm_dp *dp_display,
 				       struct drm_device *dev,
-				       struct drm_encoder *encoder)
+				       struct drm_encoder *encoder,
+				       bool yuv_supported)
 {
 	return -EINVAL;
 }
-- 
2.39.2


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

* Re: [PATCH v3 13/19] drm/msm/dp: add VSC SDP support for YUV420 over DP
  2024-02-14 18:03 ` [PATCH v3 13/19] drm/msm/dp: add VSC SDP support for YUV420 over DP Paloma Arellano
@ 2024-02-14 19:39   ` Dmitry Baryshkov
  2024-02-14 20:15     ` Abhinav Kumar
  0 siblings, 1 reply; 33+ messages in thread
From: Dmitry Baryshkov @ 2024-02-14 19:39 UTC (permalink / raw)
  To: Paloma Arellano
  Cc: freedreno, linux-arm-msm, dri-devel, robdclark, seanpaul, swboyd,
	quic_abhinavk, quic_jesszhan, quic_khsieh, marijn.suijten,
	neil.armstrong

On Wed, 14 Feb 2024 at 20:04, Paloma Arellano <quic_parellan@quicinc.com> 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.
>
> Changes in v3:
>         - Create a new struct, msm_dp_sdp_with_parity, which holds the
>           packing information for VSC SDP
>         - Use drm_dp_vsc_sdp_pack() to pack the data into the new
>           msm_dp_sdp_with_parity struct instead of specifically packing
>           for YUV420 format
>         - Modify dp_catalog_panel_send_vsc_sdp() to send the VSC SDP
>           data using the new msm_dp_sdp_with_parity struct
>
> Changes in v2:
>         - Rename GENERIC0_SDPSIZE macro to GENERIC0_SDPSIZE_VALID
>         - Remove dp_sdp from the dp_catalog struct since this data is
>           being allocated at the point used
>         - Create a new function in dp_utils to pack the VSC SDP data
>           into a buffer
>         - Create a new function that packs the SDP header bytes into a
>           buffer. This function is made generic so that it can be
>           utilized by dp_audio
>           header bytes into a buffer
>         - Create a new function in dp_utils that takes the packed buffer
>           and writes to the DP_GENERIC0_* registers
>         - Split the dp_catalog_panel_config_vsc_sdp() function into two
>           to disable/enable sending VSC SDP packets
>         - Check the DP HW version using the original useage of
>           dp_catalog_hw_revision() and correct the version checking
>           logic
>         - Rename dp_panel_setup_vsc_sdp() to
>           dp_panel_setup_vsc_sdp_yuv_420() to explicitly state that
>           currently VSC SDP is only being set up to support YUV420 modes
>
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>  drivers/gpu/drm/msm/dp/dp_catalog.c | 113 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/msm/dp/dp_catalog.h |   7 ++
>  drivers/gpu/drm/msm/dp/dp_ctrl.c    |   4 +
>  drivers/gpu/drm/msm/dp/dp_panel.c   |  55 ++++++++++++++
>  drivers/gpu/drm/msm/dp/dp_reg.h     |   3 +
>  drivers/gpu/drm/msm/dp/dp_utils.c   |  48 ++++++++++++
>  drivers/gpu/drm/msm/dp/dp_utils.h   |  18 +++++
>  7 files changed, 248 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
> index 5d84c089e520a..61d5317efe683 100644
> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
> @@ -901,6 +901,119 @@ int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog)
>         return 0;
>  }
>
> +static void dp_catalog_panel_send_vsc_sdp(struct dp_catalog *dp_catalog,
> +                                         struct msm_dp_sdp_with_parity *msm_dp_sdp)
> +{
> +       struct dp_catalog_private *catalog;
> +       u32 val;
> +
> +       if (!dp_catalog) {
> +               DRM_ERROR("invalid input\n");
> +               return;
> +       }
> +
> +       catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
> +
> +       val = ((msm_dp_sdp->vsc_sdp.sdp_header.HB0) << HEADER_BYTE_0_BIT |
> +              (msm_dp_sdp->pb.PB0 << PARITY_BYTE_0_BIT) |
> +              (msm_dp_sdp->vsc_sdp.sdp_header.HB1) << HEADER_BYTE_1_BIT |
> +              (msm_dp_sdp->pb.PB1 << PARITY_BYTE_1_BIT));
> +       dp_write_link(catalog, MMSS_DP_GENERIC0_0, val);
> +
> +       val = ((msm_dp_sdp->vsc_sdp.sdp_header.HB2) << HEADER_BYTE_2_BIT |
> +              (msm_dp_sdp->pb.PB2 << PARITY_BYTE_2_BIT) |
> +              (msm_dp_sdp->vsc_sdp.sdp_header.HB3) << HEADER_BYTE_3_BIT |
> +              (msm_dp_sdp->pb.PB3 << PARITY_BYTE_3_BIT));
> +       dp_write_link(catalog, MMSS_DP_GENERIC0_1, val);

I still think that this is not the way to do it. Could you please
extract the function that takes struct dp_sdp_header, calculates
padding and writes resulting data to the hardware? This way we can
reuse it later for all the dp_audio stuff.

> +
> +       val = ((msm_dp_sdp->vsc_sdp.db[16]) | (msm_dp_sdp->vsc_sdp.db[17] << 8) |
> +              (msm_dp_sdp->vsc_sdp.db[18] << 16));
> +       dp_write_link(catalog, MMSS_DP_GENERIC0_6, val);

Shouldn't we write full dp_sdp data, including all zeroes? Here you
assume that there is no other data in dp_sdp and also that nobody
wrote anything senseless to those registers.

> +}
> +
> +static void dp_catalog_panel_update_sdp(struct dp_catalog *dp_catalog)
> +{
> +       struct dp_catalog_private *catalog;
> +       u32 hw_revision;
> +
> +       catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
> +
> +       hw_revision = dp_catalog_hw_revision(dp_catalog);
> +       if (hw_revision < DP_HW_VERSION_1_2 && hw_revision >= DP_HW_VERSION_1_0) {
> +               dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x01);
> +               dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x00);
> +       }
> +}
> +
> +void dp_catalog_panel_enable_vsc_sdp(struct dp_catalog *dp_catalog,
> +                                    struct msm_dp_sdp_with_parity *msm_dp_sdp)
> +{
> +       struct dp_catalog_private *catalog;
> +       u32 cfg, cfg2, misc;
> +
> +       if (!dp_catalog) {
> +               DRM_ERROR("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);
> +
> +       cfg |= GEN0_SDP_EN;
> +       dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
> +
> +       cfg2 |= GENERIC0_SDPSIZE_VALID;
> +       dp_write_link(catalog, MMSS_DP_SDP_CFG2, cfg2);
> +
> +       dp_catalog_panel_send_vsc_sdp(dp_catalog, msm_dp_sdp);
> +
> +       /* indicates presence of VSC (BIT(6) of MISC1) */
> +       misc |= DP_MISC1_VSC_SDP;
> +
> +       drm_dbg_dp(catalog->drm_dev, "vsc sdp enable=1\n");
> +
> +       pr_debug("misc settings = 0x%x\n", misc);
> +       dp_write_link(catalog, REG_DP_MISC1_MISC0, misc);
> +
> +       dp_catalog_panel_update_sdp(dp_catalog);
> +}
> +
> +void dp_catalog_panel_disable_vsc_sdp(struct dp_catalog *dp_catalog)
> +{
> +       struct dp_catalog_private *catalog;
> +       u32 cfg, cfg2, misc;
> +
> +       if (!dp_catalog) {
> +               DRM_ERROR("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);
> +
> +       cfg &= ~GEN0_SDP_EN;
> +       dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
> +
> +       cfg2 &= ~GENERIC0_SDPSIZE_VALID;
> +       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=0\n");
> +
> +       pr_debug("misc settings = 0x%x\n", misc);
> +       dp_write_link(catalog, REG_DP_MISC1_MISC0, misc);
> +
> +       dp_catalog_panel_update_sdp(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_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
> index 6cb5e2a243de2..4bf08c27a9bf3 100644
> --- a/drivers/gpu/drm/msm/dp/dp_catalog.h
> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
> @@ -9,6 +9,7 @@
>  #include <drm/drm_modes.h>
>
>  #include "dp_parser.h"
> +#include "dp_utils.h"
>  #include "disp/msm_disp_snapshot.h"
>
>  /* interrupts */
> @@ -30,6 +31,9 @@
>
>  #define DP_AUX_CFG_MAX_VALUE_CNT 3
>
> +#define DP_HW_VERSION_1_0      0x10000000
> +#define DP_HW_VERSION_1_2      0x10020000
> +
>  /* PHY AUX config registers */
>  enum dp_phy_aux_config_type {
>         PHY_AUX_CFG0,
> @@ -124,6 +128,9 @@ 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_enable_vsc_sdp(struct dp_catalog *dp_catalog,
> +                                    struct msm_dp_sdp_with_parity *msm_dp_sdp);
> +void dp_catalog_panel_disable_vsc_sdp(struct dp_catalog *dp_catalog);
>  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..beef86b1aaf81 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_disable_vsc_sdp(ctrl->catalog);
> +
>         /* 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_disable_vsc_sdp(ctrl->catalog);
> +
>         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 db1942794f1a4..18420a7ba4ab3 100644
> --- a/drivers/gpu/drm/msm/dp/dp_panel.c
> +++ b/drivers/gpu/drm/msm/dp/dp_panel.c
> @@ -4,6 +4,7 @@
>   */
>
>  #include "dp_panel.h"
> +#include "dp_utils.h"
>
>  #include <drm/drm_connector.h>
>  #include <drm/drm_edid.h>
> @@ -281,6 +282,56 @@ 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);
>  }
>
> +static int dp_panel_setup_vsc_sdp_yuv_420(struct dp_panel *dp_panel)
> +{
> +       struct dp_catalog *catalog;
> +       struct dp_panel_private *panel;
> +       struct dp_display_mode *dp_mode;
> +       struct drm_dp_vsc_sdp vsc_sdp_data;
> +       struct msm_dp_sdp_with_parity msm_dp_sdp;
> +       ssize_t len;
> +       int rc = 0;
> +
> +       if (!dp_panel) {
> +               DRM_ERROR("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(&vsc_sdp_data, 0, sizeof(vsc_sdp_data));
> +
> +       /* VSC SDP header as per table 2-118 of DP 1.4 specification */
> +       vsc_sdp_data.sdp_type = DP_SDP_VSC;
> +       vsc_sdp_data.revision = 0x05;
> +       vsc_sdp_data.length = 0x13;
> +
> +       /* VSC SDP Payload for DB16 */
> +       vsc_sdp_data.pixelformat = DP_PIXELFORMAT_YUV420;
> +       vsc_sdp_data.colorimetry = DP_COLORIMETRY_DEFAULT;
> +
> +       /* VSC SDP Payload for DB17 */
> +       vsc_sdp_data.bpc = dp_mode->bpp / 3;
> +       vsc_sdp_data.dynamic_range = DP_DYNAMIC_RANGE_CTA;
> +
> +       /* VSC SDP Payload for DB18 */
> +       vsc_sdp_data.content_type = DP_CONTENT_TYPE_GRAPHICS;
> +
> +       // rc = dp_utils_pack_vsc_sdp(&vsc_sdp_data, &sdp_header, gen_buffer, buff_size);
> +       len = dp_utils_pack_vsc_sdp(&vsc_sdp_data, &msm_dp_sdp);
> +       if (len < 0) {
> +               DRM_ERROR("unable to pack vsc sdp\n");
> +               return len;
> +       }
> +
> +       dp_catalog_panel_enable_vsc_sdp(catalog, &msm_dp_sdp);
> +
> +       return rc;
> +}
> +
>  void dp_panel_dump_regs(struct dp_panel *dp_panel)
>  {
>         struct dp_catalog *catalog;
> @@ -344,6 +395,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_yuv_420(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..2983756c125cd 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_VALID                 (0x00010000)
>
>  #define MMSS_DP_AUDIO_STREAM_0                 (0x00000240)
>  #define MMSS_DP_AUDIO_STREAM_1                 (0x00000244)
> diff --git a/drivers/gpu/drm/msm/dp/dp_utils.c b/drivers/gpu/drm/msm/dp/dp_utils.c
> index 3a44fe738c004..81601f3c414fc 100644
> --- a/drivers/gpu/drm/msm/dp/dp_utils.c
> +++ b/drivers/gpu/drm/msm/dp/dp_utils.c
> @@ -4,6 +4,7 @@
>   */
>
>  #include <linux/types.h>
> +#include <drm/drm_print.h>
>
>  #include "dp_utils.h"
>
> @@ -71,3 +72,50 @@ u8 dp_utils_calculate_parity(u32 data)
>
>         return parity_byte;
>  }
> +
> +ssize_t dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, struct msm_dp_vsc_sdp_parity *pb,
> +                                size_t size)
> +{
> +       u8 header;
> +
> +       size_t length = sizeof(struct msm_dp_vsc_sdp_parity);
> +
> +       if (size < length)
> +               return -ENOSPC;
> +
> +       memset(pb, 0, size);
> +
> +       header = sdp_header->HB0;
> +       pb->PB0 = dp_utils_calculate_parity(header);
> +
> +       header = sdp_header->HB1;
> +       pb->PB1 = dp_utils_calculate_parity(header);
> +
> +       header = sdp_header->HB2;
> +       pb->PB2 = dp_utils_calculate_parity(header);
> +
> +       header = sdp_header->HB3;
> +       pb->PB3 = dp_utils_calculate_parity(header);
> +
> +       return length;
> +}
> +
> +ssize_t dp_utils_pack_vsc_sdp(struct drm_dp_vsc_sdp *vsc, struct msm_dp_sdp_with_parity *msm_dp_sdp)
> +{
> +       ssize_t len;
> +
> +       len = drm_dp_vsc_sdp_pack(vsc, &msm_dp_sdp->vsc_sdp, sizeof(msm_dp_sdp->vsc_sdp));
> +       if (len < 0) {
> +               DRM_ERROR("unable to pack vsc sdp\n");
> +               return len;
> +       }
> +
> +       len = dp_utils_pack_sdp_header(&msm_dp_sdp->vsc_sdp.sdp_header, &msm_dp_sdp->pb,
> +                                      sizeof(msm_dp_sdp->pb));
> +       if (len < 0) {
> +               DRM_ERROR("unable to pack sdp header\n");
> +               return len;
> +       }
> +
> +       return len;
> +}
> diff --git a/drivers/gpu/drm/msm/dp/dp_utils.h b/drivers/gpu/drm/msm/dp/dp_utils.h
> index 5a505cbf3432b..6946bc51cae97 100644
> --- a/drivers/gpu/drm/msm/dp/dp_utils.h
> +++ b/drivers/gpu/drm/msm/dp/dp_utils.h
> @@ -6,6 +6,8 @@
>  #ifndef _DP_UTILS_H_
>  #define _DP_UTILS_H_
>
> +#include <drm/display/drm_dp_helper.h>
> +
>  #define HEADER_BYTE_0_BIT       0
>  #define PARITY_BYTE_0_BIT       8
>  #define HEADER_BYTE_1_BIT      16
> @@ -15,8 +17,24 @@
>  #define HEADER_BYTE_3_BIT      16
>  #define PARITY_BYTE_3_BIT      24
>
> +struct msm_dp_vsc_sdp_parity {
> +       u8 PB0;
> +       u8 PB1;
> +       u8 PB2;
> +       u8 PB3;
> +} __packed;
> +
> +struct msm_dp_sdp_with_parity {
> +       struct dp_sdp vsc_sdp;
> +       struct msm_dp_vsc_sdp_parity pb;
> +};
> +
>  u8 dp_utils_get_g0_value(u8 data);
>  u8 dp_utils_get_g1_value(u8 data);
>  u8 dp_utils_calculate_parity(u32 data);
> +ssize_t dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, struct msm_dp_vsc_sdp_parity *pb,
> +                                size_t size);
> +ssize_t dp_utils_pack_vsc_sdp(struct drm_dp_vsc_sdp *vsc,
> +                             struct msm_dp_sdp_with_parity *msm_dp_sdp);
>
>  #endif /* _DP_UTILS_H_ */
> --
> 2.39.2
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH v3 15/19] drm/msm/dp: enable SDP and SDE periph flush update
  2024-02-14 18:03 ` [PATCH v3 15/19] drm/msm/dp: enable SDP and SDE periph flush update Paloma Arellano
@ 2024-02-14 19:41   ` Dmitry Baryshkov
  0 siblings, 0 replies; 33+ messages in thread
From: Dmitry Baryshkov @ 2024-02-14 19:41 UTC (permalink / raw)
  To: Paloma Arellano
  Cc: freedreno, linux-arm-msm, dri-devel, robdclark, seanpaul, swboyd,
	quic_abhinavk, quic_jesszhan, quic_khsieh, marijn.suijten,
	neil.armstrong

On Wed, 14 Feb 2024 at 20:04, Paloma Arellano <quic_parellan@quicinc.com> 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
>
> Changes in v3:
>         - Clear up that the DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE
>           macro is setting bits [24:23] to a value of 3
>
> Changes in v2:
>         - Use the original dp_catalog_hw_revision() function to
>           correctly check the DP HW version
>
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>  drivers/gpu/drm/msm/dp/dp_catalog.c | 17 +++++++++++++++++
>  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     |  5 +++++
>  4 files changed, 24 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
> index 61d5317efe683..823eeba7e71d3 100644
> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
> @@ -440,6 +440,23 @@ 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, hw_revision;
> +       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);
> +
> +       hw_revision = dp_catalog_hw_revision(dp_catalog);
> +       if (hw_revision >= DP_HW_VERSION_1_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 4bf08c27a9bf3..eb05a37837beb 100644
> --- a/drivers/gpu/drm/msm/dp/dp_catalog.h
> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
> @@ -98,6 +98,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 beef86b1aaf81..f1e7b0a5ee5d1 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 2983756c125cd..d4fb8572cd1e4 100644
> --- a/drivers/gpu/drm/msm/dp/dp_reg.h
> +++ b/drivers/gpu/drm/msm/dp/dp_reg.h
> @@ -6,6 +6,9 @@
>  #ifndef _DP_REG_H_
>  #define _DP_REG_H_
>
> +#include <linux/bitfield.h>
> +#include <linux/bits.h>
> +
>  /* DP_TX Registers */
>  #define REG_DP_HW_VERSION                      (0x00000000)
>
> @@ -102,6 +105,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)

This define covers data from the same bit field. Please use FIELD_PREP too.

> +#define DP_MAINLINK_FLUSH_MODE_SDE_PERIPH_UPDATE       FIELD_PREP(GENMASK(24, 23), 3)

#define DP_foo_MASK GENMASK(24,23)

>  #define DP_MAINLINK_FB_BOUNDARY_SEL            (0x02000000)
>
>  #define REG_DP_STATE_CTRL                      (0x00000004)
> --
> 2.39.2
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH v3 13/19] drm/msm/dp: add VSC SDP support for YUV420 over DP
  2024-02-14 19:39   ` Dmitry Baryshkov
@ 2024-02-14 20:15     ` Abhinav Kumar
  2024-02-15  8:40       ` Dmitry Baryshkov
  0 siblings, 1 reply; 33+ messages in thread
From: Abhinav Kumar @ 2024-02-14 20:15 UTC (permalink / raw)
  To: Dmitry Baryshkov, Paloma Arellano
  Cc: freedreno, linux-arm-msm, dri-devel, robdclark, seanpaul, swboyd,
	quic_jesszhan, quic_khsieh, marijn.suijten, neil.armstrong



On 2/14/2024 11:39 AM, Dmitry Baryshkov wrote:
> On Wed, 14 Feb 2024 at 20:04, Paloma Arellano <quic_parellan@quicinc.com> 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.
>>
>> Changes in v3:
>>          - Create a new struct, msm_dp_sdp_with_parity, which holds the
>>            packing information for VSC SDP
>>          - Use drm_dp_vsc_sdp_pack() to pack the data into the new
>>            msm_dp_sdp_with_parity struct instead of specifically packing
>>            for YUV420 format
>>          - Modify dp_catalog_panel_send_vsc_sdp() to send the VSC SDP
>>            data using the new msm_dp_sdp_with_parity struct
>>
>> Changes in v2:
>>          - Rename GENERIC0_SDPSIZE macro to GENERIC0_SDPSIZE_VALID
>>          - Remove dp_sdp from the dp_catalog struct since this data is
>>            being allocated at the point used
>>          - Create a new function in dp_utils to pack the VSC SDP data
>>            into a buffer
>>          - Create a new function that packs the SDP header bytes into a
>>            buffer. This function is made generic so that it can be
>>            utilized by dp_audio
>>            header bytes into a buffer
>>          - Create a new function in dp_utils that takes the packed buffer
>>            and writes to the DP_GENERIC0_* registers
>>          - Split the dp_catalog_panel_config_vsc_sdp() function into two
>>            to disable/enable sending VSC SDP packets
>>          - Check the DP HW version using the original useage of
>>            dp_catalog_hw_revision() and correct the version checking
>>            logic
>>          - Rename dp_panel_setup_vsc_sdp() to
>>            dp_panel_setup_vsc_sdp_yuv_420() to explicitly state that
>>            currently VSC SDP is only being set up to support YUV420 modes
>>
>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/dp/dp_catalog.c | 113 ++++++++++++++++++++++++++++
>>   drivers/gpu/drm/msm/dp/dp_catalog.h |   7 ++
>>   drivers/gpu/drm/msm/dp/dp_ctrl.c    |   4 +
>>   drivers/gpu/drm/msm/dp/dp_panel.c   |  55 ++++++++++++++
>>   drivers/gpu/drm/msm/dp/dp_reg.h     |   3 +
>>   drivers/gpu/drm/msm/dp/dp_utils.c   |  48 ++++++++++++
>>   drivers/gpu/drm/msm/dp/dp_utils.h   |  18 +++++
>>   7 files changed, 248 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
>> index 5d84c089e520a..61d5317efe683 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
>> @@ -901,6 +901,119 @@ int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog)
>>          return 0;
>>   }
>>
>> +static void dp_catalog_panel_send_vsc_sdp(struct dp_catalog *dp_catalog,
>> +                                         struct msm_dp_sdp_with_parity *msm_dp_sdp)
>> +{
>> +       struct dp_catalog_private *catalog;
>> +       u32 val;
>> +
>> +       if (!dp_catalog) {
>> +               DRM_ERROR("invalid input\n");
>> +               return;
>> +       }
>> +
>> +       catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
>> +
>> +       val = ((msm_dp_sdp->vsc_sdp.sdp_header.HB0) << HEADER_BYTE_0_BIT |
>> +              (msm_dp_sdp->pb.PB0 << PARITY_BYTE_0_BIT) |
>> +              (msm_dp_sdp->vsc_sdp.sdp_header.HB1) << HEADER_BYTE_1_BIT |
>> +              (msm_dp_sdp->pb.PB1 << PARITY_BYTE_1_BIT));
>> +       dp_write_link(catalog, MMSS_DP_GENERIC0_0, val);
>> +
>> +       val = ((msm_dp_sdp->vsc_sdp.sdp_header.HB2) << HEADER_BYTE_2_BIT |
>> +              (msm_dp_sdp->pb.PB2 << PARITY_BYTE_2_BIT) |
>> +              (msm_dp_sdp->vsc_sdp.sdp_header.HB3) << HEADER_BYTE_3_BIT |
>> +              (msm_dp_sdp->pb.PB3 << PARITY_BYTE_3_BIT));
>> +       dp_write_link(catalog, MMSS_DP_GENERIC0_1, val);
> 
> I still think that this is not the way to do it. Could you please
> extract the function that takes struct dp_sdp_header, calculates
> padding and writes resulting data to the hardware? This way we can
> reuse it later for all the dp_audio stuff.
> 

hmmm ... dp_utils_pack_sdp_header() does that you are asking for right?

OR are you asking for another function like:

1) rename dp_utils_pack_sdp_header() to dp_utils_calc_sdp_parity()
2) dp_utils_pack_sdp() takes two u32 to pack the header and parity 
together and we move the << HEADER_BYTE_xx | part to it

dp_catalog_panel_send_vsc_sdp() just uses these two u32 to write the 
headers.


>> +
>> +       val = ((msm_dp_sdp->vsc_sdp.db[16]) | (msm_dp_sdp->vsc_sdp.db[17] << 8) |
>> +              (msm_dp_sdp->vsc_sdp.db[18] << 16));
>> +       dp_write_link(catalog, MMSS_DP_GENERIC0_6, val);
> 
> Shouldn't we write full dp_sdp data, including all zeroes? Here you
> assume that there is no other data in dp_sdp and also that nobody
> wrote anything senseless to those registers.
> 

As per documentation, it says db[0] to db[15] are reserved so I thought 
its better not to touch/use them and start writing for 16 onwards.

1592  * VSC SDP Payload for Pixel Encoding/Colorimetry Format
1593  * db[0] - db[15]: Reserved
1594  * db[16]: Pixel Encoding and Colorimetry Formats
1595  * db[17]: Dynamic Range and Component Bit Depth
1596  * db[18]: Content Type
1597  * db[19] - db[31]: Reserved
1598  */

>> +}
>> +
>> +static void dp_catalog_panel_update_sdp(struct dp_catalog *dp_catalog)
>> +{
>> +       struct dp_catalog_private *catalog;
>> +       u32 hw_revision;
>> +
>> +       catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
>> +
>> +       hw_revision = dp_catalog_hw_revision(dp_catalog);
>> +       if (hw_revision < DP_HW_VERSION_1_2 && hw_revision >= DP_HW_VERSION_1_0) {
>> +               dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x01);
>> +               dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x00);
>> +       }
>> +}
>> +
>> +void dp_catalog_panel_enable_vsc_sdp(struct dp_catalog *dp_catalog,
>> +                                    struct msm_dp_sdp_with_parity *msm_dp_sdp)
>> +{
>> +       struct dp_catalog_private *catalog;
>> +       u32 cfg, cfg2, misc;
>> +
>> +       if (!dp_catalog) {
>> +               DRM_ERROR("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);
>> +
>> +       cfg |= GEN0_SDP_EN;
>> +       dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
>> +
>> +       cfg2 |= GENERIC0_SDPSIZE_VALID;
>> +       dp_write_link(catalog, MMSS_DP_SDP_CFG2, cfg2);
>> +
>> +       dp_catalog_panel_send_vsc_sdp(dp_catalog, msm_dp_sdp);
>> +
>> +       /* indicates presence of VSC (BIT(6) of MISC1) */
>> +       misc |= DP_MISC1_VSC_SDP;
>> +
>> +       drm_dbg_dp(catalog->drm_dev, "vsc sdp enable=1\n");
>> +
>> +       pr_debug("misc settings = 0x%x\n", misc);
>> +       dp_write_link(catalog, REG_DP_MISC1_MISC0, misc);
>> +
>> +       dp_catalog_panel_update_sdp(dp_catalog);
>> +}
>> +
>> +void dp_catalog_panel_disable_vsc_sdp(struct dp_catalog *dp_catalog)
>> +{
>> +       struct dp_catalog_private *catalog;
>> +       u32 cfg, cfg2, misc;
>> +
>> +       if (!dp_catalog) {
>> +               DRM_ERROR("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);
>> +
>> +       cfg &= ~GEN0_SDP_EN;
>> +       dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
>> +
>> +       cfg2 &= ~GENERIC0_SDPSIZE_VALID;
>> +       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=0\n");
>> +
>> +       pr_debug("misc settings = 0x%x\n", misc);
>> +       dp_write_link(catalog, REG_DP_MISC1_MISC0, misc);
>> +
>> +       dp_catalog_panel_update_sdp(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_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
>> index 6cb5e2a243de2..4bf08c27a9bf3 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.h
>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
>> @@ -9,6 +9,7 @@
>>   #include <drm/drm_modes.h>
>>
>>   #include "dp_parser.h"
>> +#include "dp_utils.h"
>>   #include "disp/msm_disp_snapshot.h"
>>
>>   /* interrupts */
>> @@ -30,6 +31,9 @@
>>
>>   #define DP_AUX_CFG_MAX_VALUE_CNT 3
>>
>> +#define DP_HW_VERSION_1_0      0x10000000
>> +#define DP_HW_VERSION_1_2      0x10020000
>> +
>>   /* PHY AUX config registers */
>>   enum dp_phy_aux_config_type {
>>          PHY_AUX_CFG0,
>> @@ -124,6 +128,9 @@ 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_enable_vsc_sdp(struct dp_catalog *dp_catalog,
>> +                                    struct msm_dp_sdp_with_parity *msm_dp_sdp);
>> +void dp_catalog_panel_disable_vsc_sdp(struct dp_catalog *dp_catalog);
>>   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..beef86b1aaf81 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_disable_vsc_sdp(ctrl->catalog);
>> +
>>          /* 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_disable_vsc_sdp(ctrl->catalog);
>> +
>>          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 db1942794f1a4..18420a7ba4ab3 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_panel.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_panel.c
>> @@ -4,6 +4,7 @@
>>    */
>>
>>   #include "dp_panel.h"
>> +#include "dp_utils.h"
>>
>>   #include <drm/drm_connector.h>
>>   #include <drm/drm_edid.h>
>> @@ -281,6 +282,56 @@ 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);
>>   }
>>
>> +static int dp_panel_setup_vsc_sdp_yuv_420(struct dp_panel *dp_panel)
>> +{
>> +       struct dp_catalog *catalog;
>> +       struct dp_panel_private *panel;
>> +       struct dp_display_mode *dp_mode;
>> +       struct drm_dp_vsc_sdp vsc_sdp_data;
>> +       struct msm_dp_sdp_with_parity msm_dp_sdp;
>> +       ssize_t len;
>> +       int rc = 0;
>> +
>> +       if (!dp_panel) {
>> +               DRM_ERROR("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(&vsc_sdp_data, 0, sizeof(vsc_sdp_data));
>> +
>> +       /* VSC SDP header as per table 2-118 of DP 1.4 specification */
>> +       vsc_sdp_data.sdp_type = DP_SDP_VSC;
>> +       vsc_sdp_data.revision = 0x05;
>> +       vsc_sdp_data.length = 0x13;
>> +
>> +       /* VSC SDP Payload for DB16 */
>> +       vsc_sdp_data.pixelformat = DP_PIXELFORMAT_YUV420;
>> +       vsc_sdp_data.colorimetry = DP_COLORIMETRY_DEFAULT;
>> +
>> +       /* VSC SDP Payload for DB17 */
>> +       vsc_sdp_data.bpc = dp_mode->bpp / 3;
>> +       vsc_sdp_data.dynamic_range = DP_DYNAMIC_RANGE_CTA;
>> +
>> +       /* VSC SDP Payload for DB18 */
>> +       vsc_sdp_data.content_type = DP_CONTENT_TYPE_GRAPHICS;
>> +
>> +       // rc = dp_utils_pack_vsc_sdp(&vsc_sdp_data, &sdp_header, gen_buffer, buff_size);
>> +       len = dp_utils_pack_vsc_sdp(&vsc_sdp_data, &msm_dp_sdp);
>> +       if (len < 0) {
>> +               DRM_ERROR("unable to pack vsc sdp\n");
>> +               return len;
>> +       }
>> +
>> +       dp_catalog_panel_enable_vsc_sdp(catalog, &msm_dp_sdp);
>> +
>> +       return rc;
>> +}
>> +
>>   void dp_panel_dump_regs(struct dp_panel *dp_panel)
>>   {
>>          struct dp_catalog *catalog;
>> @@ -344,6 +395,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_yuv_420(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..2983756c125cd 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_VALID                 (0x00010000)
>>
>>   #define MMSS_DP_AUDIO_STREAM_0                 (0x00000240)
>>   #define MMSS_DP_AUDIO_STREAM_1                 (0x00000244)
>> diff --git a/drivers/gpu/drm/msm/dp/dp_utils.c b/drivers/gpu/drm/msm/dp/dp_utils.c
>> index 3a44fe738c004..81601f3c414fc 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_utils.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_utils.c
>> @@ -4,6 +4,7 @@
>>    */
>>
>>   #include <linux/types.h>
>> +#include <drm/drm_print.h>
>>
>>   #include "dp_utils.h"
>>
>> @@ -71,3 +72,50 @@ u8 dp_utils_calculate_parity(u32 data)
>>
>>          return parity_byte;
>>   }
>> +
>> +ssize_t dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, struct msm_dp_vsc_sdp_parity *pb,
>> +                                size_t size)
>> +{
>> +       u8 header;
>> +
>> +       size_t length = sizeof(struct msm_dp_vsc_sdp_parity);
>> +
>> +       if (size < length)
>> +               return -ENOSPC;
>> +
>> +       memset(pb, 0, size);
>> +
>> +       header = sdp_header->HB0;
>> +       pb->PB0 = dp_utils_calculate_parity(header);
>> +
>> +       header = sdp_header->HB1;
>> +       pb->PB1 = dp_utils_calculate_parity(header);
>> +
>> +       header = sdp_header->HB2;
>> +       pb->PB2 = dp_utils_calculate_parity(header);
>> +
>> +       header = sdp_header->HB3;
>> +       pb->PB3 = dp_utils_calculate_parity(header);
>> +
>> +       return length;
>> +}
>> +
>> +ssize_t dp_utils_pack_vsc_sdp(struct drm_dp_vsc_sdp *vsc, struct msm_dp_sdp_with_parity *msm_dp_sdp)
>> +{
>> +       ssize_t len;
>> +
>> +       len = drm_dp_vsc_sdp_pack(vsc, &msm_dp_sdp->vsc_sdp, sizeof(msm_dp_sdp->vsc_sdp));
>> +       if (len < 0) {
>> +               DRM_ERROR("unable to pack vsc sdp\n");
>> +               return len;
>> +       }
>> +
>> +       len = dp_utils_pack_sdp_header(&msm_dp_sdp->vsc_sdp.sdp_header, &msm_dp_sdp->pb,
>> +                                      sizeof(msm_dp_sdp->pb));
>> +       if (len < 0) {
>> +               DRM_ERROR("unable to pack sdp header\n");
>> +               return len;
>> +       }
>> +
>> +       return len;
>> +}
>> diff --git a/drivers/gpu/drm/msm/dp/dp_utils.h b/drivers/gpu/drm/msm/dp/dp_utils.h
>> index 5a505cbf3432b..6946bc51cae97 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_utils.h
>> +++ b/drivers/gpu/drm/msm/dp/dp_utils.h
>> @@ -6,6 +6,8 @@
>>   #ifndef _DP_UTILS_H_
>>   #define _DP_UTILS_H_
>>
>> +#include <drm/display/drm_dp_helper.h>
>> +
>>   #define HEADER_BYTE_0_BIT       0
>>   #define PARITY_BYTE_0_BIT       8
>>   #define HEADER_BYTE_1_BIT      16
>> @@ -15,8 +17,24 @@
>>   #define HEADER_BYTE_3_BIT      16
>>   #define PARITY_BYTE_3_BIT      24
>>
>> +struct msm_dp_vsc_sdp_parity {
>> +       u8 PB0;
>> +       u8 PB1;
>> +       u8 PB2;
>> +       u8 PB3;
>> +} __packed;
>> +
>> +struct msm_dp_sdp_with_parity {
>> +       struct dp_sdp vsc_sdp;
>> +       struct msm_dp_vsc_sdp_parity pb;
>> +};
>> +
>>   u8 dp_utils_get_g0_value(u8 data);
>>   u8 dp_utils_get_g1_value(u8 data);
>>   u8 dp_utils_calculate_parity(u32 data);
>> +ssize_t dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, struct msm_dp_vsc_sdp_parity *pb,
>> +                                size_t size);
>> +ssize_t dp_utils_pack_vsc_sdp(struct drm_dp_vsc_sdp *vsc,
>> +                             struct msm_dp_sdp_with_parity *msm_dp_sdp);
>>
>>   #endif /* _DP_UTILS_H_ */
>> --
>> 2.39.2
>>
> 
> 

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

* Re: [PATCH v3 13/19] drm/msm/dp: add VSC SDP support for YUV420 over DP
  2024-02-14 20:15     ` Abhinav Kumar
@ 2024-02-15  8:40       ` Dmitry Baryshkov
  2024-02-15 16:39         ` Abhinav Kumar
  0 siblings, 1 reply; 33+ messages in thread
From: Dmitry Baryshkov @ 2024-02-15  8:40 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: Paloma Arellano, freedreno, linux-arm-msm, dri-devel, robdclark,
	seanpaul, swboyd, quic_jesszhan, quic_khsieh, marijn.suijten,
	neil.armstrong

On Wed, 14 Feb 2024 at 22:15, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 2/14/2024 11:39 AM, Dmitry Baryshkov wrote:
> > On Wed, 14 Feb 2024 at 20:04, Paloma Arellano <quic_parellan@quicinc.com> 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.
> >>
> >> Changes in v3:
> >>          - Create a new struct, msm_dp_sdp_with_parity, which holds the
> >>            packing information for VSC SDP
> >>          - Use drm_dp_vsc_sdp_pack() to pack the data into the new
> >>            msm_dp_sdp_with_parity struct instead of specifically packing
> >>            for YUV420 format
> >>          - Modify dp_catalog_panel_send_vsc_sdp() to send the VSC SDP
> >>            data using the new msm_dp_sdp_with_parity struct
> >>
> >> Changes in v2:
> >>          - Rename GENERIC0_SDPSIZE macro to GENERIC0_SDPSIZE_VALID
> >>          - Remove dp_sdp from the dp_catalog struct since this data is
> >>            being allocated at the point used
> >>          - Create a new function in dp_utils to pack the VSC SDP data
> >>            into a buffer
> >>          - Create a new function that packs the SDP header bytes into a
> >>            buffer. This function is made generic so that it can be
> >>            utilized by dp_audio
> >>            header bytes into a buffer
> >>          - Create a new function in dp_utils that takes the packed buffer
> >>            and writes to the DP_GENERIC0_* registers
> >>          - Split the dp_catalog_panel_config_vsc_sdp() function into two
> >>            to disable/enable sending VSC SDP packets
> >>          - Check the DP HW version using the original useage of
> >>            dp_catalog_hw_revision() and correct the version checking
> >>            logic
> >>          - Rename dp_panel_setup_vsc_sdp() to
> >>            dp_panel_setup_vsc_sdp_yuv_420() to explicitly state that
> >>            currently VSC SDP is only being set up to support YUV420 modes
> >>
> >> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >> ---
> >>   drivers/gpu/drm/msm/dp/dp_catalog.c | 113 ++++++++++++++++++++++++++++
> >>   drivers/gpu/drm/msm/dp/dp_catalog.h |   7 ++
> >>   drivers/gpu/drm/msm/dp/dp_ctrl.c    |   4 +
> >>   drivers/gpu/drm/msm/dp/dp_panel.c   |  55 ++++++++++++++
> >>   drivers/gpu/drm/msm/dp/dp_reg.h     |   3 +
> >>   drivers/gpu/drm/msm/dp/dp_utils.c   |  48 ++++++++++++
> >>   drivers/gpu/drm/msm/dp/dp_utils.h   |  18 +++++
> >>   7 files changed, 248 insertions(+)
> >>
> >> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
> >> index 5d84c089e520a..61d5317efe683 100644
> >> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
> >> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
> >> @@ -901,6 +901,119 @@ int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog)
> >>          return 0;
> >>   }
> >>
> >> +static void dp_catalog_panel_send_vsc_sdp(struct dp_catalog *dp_catalog,
> >> +                                         struct msm_dp_sdp_with_parity *msm_dp_sdp)
> >> +{
> >> +       struct dp_catalog_private *catalog;
> >> +       u32 val;
> >> +
> >> +       if (!dp_catalog) {
> >> +               DRM_ERROR("invalid input\n");
> >> +               return;
> >> +       }
> >> +
> >> +       catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
> >> +
> >> +       val = ((msm_dp_sdp->vsc_sdp.sdp_header.HB0) << HEADER_BYTE_0_BIT |
> >> +              (msm_dp_sdp->pb.PB0 << PARITY_BYTE_0_BIT) |
> >> +              (msm_dp_sdp->vsc_sdp.sdp_header.HB1) << HEADER_BYTE_1_BIT |
> >> +              (msm_dp_sdp->pb.PB1 << PARITY_BYTE_1_BIT));
> >> +       dp_write_link(catalog, MMSS_DP_GENERIC0_0, val);
> >> +
> >> +       val = ((msm_dp_sdp->vsc_sdp.sdp_header.HB2) << HEADER_BYTE_2_BIT |
> >> +              (msm_dp_sdp->pb.PB2 << PARITY_BYTE_2_BIT) |
> >> +              (msm_dp_sdp->vsc_sdp.sdp_header.HB3) << HEADER_BYTE_3_BIT |
> >> +              (msm_dp_sdp->pb.PB3 << PARITY_BYTE_3_BIT));
> >> +       dp_write_link(catalog, MMSS_DP_GENERIC0_1, val);
> >
> > I still think that this is not the way to do it. Could you please
> > extract the function that takes struct dp_sdp_header, calculates
> > padding and writes resulting data to the hardware? This way we can
> > reuse it later for all the dp_audio stuff.
> >
>
> hmmm ... dp_utils_pack_sdp_header() does that you are asking for right?
>
> OR are you asking for another function like:
>
> 1) rename dp_utils_pack_sdp_header() to dp_utils_calc_sdp_parity()
> 2) dp_utils_pack_sdp() takes two u32 to pack the header and parity
> together and we move the << HEADER_BYTE_xx | part to it
>
> dp_catalog_panel_send_vsc_sdp() just uses these two u32 to write the
> headers.

I'm really looking for the following function:

void dp_catalog_panel_send_vsc_sdp(struct dp_catalog *dp_catalog,
struct dp_sdp *dp_sdp)
{
    dp_write_vsc_header(dp_catalog, MMSS_DP_GENERIC0_0, &dp_sdp->sdp_header);
    dp_write_vsc_packet(dp_catalog, MMSS_DP_GENERIC0_2, dp_sdp);
}

Then dp_audio functions will be able to fill struct dp_sdp_header and
call dp_write_vsc_header (or whatever other name for that function)
directly.

>
>
> >> +
> >> +       val = ((msm_dp_sdp->vsc_sdp.db[16]) | (msm_dp_sdp->vsc_sdp.db[17] << 8) |
> >> +              (msm_dp_sdp->vsc_sdp.db[18] << 16));
> >> +       dp_write_link(catalog, MMSS_DP_GENERIC0_6, val);
> >
> > Shouldn't we write full dp_sdp data, including all zeroes? Here you
> > assume that there is no other data in dp_sdp and also that nobody
> > wrote anything senseless to those registers.
> >
>
> As per documentation, it says db[0] to db[15] are reserved so I thought
> its better not to touch/use them and start writing for 16 onwards.
>
> 1592  * VSC SDP Payload for Pixel Encoding/Colorimetry Format
> 1593  * db[0] - db[15]: Reserved
> 1594  * db[16]: Pixel Encoding and Colorimetry Formats
> 1595  * db[17]: Dynamic Range and Component Bit Depth
> 1596  * db[18]: Content Type
> 1597  * db[19] - db[31]: Reserved
> 1598  */

If I understand correctly, it also supports 3D Stereo and other bits.
Also other revisions of VSC packets have other field requirements. So,
I don't think it is incorrect to write just bytes 16-18.

>
> >> +}
> >> +
> >> +static void dp_catalog_panel_update_sdp(struct dp_catalog *dp_catalog)
> >> +{
> >> +       struct dp_catalog_private *catalog;
> >> +       u32 hw_revision;
> >> +
> >> +       catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
> >> +
> >> +       hw_revision = dp_catalog_hw_revision(dp_catalog);
> >> +       if (hw_revision < DP_HW_VERSION_1_2 && hw_revision >= DP_HW_VERSION_1_0) {
> >> +               dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x01);
> >> +               dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x00);
> >> +       }
> >> +}
> >> +
> >> +void dp_catalog_panel_enable_vsc_sdp(struct dp_catalog *dp_catalog,
> >> +                                    struct msm_dp_sdp_with_parity *msm_dp_sdp)
> >> +{
> >> +       struct dp_catalog_private *catalog;
> >> +       u32 cfg, cfg2, misc;
> >> +
> >> +       if (!dp_catalog) {
> >> +               DRM_ERROR("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);
> >> +
> >> +       cfg |= GEN0_SDP_EN;
> >> +       dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
> >> +
> >> +       cfg2 |= GENERIC0_SDPSIZE_VALID;
> >> +       dp_write_link(catalog, MMSS_DP_SDP_CFG2, cfg2);
> >> +
> >> +       dp_catalog_panel_send_vsc_sdp(dp_catalog, msm_dp_sdp);
> >> +
> >> +       /* indicates presence of VSC (BIT(6) of MISC1) */
> >> +       misc |= DP_MISC1_VSC_SDP;
> >> +
> >> +       drm_dbg_dp(catalog->drm_dev, "vsc sdp enable=1\n");
> >> +
> >> +       pr_debug("misc settings = 0x%x\n", misc);
> >> +       dp_write_link(catalog, REG_DP_MISC1_MISC0, misc);
> >> +
> >> +       dp_catalog_panel_update_sdp(dp_catalog);
> >> +}
> >> +
> >> +void dp_catalog_panel_disable_vsc_sdp(struct dp_catalog *dp_catalog)
> >> +{
> >> +       struct dp_catalog_private *catalog;
> >> +       u32 cfg, cfg2, misc;
> >> +
> >> +       if (!dp_catalog) {
> >> +               DRM_ERROR("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);
> >> +
> >> +       cfg &= ~GEN0_SDP_EN;
> >> +       dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
> >> +
> >> +       cfg2 &= ~GENERIC0_SDPSIZE_VALID;
> >> +       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=0\n");
> >> +
> >> +       pr_debug("misc settings = 0x%x\n", misc);
> >> +       dp_write_link(catalog, REG_DP_MISC1_MISC0, misc);
> >> +
> >> +       dp_catalog_panel_update_sdp(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_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
> >> index 6cb5e2a243de2..4bf08c27a9bf3 100644
> >> --- a/drivers/gpu/drm/msm/dp/dp_catalog.h
> >> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
> >> @@ -9,6 +9,7 @@
> >>   #include <drm/drm_modes.h>
> >>
> >>   #include "dp_parser.h"
> >> +#include "dp_utils.h"
> >>   #include "disp/msm_disp_snapshot.h"
> >>
> >>   /* interrupts */
> >> @@ -30,6 +31,9 @@
> >>
> >>   #define DP_AUX_CFG_MAX_VALUE_CNT 3
> >>
> >> +#define DP_HW_VERSION_1_0      0x10000000
> >> +#define DP_HW_VERSION_1_2      0x10020000
> >> +
> >>   /* PHY AUX config registers */
> >>   enum dp_phy_aux_config_type {
> >>          PHY_AUX_CFG0,
> >> @@ -124,6 +128,9 @@ 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_enable_vsc_sdp(struct dp_catalog *dp_catalog,
> >> +                                    struct msm_dp_sdp_with_parity *msm_dp_sdp);
> >> +void dp_catalog_panel_disable_vsc_sdp(struct dp_catalog *dp_catalog);
> >>   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..beef86b1aaf81 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_disable_vsc_sdp(ctrl->catalog);
> >> +
> >>          /* 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_disable_vsc_sdp(ctrl->catalog);
> >> +
> >>          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 db1942794f1a4..18420a7ba4ab3 100644
> >> --- a/drivers/gpu/drm/msm/dp/dp_panel.c
> >> +++ b/drivers/gpu/drm/msm/dp/dp_panel.c
> >> @@ -4,6 +4,7 @@
> >>    */
> >>
> >>   #include "dp_panel.h"
> >> +#include "dp_utils.h"
> >>
> >>   #include <drm/drm_connector.h>
> >>   #include <drm/drm_edid.h>
> >> @@ -281,6 +282,56 @@ 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);
> >>   }
> >>
> >> +static int dp_panel_setup_vsc_sdp_yuv_420(struct dp_panel *dp_panel)
> >> +{
> >> +       struct dp_catalog *catalog;
> >> +       struct dp_panel_private *panel;
> >> +       struct dp_display_mode *dp_mode;
> >> +       struct drm_dp_vsc_sdp vsc_sdp_data;
> >> +       struct msm_dp_sdp_with_parity msm_dp_sdp;
> >> +       ssize_t len;
> >> +       int rc = 0;
> >> +
> >> +       if (!dp_panel) {
> >> +               DRM_ERROR("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(&vsc_sdp_data, 0, sizeof(vsc_sdp_data));
> >> +
> >> +       /* VSC SDP header as per table 2-118 of DP 1.4 specification */
> >> +       vsc_sdp_data.sdp_type = DP_SDP_VSC;
> >> +       vsc_sdp_data.revision = 0x05;
> >> +       vsc_sdp_data.length = 0x13;
> >> +
> >> +       /* VSC SDP Payload for DB16 */
> >> +       vsc_sdp_data.pixelformat = DP_PIXELFORMAT_YUV420;
> >> +       vsc_sdp_data.colorimetry = DP_COLORIMETRY_DEFAULT;
> >> +
> >> +       /* VSC SDP Payload for DB17 */
> >> +       vsc_sdp_data.bpc = dp_mode->bpp / 3;
> >> +       vsc_sdp_data.dynamic_range = DP_DYNAMIC_RANGE_CTA;
> >> +
> >> +       /* VSC SDP Payload for DB18 */
> >> +       vsc_sdp_data.content_type = DP_CONTENT_TYPE_GRAPHICS;
> >> +
> >> +       // rc = dp_utils_pack_vsc_sdp(&vsc_sdp_data, &sdp_header, gen_buffer, buff_size);
> >> +       len = dp_utils_pack_vsc_sdp(&vsc_sdp_data, &msm_dp_sdp);
> >> +       if (len < 0) {
> >> +               DRM_ERROR("unable to pack vsc sdp\n");
> >> +               return len;
> >> +       }
> >> +
> >> +       dp_catalog_panel_enable_vsc_sdp(catalog, &msm_dp_sdp);
> >> +
> >> +       return rc;
> >> +}
> >> +
> >>   void dp_panel_dump_regs(struct dp_panel *dp_panel)
> >>   {
> >>          struct dp_catalog *catalog;
> >> @@ -344,6 +395,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_yuv_420(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..2983756c125cd 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_VALID                 (0x00010000)
> >>
> >>   #define MMSS_DP_AUDIO_STREAM_0                 (0x00000240)
> >>   #define MMSS_DP_AUDIO_STREAM_1                 (0x00000244)
> >> diff --git a/drivers/gpu/drm/msm/dp/dp_utils.c b/drivers/gpu/drm/msm/dp/dp_utils.c
> >> index 3a44fe738c004..81601f3c414fc 100644
> >> --- a/drivers/gpu/drm/msm/dp/dp_utils.c
> >> +++ b/drivers/gpu/drm/msm/dp/dp_utils.c
> >> @@ -4,6 +4,7 @@
> >>    */
> >>
> >>   #include <linux/types.h>
> >> +#include <drm/drm_print.h>
> >>
> >>   #include "dp_utils.h"
> >>
> >> @@ -71,3 +72,50 @@ u8 dp_utils_calculate_parity(u32 data)
> >>
> >>          return parity_byte;
> >>   }
> >> +
> >> +ssize_t dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, struct msm_dp_vsc_sdp_parity *pb,
> >> +                                size_t size)
> >> +{
> >> +       u8 header;
> >> +
> >> +       size_t length = sizeof(struct msm_dp_vsc_sdp_parity);
> >> +
> >> +       if (size < length)
> >> +               return -ENOSPC;
> >> +
> >> +       memset(pb, 0, size);
> >> +
> >> +       header = sdp_header->HB0;
> >> +       pb->PB0 = dp_utils_calculate_parity(header);
> >> +
> >> +       header = sdp_header->HB1;
> >> +       pb->PB1 = dp_utils_calculate_parity(header);
> >> +
> >> +       header = sdp_header->HB2;
> >> +       pb->PB2 = dp_utils_calculate_parity(header);
> >> +
> >> +       header = sdp_header->HB3;
> >> +       pb->PB3 = dp_utils_calculate_parity(header);
> >> +
> >> +       return length;
> >> +}
> >> +
> >> +ssize_t dp_utils_pack_vsc_sdp(struct drm_dp_vsc_sdp *vsc, struct msm_dp_sdp_with_parity *msm_dp_sdp)
> >> +{
> >> +       ssize_t len;
> >> +
> >> +       len = drm_dp_vsc_sdp_pack(vsc, &msm_dp_sdp->vsc_sdp, sizeof(msm_dp_sdp->vsc_sdp));
> >> +       if (len < 0) {
> >> +               DRM_ERROR("unable to pack vsc sdp\n");
> >> +               return len;
> >> +       }
> >> +
> >> +       len = dp_utils_pack_sdp_header(&msm_dp_sdp->vsc_sdp.sdp_header, &msm_dp_sdp->pb,
> >> +                                      sizeof(msm_dp_sdp->pb));
> >> +       if (len < 0) {
> >> +               DRM_ERROR("unable to pack sdp header\n");
> >> +               return len;
> >> +       }
> >> +
> >> +       return len;
> >> +}
> >> diff --git a/drivers/gpu/drm/msm/dp/dp_utils.h b/drivers/gpu/drm/msm/dp/dp_utils.h
> >> index 5a505cbf3432b..6946bc51cae97 100644
> >> --- a/drivers/gpu/drm/msm/dp/dp_utils.h
> >> +++ b/drivers/gpu/drm/msm/dp/dp_utils.h
> >> @@ -6,6 +6,8 @@
> >>   #ifndef _DP_UTILS_H_
> >>   #define _DP_UTILS_H_
> >>
> >> +#include <drm/display/drm_dp_helper.h>
> >> +
> >>   #define HEADER_BYTE_0_BIT       0
> >>   #define PARITY_BYTE_0_BIT       8
> >>   #define HEADER_BYTE_1_BIT      16
> >> @@ -15,8 +17,24 @@
> >>   #define HEADER_BYTE_3_BIT      16
> >>   #define PARITY_BYTE_3_BIT      24
> >>
> >> +struct msm_dp_vsc_sdp_parity {
> >> +       u8 PB0;
> >> +       u8 PB1;
> >> +       u8 PB2;
> >> +       u8 PB3;
> >> +} __packed;
> >> +
> >> +struct msm_dp_sdp_with_parity {
> >> +       struct dp_sdp vsc_sdp;
> >> +       struct msm_dp_vsc_sdp_parity pb;
> >> +};
> >> +
> >>   u8 dp_utils_get_g0_value(u8 data);
> >>   u8 dp_utils_get_g1_value(u8 data);
> >>   u8 dp_utils_calculate_parity(u32 data);
> >> +ssize_t dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, struct msm_dp_vsc_sdp_parity *pb,
> >> +                                size_t size);
> >> +ssize_t dp_utils_pack_vsc_sdp(struct drm_dp_vsc_sdp *vsc,
> >> +                             struct msm_dp_sdp_with_parity *msm_dp_sdp);
> >>
> >>   #endif /* _DP_UTILS_H_ */
> >> --
> >> 2.39.2
> >>
> >
> >



-- 
With best wishes
Dmitry

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

* Re: [PATCH v3 16/19] drm/msm/dpu: modify encoder programming for CDM over DP
  2024-02-14 18:03 ` [PATCH v3 16/19] drm/msm/dpu: modify encoder programming for CDM over DP Paloma Arellano
@ 2024-02-15  8:45   ` Dmitry Baryshkov
  2024-02-15 15:47     ` Abhinav Kumar
  0 siblings, 1 reply; 33+ messages in thread
From: Dmitry Baryshkov @ 2024-02-15  8:45 UTC (permalink / raw)
  To: Paloma Arellano
  Cc: freedreno, linux-arm-msm, dri-devel, robdclark, seanpaul, swboyd,
	quic_abhinavk, quic_jesszhan, quic_khsieh, marijn.suijten,
	neil.armstrong

On Wed, 14 Feb 2024 at 20:04, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>
> Adjust the encoder format programming in the case of video mode for DP
> to accommodate CDM related changes.
>
> Changes in v2:
>         - Move timing engine programming to a separate patch from this
>           one
>         - Move update_pending_flush_periph() invocation completely to
>           this patch
>         - Change the logic of dpu_encoder_get_drm_fmt() so that it only
>           calls drm_mode_is_420_only() instead of doing additional
>           unnecessary checks
>         - Create new functions msm_dp_needs_periph_flush() and it's
>           supporting function dpu_encoder_needs_periph_flush() to check
>           if the mode is YUV420 and VSC SDP is enabled before doing a
>           peripheral flush
>
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 35 +++++++++++++++++++
>  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  | 13 +++++++
>  .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 19 ++++++++++
>  drivers/gpu/drm/msm/dp/dp_display.c           | 18 ++++++++++
>  drivers/gpu/drm/msm/msm_drv.h                 | 17 ++++++++-
>  5 files changed, 101 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 7e7796561009a..6280c6be6dca9 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -222,6 +222,41 @@ 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(struct dpu_encoder_phys *phys_enc)
> +{
> +       struct drm_encoder *drm_enc;
> +       struct dpu_encoder_virt *dpu_enc;
> +       struct drm_display_info *info;
> +       struct drm_display_mode *mode;
> +
> +       drm_enc = phys_enc->parent;
> +       dpu_enc = to_dpu_encoder_virt(drm_enc);
> +       info = &dpu_enc->connector->display_info;
> +       mode = &phys_enc->cached_mode;
> +
> +       if (drm_mode_is_420_only(info, mode))
> +               return DRM_FORMAT_YUV420;
> +
> +       return DRM_FORMAT_RGB888;
> +}
> +
> +bool dpu_encoder_needs_periph_flush(struct dpu_encoder_phys *phys_enc)
> +{
> +       struct drm_encoder *drm_enc;
> +       struct dpu_encoder_virt *dpu_enc;
> +       struct msm_display_info *disp_info;
> +       struct msm_drm_private *priv;
> +       struct drm_display_mode *mode;
> +
> +       drm_enc = phys_enc->parent;
> +       dpu_enc = to_dpu_encoder_virt(drm_enc);
> +       disp_info = &dpu_enc->disp_info;
> +       priv = drm_enc->dev->dev_private;
> +       mode = &phys_enc->cached_mode;
> +
> +       return phys_enc->hw_intf->cap->type == INTF_DP && phys_enc->hw_cdm &&
> +              msm_dp_needs_periph_flush(priv->dp[disp_info->h_tile_instance[0]], mode);
> +}
>
>  bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc)
>  {
> 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 f43d57d9c74e1..211a3d90eb690 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> @@ -341,6 +341,19 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
>   */
>  unsigned int dpu_encoder_helper_get_dsc(struct dpu_encoder_phys *phys_enc);
>
> +/**
> + * dpu_encoder_get_drm_fmt - return DRM fourcc format
> + * @phys_enc: Pointer to physical encoder structure
> + */
> +u32 dpu_encoder_get_drm_fmt(struct dpu_encoder_phys *phys_enc);
> +
> +/**
> + * dpu_encoder_needs_periph_flush - return true if physical encoder requires
> + *     peripheral flush
> + * @phys_enc: Pointer to physical encoder structure
> + */
> +bool dpu_encoder_needs_periph_flush(struct dpu_encoder_phys *phys_enc);
> +
>  /**
>   * dpu_encoder_helper_split_config - split display configuration helper function
>   *     This helper function may be used by physical encoders to configure
> 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 f02411b062c4c..e29bc4bd39208 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
> @@ -415,8 +415,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)

I thought that Abhinav proposed to drop the if(hw_cdm) condition here.
LGTM otherwise.

> +               fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc);
> +       fmt = dpu_get_dpu_format(fmt_fourcc);
>
>         DPU_DEBUG_VIDENC(phys_enc, "\n");
>
> @@ -425,6 +432,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);
>
>         /*
> @@ -440,6 +449,16 @@ 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_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 && dpu_encoder_needs_periph_flush(phys_enc))
> +               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/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
> index 4b04388719363..ebcc76ef1d590 100644
> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> @@ -1397,6 +1397,24 @@ 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 && drm_mode_is_420_only(info, mode);
> +}
> +
> +bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display,
> +                              const struct drm_display_mode *mode)
> +{
> +       return msm_dp_is_yuv_420_enabled(dp_display, 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..b876ebd48effe 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -387,7 +387,10 @@ 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_needs_periph_flush(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 +412,18 @@ 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_needs_periph_flush(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
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH v3 17/19] drm/msm/dpu: modify timing engine programming for YUV420 over DP
  2024-02-14 18:03 ` [PATCH v3 17/19] drm/msm/dpu: modify timing engine programming for YUV420 " Paloma Arellano
@ 2024-02-15  8:55   ` Dmitry Baryshkov
  0 siblings, 0 replies; 33+ messages in thread
From: Dmitry Baryshkov @ 2024-02-15  8:55 UTC (permalink / raw)
  To: Paloma Arellano
  Cc: freedreno, linux-arm-msm, dri-devel, robdclark, seanpaul, swboyd,
	quic_abhinavk, quic_jesszhan, quic_khsieh, marijn.suijten,
	neil.armstrong

On Wed, 14 Feb 2024 at 20:04, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>
> Adjust the encoder timing engine setup programming in the case of video
> mode for YUV420 over DP to accommodate CDM.
>
> Changes in v3:
>         - Move drm_display_mode's hskew division to another patch
>         - Minor cleanup
>
> Changes in v2:
>         - Move timing engine programming to this patch
>
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)

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

-- 
With best wishes
Dmitry

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

* Re: [PATCH v3 02/19] drm/msm/dpu: add division of drm_display_mode's hskew parameter
  2024-02-14 18:03 ` [PATCH v3 02/19] drm/msm/dpu: add division of drm_display_mode's hskew parameter Paloma Arellano
@ 2024-02-15  8:56   ` Dmitry Baryshkov
  0 siblings, 0 replies; 33+ messages in thread
From: Dmitry Baryshkov @ 2024-02-15  8:56 UTC (permalink / raw)
  To: Paloma Arellano
  Cc: freedreno, linux-arm-msm, dri-devel, robdclark, seanpaul, swboyd,
	quic_abhinavk, quic_jesszhan, quic_khsieh, marijn.suijten,
	neil.armstrong

On Wed, 14 Feb 2024 at 20:04, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>
> Setting up the timing engine when the physical encoder has a split role
> neglects dividing the drm_display_mode's hskew parameter. Let's fix this
> since this must also be done in preparation for implementing YUV420 over
> DP.
>
> Fixes: 25fdd5933e4c ("drm/msm: Add SDM845 DPU support")
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)

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

-- 
With best wishes
Dmitry

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

* Re: [PATCH v3 19/19] drm/msm/dp: allow YUV420 mode for DP connector when CDM available
  2024-02-14 18:03 ` [PATCH v3 19/19] drm/msm/dp: allow YUV420 mode for DP connector when CDM available Paloma Arellano
@ 2024-02-15  8:57   ` Dmitry Baryshkov
  0 siblings, 0 replies; 33+ messages in thread
From: Dmitry Baryshkov @ 2024-02-15  8:57 UTC (permalink / raw)
  To: Paloma Arellano
  Cc: freedreno, linux-arm-msm, dri-devel, robdclark, seanpaul, swboyd,
	quic_abhinavk, quic_jesszhan, quic_khsieh, marijn.suijten,
	neil.armstrong

On Wed, 14 Feb 2024 at 20:04, Paloma Arellano <quic_parellan@quicinc.com> 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 there is a CDM block available.
>
> Changes in v3:
>         - Move setting the connector's ycbcr_420_allowed parameter so
>           that it is not dependent on if the dp_display is not eDP
>
> Changes in v2:
>         - Check for if dp_catalog has a CDM block available instead of
>           checking if VSC SDP is allowed when setting the dp connector's
>           ycbcr_420_allowed parameter
>
> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 4 +++-
>  drivers/gpu/drm/msm/dp/dp_display.c     | 4 ++--
>  drivers/gpu/drm/msm/dp/dp_drm.c         | 6 +++++-
>  drivers/gpu/drm/msm/dp/dp_drm.h         | 3 ++-
>  drivers/gpu/drm/msm/msm_drv.h           | 5 +++--
>  5 files changed, 15 insertions(+), 7 deletions(-)

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



-- 
With best wishes
Dmitry

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

* Re: [PATCH v3 16/19] drm/msm/dpu: modify encoder programming for CDM over DP
  2024-02-15  8:45   ` Dmitry Baryshkov
@ 2024-02-15 15:47     ` Abhinav Kumar
  2024-02-15 18:37       ` Paloma Arellano
  0 siblings, 1 reply; 33+ messages in thread
From: Abhinav Kumar @ 2024-02-15 15:47 UTC (permalink / raw)
  To: Dmitry Baryshkov, Paloma Arellano
  Cc: freedreno, linux-arm-msm, dri-devel, robdclark, seanpaul, swboyd,
	quic_jesszhan, quic_khsieh, marijn.suijten, neil.armstrong



On 2/15/2024 12:45 AM, Dmitry Baryshkov wrote:
> On Wed, 14 Feb 2024 at 20:04, Paloma Arellano <quic_parellan@quicinc.com> wrote:
>>
>> Adjust the encoder format programming in the case of video mode for DP
>> to accommodate CDM related changes.
>>
>> Changes in v2:
>>          - Move timing engine programming to a separate patch from this
>>            one
>>          - Move update_pending_flush_periph() invocation completely to
>>            this patch
>>          - Change the logic of dpu_encoder_get_drm_fmt() so that it only
>>            calls drm_mode_is_420_only() instead of doing additional
>>            unnecessary checks
>>          - Create new functions msm_dp_needs_periph_flush() and it's
>>            supporting function dpu_encoder_needs_periph_flush() to check
>>            if the mode is YUV420 and VSC SDP is enabled before doing a
>>            peripheral flush
>>
>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 35 +++++++++++++++++++
>>   .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  | 13 +++++++
>>   .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 19 ++++++++++
>>   drivers/gpu/drm/msm/dp/dp_display.c           | 18 ++++++++++
>>   drivers/gpu/drm/msm/msm_drv.h                 | 17 ++++++++-
>>   5 files changed, 101 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> index 7e7796561009a..6280c6be6dca9 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> @@ -222,6 +222,41 @@ 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(struct dpu_encoder_phys *phys_enc)
>> +{
>> +       struct drm_encoder *drm_enc;
>> +       struct dpu_encoder_virt *dpu_enc;
>> +       struct drm_display_info *info;
>> +       struct drm_display_mode *mode;
>> +
>> +       drm_enc = phys_enc->parent;
>> +       dpu_enc = to_dpu_encoder_virt(drm_enc);
>> +       info = &dpu_enc->connector->display_info;
>> +       mode = &phys_enc->cached_mode;
>> +
>> +       if (drm_mode_is_420_only(info, mode))
>> +               return DRM_FORMAT_YUV420;
>> +
>> +       return DRM_FORMAT_RGB888;
>> +}
>> +
>> +bool dpu_encoder_needs_periph_flush(struct dpu_encoder_phys *phys_enc)
>> +{
>> +       struct drm_encoder *drm_enc;
>> +       struct dpu_encoder_virt *dpu_enc;
>> +       struct msm_display_info *disp_info;
>> +       struct msm_drm_private *priv;
>> +       struct drm_display_mode *mode;
>> +
>> +       drm_enc = phys_enc->parent;
>> +       dpu_enc = to_dpu_encoder_virt(drm_enc);
>> +       disp_info = &dpu_enc->disp_info;
>> +       priv = drm_enc->dev->dev_private;
>> +       mode = &phys_enc->cached_mode;
>> +
>> +       return phys_enc->hw_intf->cap->type == INTF_DP && phys_enc->hw_cdm &&
>> +              msm_dp_needs_periph_flush(priv->dp[disp_info->h_tile_instance[0]], mode);
>> +}
>>
>>   bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc)
>>   {
>> 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 f43d57d9c74e1..211a3d90eb690 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>> @@ -341,6 +341,19 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
>>    */
>>   unsigned int dpu_encoder_helper_get_dsc(struct dpu_encoder_phys *phys_enc);
>>
>> +/**
>> + * dpu_encoder_get_drm_fmt - return DRM fourcc format
>> + * @phys_enc: Pointer to physical encoder structure
>> + */
>> +u32 dpu_encoder_get_drm_fmt(struct dpu_encoder_phys *phys_enc);
>> +
>> +/**
>> + * dpu_encoder_needs_periph_flush - return true if physical encoder requires
>> + *     peripheral flush
>> + * @phys_enc: Pointer to physical encoder structure
>> + */
>> +bool dpu_encoder_needs_periph_flush(struct dpu_encoder_phys *phys_enc);
>> +
>>   /**
>>    * dpu_encoder_helper_split_config - split display configuration helper function
>>    *     This helper function may be used by physical encoders to configure
>> 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 f02411b062c4c..e29bc4bd39208 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
>> @@ -415,8 +415,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)
> 
> I thought that Abhinav proposed to drop the if(hw_cdm) condition here.
> LGTM otherwise.
> 

Yes I did.

This needs to be fixed in v4.

>> +               fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc);
>> +       fmt = dpu_get_dpu_format(fmt_fourcc);
>>
>>          DPU_DEBUG_VIDENC(phys_enc, "\n");
>>
>> @@ -425,6 +432,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);
>>
>>          /*
>> @@ -440,6 +449,16 @@ 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_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 && dpu_encoder_needs_periph_flush(phys_enc))
>> +               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/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
>> index 4b04388719363..ebcc76ef1d590 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
>> @@ -1397,6 +1397,24 @@ 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 && drm_mode_is_420_only(info, mode);
>> +}
>> +
>> +bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display,
>> +                              const struct drm_display_mode *mode)
>> +{
>> +       return msm_dp_is_yuv_420_enabled(dp_display, 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..b876ebd48effe 100644
>> --- a/drivers/gpu/drm/msm/msm_drv.h
>> +++ b/drivers/gpu/drm/msm/msm_drv.h
>> @@ -387,7 +387,10 @@ 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_needs_periph_flush(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 +412,18 @@ 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_needs_periph_flush(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	[flat|nested] 33+ messages in thread

* Re: [PATCH v3 13/19] drm/msm/dp: add VSC SDP support for YUV420 over DP
  2024-02-15  8:40       ` Dmitry Baryshkov
@ 2024-02-15 16:39         ` Abhinav Kumar
  2024-02-15 17:03           ` Dmitry Baryshkov
  0 siblings, 1 reply; 33+ messages in thread
From: Abhinav Kumar @ 2024-02-15 16:39 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 2/15/2024 12:40 AM, Dmitry Baryshkov wrote:
> On Wed, 14 Feb 2024 at 22:15, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 2/14/2024 11:39 AM, Dmitry Baryshkov wrote:
>>> On Wed, 14 Feb 2024 at 20:04, Paloma Arellano <quic_parellan@quicinc.com> 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.
>>>>
>>>> Changes in v3:
>>>>           - Create a new struct, msm_dp_sdp_with_parity, which holds the
>>>>             packing information for VSC SDP
>>>>           - Use drm_dp_vsc_sdp_pack() to pack the data into the new
>>>>             msm_dp_sdp_with_parity struct instead of specifically packing
>>>>             for YUV420 format
>>>>           - Modify dp_catalog_panel_send_vsc_sdp() to send the VSC SDP
>>>>             data using the new msm_dp_sdp_with_parity struct
>>>>
>>>> Changes in v2:
>>>>           - Rename GENERIC0_SDPSIZE macro to GENERIC0_SDPSIZE_VALID
>>>>           - Remove dp_sdp from the dp_catalog struct since this data is
>>>>             being allocated at the point used
>>>>           - Create a new function in dp_utils to pack the VSC SDP data
>>>>             into a buffer
>>>>           - Create a new function that packs the SDP header bytes into a
>>>>             buffer. This function is made generic so that it can be
>>>>             utilized by dp_audio
>>>>             header bytes into a buffer
>>>>           - Create a new function in dp_utils that takes the packed buffer
>>>>             and writes to the DP_GENERIC0_* registers
>>>>           - Split the dp_catalog_panel_config_vsc_sdp() function into two
>>>>             to disable/enable sending VSC SDP packets
>>>>           - Check the DP HW version using the original useage of
>>>>             dp_catalog_hw_revision() and correct the version checking
>>>>             logic
>>>>           - Rename dp_panel_setup_vsc_sdp() to
>>>>             dp_panel_setup_vsc_sdp_yuv_420() to explicitly state that
>>>>             currently VSC SDP is only being set up to support YUV420 modes
>>>>
>>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>>> ---
>>>>    drivers/gpu/drm/msm/dp/dp_catalog.c | 113 ++++++++++++++++++++++++++++
>>>>    drivers/gpu/drm/msm/dp/dp_catalog.h |   7 ++
>>>>    drivers/gpu/drm/msm/dp/dp_ctrl.c    |   4 +
>>>>    drivers/gpu/drm/msm/dp/dp_panel.c   |  55 ++++++++++++++
>>>>    drivers/gpu/drm/msm/dp/dp_reg.h     |   3 +
>>>>    drivers/gpu/drm/msm/dp/dp_utils.c   |  48 ++++++++++++
>>>>    drivers/gpu/drm/msm/dp/dp_utils.h   |  18 +++++
>>>>    7 files changed, 248 insertions(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
>>>> index 5d84c089e520a..61d5317efe683 100644
>>>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
>>>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
>>>> @@ -901,6 +901,119 @@ int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog)
>>>>           return 0;
>>>>    }
>>>>
>>>> +static void dp_catalog_panel_send_vsc_sdp(struct dp_catalog *dp_catalog,
>>>> +                                         struct msm_dp_sdp_with_parity *msm_dp_sdp)
>>>> +{
>>>> +       struct dp_catalog_private *catalog;
>>>> +       u32 val;
>>>> +
>>>> +       if (!dp_catalog) {
>>>> +               DRM_ERROR("invalid input\n");
>>>> +               return;
>>>> +       }
>>>> +
>>>> +       catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
>>>> +
>>>> +       val = ((msm_dp_sdp->vsc_sdp.sdp_header.HB0) << HEADER_BYTE_0_BIT |
>>>> +              (msm_dp_sdp->pb.PB0 << PARITY_BYTE_0_BIT) |
>>>> +              (msm_dp_sdp->vsc_sdp.sdp_header.HB1) << HEADER_BYTE_1_BIT |
>>>> +              (msm_dp_sdp->pb.PB1 << PARITY_BYTE_1_BIT));
>>>> +       dp_write_link(catalog, MMSS_DP_GENERIC0_0, val);
>>>> +
>>>> +       val = ((msm_dp_sdp->vsc_sdp.sdp_header.HB2) << HEADER_BYTE_2_BIT |
>>>> +              (msm_dp_sdp->pb.PB2 << PARITY_BYTE_2_BIT) |
>>>> +              (msm_dp_sdp->vsc_sdp.sdp_header.HB3) << HEADER_BYTE_3_BIT |
>>>> +              (msm_dp_sdp->pb.PB3 << PARITY_BYTE_3_BIT));
>>>> +       dp_write_link(catalog, MMSS_DP_GENERIC0_1, val);
>>>
>>> I still think that this is not the way to do it. Could you please
>>> extract the function that takes struct dp_sdp_header, calculates
>>> padding and writes resulting data to the hardware? This way we can
>>> reuse it later for all the dp_audio stuff.
>>>
>>
>> hmmm ... dp_utils_pack_sdp_header() does that you are asking for right?
>>
>> OR are you asking for another function like:
>>
>> 1) rename dp_utils_pack_sdp_header() to dp_utils_calc_sdp_parity()
>> 2) dp_utils_pack_sdp() takes two u32 to pack the header and parity
>> together and we move the << HEADER_BYTE_xx | part to it
>>
>> dp_catalog_panel_send_vsc_sdp() just uses these two u32 to write the
>> headers.
> 
> I'm really looking for the following function:
> 
> void dp_catalog_panel_send_vsc_sdp(struct dp_catalog *dp_catalog,
> struct dp_sdp *dp_sdp)
> {
>      dp_write_vsc_header(dp_catalog, MMSS_DP_GENERIC0_0, &dp_sdp->sdp_header);
>      dp_write_vsc_packet(dp_catalog, MMSS_DP_GENERIC0_2, dp_sdp);
> }
> 
> Then dp_audio functions will be able to fill struct dp_sdp_header and
> call dp_write_vsc_header (or whatever other name for that function)
> directly.
> 

I think there is some misunderstanding here.

Audio does not write or use generic_0 registers. It uses audio infoframe 
SDP registers. So the catalog function of audio will not change.

The only part common between audio and vsc sdp is the parity byte 
calculation and the packing of parity and header bytes into 2 u32s.

Thats why I wrote that we will have a common util between audio and vsc 
sdp only to pack the data but the catalog functions will be different.


>>
>>
>>>> +
>>>> +       val = ((msm_dp_sdp->vsc_sdp.db[16]) | (msm_dp_sdp->vsc_sdp.db[17] << 8) |
>>>> +              (msm_dp_sdp->vsc_sdp.db[18] << 16));
>>>> +       dp_write_link(catalog, MMSS_DP_GENERIC0_6, val);
>>>
>>> Shouldn't we write full dp_sdp data, including all zeroes? Here you
>>> assume that there is no other data in dp_sdp and also that nobody
>>> wrote anything senseless to those registers.
>>>
>>
>> As per documentation, it says db[0] to db[15] are reserved so I thought
>> its better not to touch/use them and start writing for 16 onwards.
>>
>> 1592  * VSC SDP Payload for Pixel Encoding/Colorimetry Format
>> 1593  * db[0] - db[15]: Reserved
>> 1594  * db[16]: Pixel Encoding and Colorimetry Formats
>> 1595  * db[17]: Dynamic Range and Component Bit Depth
>> 1596  * db[18]: Content Type
>> 1597  * db[19] - db[31]: Reserved
>> 1598  */
> 
> If I understand correctly, it also supports 3D Stereo and other bits.
> Also other revisions of VSC packets have other field requirements. So,
> I don't think it is incorrect to write just bytes 16-18.
> 

hmmm .... the packing function of vsc sdp does not consider 3D stereo 
bits today. But I guess if someone adds it later then we will not have 
to change this code if we write the rest of the payload as well.

Okay, lets write all the 32 bytes of payload across to registers 
GENERIC0_2 to GENERIC0_9


>>
>>>> +}
>>>> +
>>>> +static void dp_catalog_panel_update_sdp(struct dp_catalog *dp_catalog)
>>>> +{
>>>> +       struct dp_catalog_private *catalog;
>>>> +       u32 hw_revision;
>>>> +
>>>> +       catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
>>>> +
>>>> +       hw_revision = dp_catalog_hw_revision(dp_catalog);
>>>> +       if (hw_revision < DP_HW_VERSION_1_2 && hw_revision >= DP_HW_VERSION_1_0) {
>>>> +               dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x01);
>>>> +               dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x00);
>>>> +       }
>>>> +}
>>>> +
>>>> +void dp_catalog_panel_enable_vsc_sdp(struct dp_catalog *dp_catalog,
>>>> +                                    struct msm_dp_sdp_with_parity *msm_dp_sdp)
>>>> +{
>>>> +       struct dp_catalog_private *catalog;
>>>> +       u32 cfg, cfg2, misc;
>>>> +
>>>> +       if (!dp_catalog) {
>>>> +               DRM_ERROR("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);
>>>> +
>>>> +       cfg |= GEN0_SDP_EN;
>>>> +       dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
>>>> +
>>>> +       cfg2 |= GENERIC0_SDPSIZE_VALID;
>>>> +       dp_write_link(catalog, MMSS_DP_SDP_CFG2, cfg2);
>>>> +
>>>> +       dp_catalog_panel_send_vsc_sdp(dp_catalog, msm_dp_sdp);
>>>> +
>>>> +       /* indicates presence of VSC (BIT(6) of MISC1) */
>>>> +       misc |= DP_MISC1_VSC_SDP;
>>>> +
>>>> +       drm_dbg_dp(catalog->drm_dev, "vsc sdp enable=1\n");
>>>> +
>>>> +       pr_debug("misc settings = 0x%x\n", misc);
>>>> +       dp_write_link(catalog, REG_DP_MISC1_MISC0, misc);
>>>> +
>>>> +       dp_catalog_panel_update_sdp(dp_catalog);
>>>> +}
>>>> +
>>>> +void dp_catalog_panel_disable_vsc_sdp(struct dp_catalog *dp_catalog)
>>>> +{
>>>> +       struct dp_catalog_private *catalog;
>>>> +       u32 cfg, cfg2, misc;
>>>> +
>>>> +       if (!dp_catalog) {
>>>> +               DRM_ERROR("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);
>>>> +
>>>> +       cfg &= ~GEN0_SDP_EN;
>>>> +       dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
>>>> +
>>>> +       cfg2 &= ~GENERIC0_SDPSIZE_VALID;
>>>> +       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=0\n");
>>>> +
>>>> +       pr_debug("misc settings = 0x%x\n", misc);
>>>> +       dp_write_link(catalog, REG_DP_MISC1_MISC0, misc);
>>>> +
>>>> +       dp_catalog_panel_update_sdp(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_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
>>>> index 6cb5e2a243de2..4bf08c27a9bf3 100644
>>>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.h
>>>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
>>>> @@ -9,6 +9,7 @@
>>>>    #include <drm/drm_modes.h>
>>>>
>>>>    #include "dp_parser.h"
>>>> +#include "dp_utils.h"
>>>>    #include "disp/msm_disp_snapshot.h"
>>>>
>>>>    /* interrupts */
>>>> @@ -30,6 +31,9 @@
>>>>
>>>>    #define DP_AUX_CFG_MAX_VALUE_CNT 3
>>>>
>>>> +#define DP_HW_VERSION_1_0      0x10000000
>>>> +#define DP_HW_VERSION_1_2      0x10020000
>>>> +
>>>>    /* PHY AUX config registers */
>>>>    enum dp_phy_aux_config_type {
>>>>           PHY_AUX_CFG0,
>>>> @@ -124,6 +128,9 @@ 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_enable_vsc_sdp(struct dp_catalog *dp_catalog,
>>>> +                                    struct msm_dp_sdp_with_parity *msm_dp_sdp);
>>>> +void dp_catalog_panel_disable_vsc_sdp(struct dp_catalog *dp_catalog);
>>>>    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..beef86b1aaf81 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_disable_vsc_sdp(ctrl->catalog);
>>>> +
>>>>           /* 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_disable_vsc_sdp(ctrl->catalog);
>>>> +
>>>>           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 db1942794f1a4..18420a7ba4ab3 100644
>>>> --- a/drivers/gpu/drm/msm/dp/dp_panel.c
>>>> +++ b/drivers/gpu/drm/msm/dp/dp_panel.c
>>>> @@ -4,6 +4,7 @@
>>>>     */
>>>>
>>>>    #include "dp_panel.h"
>>>> +#include "dp_utils.h"
>>>>
>>>>    #include <drm/drm_connector.h>
>>>>    #include <drm/drm_edid.h>
>>>> @@ -281,6 +282,56 @@ 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);
>>>>    }
>>>>
>>>> +static int dp_panel_setup_vsc_sdp_yuv_420(struct dp_panel *dp_panel)
>>>> +{
>>>> +       struct dp_catalog *catalog;
>>>> +       struct dp_panel_private *panel;
>>>> +       struct dp_display_mode *dp_mode;
>>>> +       struct drm_dp_vsc_sdp vsc_sdp_data;
>>>> +       struct msm_dp_sdp_with_parity msm_dp_sdp;
>>>> +       ssize_t len;
>>>> +       int rc = 0;
>>>> +
>>>> +       if (!dp_panel) {
>>>> +               DRM_ERROR("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(&vsc_sdp_data, 0, sizeof(vsc_sdp_data));
>>>> +
>>>> +       /* VSC SDP header as per table 2-118 of DP 1.4 specification */
>>>> +       vsc_sdp_data.sdp_type = DP_SDP_VSC;
>>>> +       vsc_sdp_data.revision = 0x05;
>>>> +       vsc_sdp_data.length = 0x13;
>>>> +
>>>> +       /* VSC SDP Payload for DB16 */
>>>> +       vsc_sdp_data.pixelformat = DP_PIXELFORMAT_YUV420;
>>>> +       vsc_sdp_data.colorimetry = DP_COLORIMETRY_DEFAULT;
>>>> +
>>>> +       /* VSC SDP Payload for DB17 */
>>>> +       vsc_sdp_data.bpc = dp_mode->bpp / 3;
>>>> +       vsc_sdp_data.dynamic_range = DP_DYNAMIC_RANGE_CTA;
>>>> +
>>>> +       /* VSC SDP Payload for DB18 */
>>>> +       vsc_sdp_data.content_type = DP_CONTENT_TYPE_GRAPHICS;
>>>> +
>>>> +       // rc = dp_utils_pack_vsc_sdp(&vsc_sdp_data, &sdp_header, gen_buffer, buff_size);
>>>> +       len = dp_utils_pack_vsc_sdp(&vsc_sdp_data, &msm_dp_sdp);
>>>> +       if (len < 0) {
>>>> +               DRM_ERROR("unable to pack vsc sdp\n");
>>>> +               return len;
>>>> +       }
>>>> +
>>>> +       dp_catalog_panel_enable_vsc_sdp(catalog, &msm_dp_sdp);
>>>> +
>>>> +       return rc;
>>>> +}
>>>> +
>>>>    void dp_panel_dump_regs(struct dp_panel *dp_panel)
>>>>    {
>>>>           struct dp_catalog *catalog;
>>>> @@ -344,6 +395,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_yuv_420(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..2983756c125cd 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_VALID                 (0x00010000)
>>>>
>>>>    #define MMSS_DP_AUDIO_STREAM_0                 (0x00000240)
>>>>    #define MMSS_DP_AUDIO_STREAM_1                 (0x00000244)
>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_utils.c b/drivers/gpu/drm/msm/dp/dp_utils.c
>>>> index 3a44fe738c004..81601f3c414fc 100644
>>>> --- a/drivers/gpu/drm/msm/dp/dp_utils.c
>>>> +++ b/drivers/gpu/drm/msm/dp/dp_utils.c
>>>> @@ -4,6 +4,7 @@
>>>>     */
>>>>
>>>>    #include <linux/types.h>
>>>> +#include <drm/drm_print.h>
>>>>
>>>>    #include "dp_utils.h"
>>>>
>>>> @@ -71,3 +72,50 @@ u8 dp_utils_calculate_parity(u32 data)
>>>>
>>>>           return parity_byte;
>>>>    }
>>>> +
>>>> +ssize_t dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, struct msm_dp_vsc_sdp_parity *pb,
>>>> +                                size_t size)
>>>> +{
>>>> +       u8 header;
>>>> +
>>>> +       size_t length = sizeof(struct msm_dp_vsc_sdp_parity);
>>>> +
>>>> +       if (size < length)
>>>> +               return -ENOSPC;
>>>> +
>>>> +       memset(pb, 0, size);
>>>> +
>>>> +       header = sdp_header->HB0;
>>>> +       pb->PB0 = dp_utils_calculate_parity(header);
>>>> +
>>>> +       header = sdp_header->HB1;
>>>> +       pb->PB1 = dp_utils_calculate_parity(header);
>>>> +
>>>> +       header = sdp_header->HB2;
>>>> +       pb->PB2 = dp_utils_calculate_parity(header);
>>>> +
>>>> +       header = sdp_header->HB3;
>>>> +       pb->PB3 = dp_utils_calculate_parity(header);
>>>> +
>>>> +       return length;
>>>> +}
>>>> +
>>>> +ssize_t dp_utils_pack_vsc_sdp(struct drm_dp_vsc_sdp *vsc, struct msm_dp_sdp_with_parity *msm_dp_sdp)
>>>> +{
>>>> +       ssize_t len;
>>>> +
>>>> +       len = drm_dp_vsc_sdp_pack(vsc, &msm_dp_sdp->vsc_sdp, sizeof(msm_dp_sdp->vsc_sdp));
>>>> +       if (len < 0) {
>>>> +               DRM_ERROR("unable to pack vsc sdp\n");
>>>> +               return len;
>>>> +       }
>>>> +
>>>> +       len = dp_utils_pack_sdp_header(&msm_dp_sdp->vsc_sdp.sdp_header, &msm_dp_sdp->pb,
>>>> +                                      sizeof(msm_dp_sdp->pb));
>>>> +       if (len < 0) {
>>>> +               DRM_ERROR("unable to pack sdp header\n");
>>>> +               return len;
>>>> +       }
>>>> +
>>>> +       return len;
>>>> +}
>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_utils.h b/drivers/gpu/drm/msm/dp/dp_utils.h
>>>> index 5a505cbf3432b..6946bc51cae97 100644
>>>> --- a/drivers/gpu/drm/msm/dp/dp_utils.h
>>>> +++ b/drivers/gpu/drm/msm/dp/dp_utils.h
>>>> @@ -6,6 +6,8 @@
>>>>    #ifndef _DP_UTILS_H_
>>>>    #define _DP_UTILS_H_
>>>>
>>>> +#include <drm/display/drm_dp_helper.h>
>>>> +
>>>>    #define HEADER_BYTE_0_BIT       0
>>>>    #define PARITY_BYTE_0_BIT       8
>>>>    #define HEADER_BYTE_1_BIT      16
>>>> @@ -15,8 +17,24 @@
>>>>    #define HEADER_BYTE_3_BIT      16
>>>>    #define PARITY_BYTE_3_BIT      24
>>>>
>>>> +struct msm_dp_vsc_sdp_parity {
>>>> +       u8 PB0;
>>>> +       u8 PB1;
>>>> +       u8 PB2;
>>>> +       u8 PB3;
>>>> +} __packed;
>>>> +
>>>> +struct msm_dp_sdp_with_parity {
>>>> +       struct dp_sdp vsc_sdp;
>>>> +       struct msm_dp_vsc_sdp_parity pb;
>>>> +};
>>>> +
>>>>    u8 dp_utils_get_g0_value(u8 data);
>>>>    u8 dp_utils_get_g1_value(u8 data);
>>>>    u8 dp_utils_calculate_parity(u32 data);
>>>> +ssize_t dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, struct msm_dp_vsc_sdp_parity *pb,
>>>> +                                size_t size);
>>>> +ssize_t dp_utils_pack_vsc_sdp(struct drm_dp_vsc_sdp *vsc,
>>>> +                             struct msm_dp_sdp_with_parity *msm_dp_sdp);
>>>>
>>>>    #endif /* _DP_UTILS_H_ */
>>>> --
>>>> 2.39.2
>>>>
>>>
>>>
> 
> 
> 

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

* Re: [PATCH v3 13/19] drm/msm/dp: add VSC SDP support for YUV420 over DP
  2024-02-15 16:39         ` Abhinav Kumar
@ 2024-02-15 17:03           ` Dmitry Baryshkov
  2024-02-15 18:40             ` Dmitry Baryshkov
  0 siblings, 1 reply; 33+ messages in thread
From: Dmitry Baryshkov @ 2024-02-15 17:03 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: Paloma Arellano, freedreno, linux-arm-msm, dri-devel, robdclark,
	seanpaul, swboyd, quic_jesszhan, quic_khsieh, marijn.suijten,
	neil.armstrong

On Thu, 15 Feb 2024 at 18:39, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 2/15/2024 12:40 AM, Dmitry Baryshkov wrote:
> > On Wed, 14 Feb 2024 at 22:15, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >>
> >>
> >> On 2/14/2024 11:39 AM, Dmitry Baryshkov wrote:
> >>> On Wed, 14 Feb 2024 at 20:04, Paloma Arellano <quic_parellan@quicinc.com> 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.
> >>>>
> >>>> Changes in v3:
> >>>>           - Create a new struct, msm_dp_sdp_with_parity, which holds the
> >>>>             packing information for VSC SDP
> >>>>           - Use drm_dp_vsc_sdp_pack() to pack the data into the new
> >>>>             msm_dp_sdp_with_parity struct instead of specifically packing
> >>>>             for YUV420 format
> >>>>           - Modify dp_catalog_panel_send_vsc_sdp() to send the VSC SDP
> >>>>             data using the new msm_dp_sdp_with_parity struct
> >>>>
> >>>> Changes in v2:
> >>>>           - Rename GENERIC0_SDPSIZE macro to GENERIC0_SDPSIZE_VALID
> >>>>           - Remove dp_sdp from the dp_catalog struct since this data is
> >>>>             being allocated at the point used
> >>>>           - Create a new function in dp_utils to pack the VSC SDP data
> >>>>             into a buffer
> >>>>           - Create a new function that packs the SDP header bytes into a
> >>>>             buffer. This function is made generic so that it can be
> >>>>             utilized by dp_audio
> >>>>             header bytes into a buffer
> >>>>           - Create a new function in dp_utils that takes the packed buffer
> >>>>             and writes to the DP_GENERIC0_* registers
> >>>>           - Split the dp_catalog_panel_config_vsc_sdp() function into two
> >>>>             to disable/enable sending VSC SDP packets
> >>>>           - Check the DP HW version using the original useage of
> >>>>             dp_catalog_hw_revision() and correct the version checking
> >>>>             logic
> >>>>           - Rename dp_panel_setup_vsc_sdp() to
> >>>>             dp_panel_setup_vsc_sdp_yuv_420() to explicitly state that
> >>>>             currently VSC SDP is only being set up to support YUV420 modes
> >>>>
> >>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> >>>> ---
> >>>>    drivers/gpu/drm/msm/dp/dp_catalog.c | 113 ++++++++++++++++++++++++++++
> >>>>    drivers/gpu/drm/msm/dp/dp_catalog.h |   7 ++
> >>>>    drivers/gpu/drm/msm/dp/dp_ctrl.c    |   4 +
> >>>>    drivers/gpu/drm/msm/dp/dp_panel.c   |  55 ++++++++++++++
> >>>>    drivers/gpu/drm/msm/dp/dp_reg.h     |   3 +
> >>>>    drivers/gpu/drm/msm/dp/dp_utils.c   |  48 ++++++++++++
> >>>>    drivers/gpu/drm/msm/dp/dp_utils.h   |  18 +++++
> >>>>    7 files changed, 248 insertions(+)
> >>>>
> >>>> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
> >>>> index 5d84c089e520a..61d5317efe683 100644
> >>>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
> >>>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
> >>>> @@ -901,6 +901,119 @@ int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog)
> >>>>           return 0;
> >>>>    }
> >>>>
> >>>> +static void dp_catalog_panel_send_vsc_sdp(struct dp_catalog *dp_catalog,
> >>>> +                                         struct msm_dp_sdp_with_parity *msm_dp_sdp)
> >>>> +{
> >>>> +       struct dp_catalog_private *catalog;
> >>>> +       u32 val;
> >>>> +
> >>>> +       if (!dp_catalog) {
> >>>> +               DRM_ERROR("invalid input\n");
> >>>> +               return;
> >>>> +       }
> >>>> +
> >>>> +       catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
> >>>> +
> >>>> +       val = ((msm_dp_sdp->vsc_sdp.sdp_header.HB0) << HEADER_BYTE_0_BIT |
> >>>> +              (msm_dp_sdp->pb.PB0 << PARITY_BYTE_0_BIT) |
> >>>> +              (msm_dp_sdp->vsc_sdp.sdp_header.HB1) << HEADER_BYTE_1_BIT |
> >>>> +              (msm_dp_sdp->pb.PB1 << PARITY_BYTE_1_BIT));
> >>>> +       dp_write_link(catalog, MMSS_DP_GENERIC0_0, val);
> >>>> +
> >>>> +       val = ((msm_dp_sdp->vsc_sdp.sdp_header.HB2) << HEADER_BYTE_2_BIT |
> >>>> +              (msm_dp_sdp->pb.PB2 << PARITY_BYTE_2_BIT) |
> >>>> +              (msm_dp_sdp->vsc_sdp.sdp_header.HB3) << HEADER_BYTE_3_BIT |
> >>>> +              (msm_dp_sdp->pb.PB3 << PARITY_BYTE_3_BIT));
> >>>> +       dp_write_link(catalog, MMSS_DP_GENERIC0_1, val);
> >>>
> >>> I still think that this is not the way to do it. Could you please
> >>> extract the function that takes struct dp_sdp_header, calculates
> >>> padding and writes resulting data to the hardware? This way we can
> >>> reuse it later for all the dp_audio stuff.
> >>>
> >>
> >> hmmm ... dp_utils_pack_sdp_header() does that you are asking for right?
> >>
> >> OR are you asking for another function like:
> >>
> >> 1) rename dp_utils_pack_sdp_header() to dp_utils_calc_sdp_parity()
> >> 2) dp_utils_pack_sdp() takes two u32 to pack the header and parity
> >> together and we move the << HEADER_BYTE_xx | part to it
> >>
> >> dp_catalog_panel_send_vsc_sdp() just uses these two u32 to write the
> >> headers.
> >
> > I'm really looking for the following function:
> >
> > void dp_catalog_panel_send_vsc_sdp(struct dp_catalog *dp_catalog,
> > struct dp_sdp *dp_sdp)
> > {
> >      dp_write_vsc_header(dp_catalog, MMSS_DP_GENERIC0_0, &dp_sdp->sdp_header);
> >      dp_write_vsc_packet(dp_catalog, MMSS_DP_GENERIC0_2, dp_sdp);
> > }
> >
> > Then dp_audio functions will be able to fill struct dp_sdp_header and
> > call dp_write_vsc_header (or whatever other name for that function)
> > directly.
> >
>
> I think there is some misunderstanding here.
>
> Audio does not write or use generic_0 registers. It uses audio infoframe
> SDP registers. So the catalog function of audio will not change.

Sure, that's why I added the register to the `dp_write_vsc_header` prototype.

E.g.:

void dp_audio_stream_sdp(...)
{
    struct dp_sdp_header hdr;
    hdr.HB0 = 0;
    hdr.HB1 = 0x2;
    hdr.HB2 = ...;
    hdr.HB3 = audio->nchannels - 1;
    dp_write_vsc_header(dp_catalog, MMSS_DP_AUDIO_STREAM_0, &hdr);
}


>
> The only part common between audio and vsc sdp is the parity byte
> calculation and the packing of parity and header bytes into 2 u32s.
>
> Thats why I wrote that we will have a common util between audio and vsc
> sdp only to pack the data but the catalog functions will be different.
>
>
> >>
> >>
> >>>> +
> >>>> +       val = ((msm_dp_sdp->vsc_sdp.db[16]) | (msm_dp_sdp->vsc_sdp.db[17] << 8) |
> >>>> +              (msm_dp_sdp->vsc_sdp.db[18] << 16));
> >>>> +       dp_write_link(catalog, MMSS_DP_GENERIC0_6, val);
> >>>
> >>> Shouldn't we write full dp_sdp data, including all zeroes? Here you
> >>> assume that there is no other data in dp_sdp and also that nobody
> >>> wrote anything senseless to those registers.
> >>>
> >>
> >> As per documentation, it says db[0] to db[15] are reserved so I thought
> >> its better not to touch/use them and start writing for 16 onwards.
> >>
> >> 1592  * VSC SDP Payload for Pixel Encoding/Colorimetry Format
> >> 1593  * db[0] - db[15]: Reserved
> >> 1594  * db[16]: Pixel Encoding and Colorimetry Formats
> >> 1595  * db[17]: Dynamic Range and Component Bit Depth
> >> 1596  * db[18]: Content Type
> >> 1597  * db[19] - db[31]: Reserved
> >> 1598  */
> >
> > If I understand correctly, it also supports 3D Stereo and other bits.
> > Also other revisions of VSC packets have other field requirements. So,
> > I don't think it is incorrect to write just bytes 16-18.
> >
>
> hmmm .... the packing function of vsc sdp does not consider 3D stereo
> bits today. But I guess if someone adds it later then we will not have
> to change this code if we write the rest of the payload as well.
>
> Okay, lets write all the 32 bytes of payload across to registers
> GENERIC0_2 to GENERIC0_9
>
>
> >>
> >>>> +}
> >>>> +
> >>>> +static void dp_catalog_panel_update_sdp(struct dp_catalog *dp_catalog)
> >>>> +{
> >>>> +       struct dp_catalog_private *catalog;
> >>>> +       u32 hw_revision;
> >>>> +
> >>>> +       catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
> >>>> +
> >>>> +       hw_revision = dp_catalog_hw_revision(dp_catalog);
> >>>> +       if (hw_revision < DP_HW_VERSION_1_2 && hw_revision >= DP_HW_VERSION_1_0) {
> >>>> +               dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x01);
> >>>> +               dp_write_link(catalog, MMSS_DP_SDP_CFG3, 0x00);
> >>>> +       }
> >>>> +}
> >>>> +
> >>>> +void dp_catalog_panel_enable_vsc_sdp(struct dp_catalog *dp_catalog,
> >>>> +                                    struct msm_dp_sdp_with_parity *msm_dp_sdp)
> >>>> +{
> >>>> +       struct dp_catalog_private *catalog;
> >>>> +       u32 cfg, cfg2, misc;
> >>>> +
> >>>> +       if (!dp_catalog) {
> >>>> +               DRM_ERROR("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);
> >>>> +
> >>>> +       cfg |= GEN0_SDP_EN;
> >>>> +       dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
> >>>> +
> >>>> +       cfg2 |= GENERIC0_SDPSIZE_VALID;
> >>>> +       dp_write_link(catalog, MMSS_DP_SDP_CFG2, cfg2);
> >>>> +
> >>>> +       dp_catalog_panel_send_vsc_sdp(dp_catalog, msm_dp_sdp);
> >>>> +
> >>>> +       /* indicates presence of VSC (BIT(6) of MISC1) */
> >>>> +       misc |= DP_MISC1_VSC_SDP;
> >>>> +
> >>>> +       drm_dbg_dp(catalog->drm_dev, "vsc sdp enable=1\n");
> >>>> +
> >>>> +       pr_debug("misc settings = 0x%x\n", misc);
> >>>> +       dp_write_link(catalog, REG_DP_MISC1_MISC0, misc);
> >>>> +
> >>>> +       dp_catalog_panel_update_sdp(dp_catalog);
> >>>> +}
> >>>> +
> >>>> +void dp_catalog_panel_disable_vsc_sdp(struct dp_catalog *dp_catalog)
> >>>> +{
> >>>> +       struct dp_catalog_private *catalog;
> >>>> +       u32 cfg, cfg2, misc;
> >>>> +
> >>>> +       if (!dp_catalog) {
> >>>> +               DRM_ERROR("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);
> >>>> +
> >>>> +       cfg &= ~GEN0_SDP_EN;
> >>>> +       dp_write_link(catalog, MMSS_DP_SDP_CFG, cfg);
> >>>> +
> >>>> +       cfg2 &= ~GENERIC0_SDPSIZE_VALID;
> >>>> +       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=0\n");
> >>>> +
> >>>> +       pr_debug("misc settings = 0x%x\n", misc);
> >>>> +       dp_write_link(catalog, REG_DP_MISC1_MISC0, misc);
> >>>> +
> >>>> +       dp_catalog_panel_update_sdp(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_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
> >>>> index 6cb5e2a243de2..4bf08c27a9bf3 100644
> >>>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.h
> >>>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
> >>>> @@ -9,6 +9,7 @@
> >>>>    #include <drm/drm_modes.h>
> >>>>
> >>>>    #include "dp_parser.h"
> >>>> +#include "dp_utils.h"
> >>>>    #include "disp/msm_disp_snapshot.h"
> >>>>
> >>>>    /* interrupts */
> >>>> @@ -30,6 +31,9 @@
> >>>>
> >>>>    #define DP_AUX_CFG_MAX_VALUE_CNT 3
> >>>>
> >>>> +#define DP_HW_VERSION_1_0      0x10000000
> >>>> +#define DP_HW_VERSION_1_2      0x10020000
> >>>> +
> >>>>    /* PHY AUX config registers */
> >>>>    enum dp_phy_aux_config_type {
> >>>>           PHY_AUX_CFG0,
> >>>> @@ -124,6 +128,9 @@ 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_enable_vsc_sdp(struct dp_catalog *dp_catalog,
> >>>> +                                    struct msm_dp_sdp_with_parity *msm_dp_sdp);
> >>>> +void dp_catalog_panel_disable_vsc_sdp(struct dp_catalog *dp_catalog);
> >>>>    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..beef86b1aaf81 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_disable_vsc_sdp(ctrl->catalog);
> >>>> +
> >>>>           /* 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_disable_vsc_sdp(ctrl->catalog);
> >>>> +
> >>>>           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 db1942794f1a4..18420a7ba4ab3 100644
> >>>> --- a/drivers/gpu/drm/msm/dp/dp_panel.c
> >>>> +++ b/drivers/gpu/drm/msm/dp/dp_panel.c
> >>>> @@ -4,6 +4,7 @@
> >>>>     */
> >>>>
> >>>>    #include "dp_panel.h"
> >>>> +#include "dp_utils.h"
> >>>>
> >>>>    #include <drm/drm_connector.h>
> >>>>    #include <drm/drm_edid.h>
> >>>> @@ -281,6 +282,56 @@ 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);
> >>>>    }
> >>>>
> >>>> +static int dp_panel_setup_vsc_sdp_yuv_420(struct dp_panel *dp_panel)
> >>>> +{
> >>>> +       struct dp_catalog *catalog;
> >>>> +       struct dp_panel_private *panel;
> >>>> +       struct dp_display_mode *dp_mode;
> >>>> +       struct drm_dp_vsc_sdp vsc_sdp_data;
> >>>> +       struct msm_dp_sdp_with_parity msm_dp_sdp;
> >>>> +       ssize_t len;
> >>>> +       int rc = 0;
> >>>> +
> >>>> +       if (!dp_panel) {
> >>>> +               DRM_ERROR("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(&vsc_sdp_data, 0, sizeof(vsc_sdp_data));
> >>>> +
> >>>> +       /* VSC SDP header as per table 2-118 of DP 1.4 specification */
> >>>> +       vsc_sdp_data.sdp_type = DP_SDP_VSC;
> >>>> +       vsc_sdp_data.revision = 0x05;
> >>>> +       vsc_sdp_data.length = 0x13;
> >>>> +
> >>>> +       /* VSC SDP Payload for DB16 */
> >>>> +       vsc_sdp_data.pixelformat = DP_PIXELFORMAT_YUV420;
> >>>> +       vsc_sdp_data.colorimetry = DP_COLORIMETRY_DEFAULT;
> >>>> +
> >>>> +       /* VSC SDP Payload for DB17 */
> >>>> +       vsc_sdp_data.bpc = dp_mode->bpp / 3;
> >>>> +       vsc_sdp_data.dynamic_range = DP_DYNAMIC_RANGE_CTA;
> >>>> +
> >>>> +       /* VSC SDP Payload for DB18 */
> >>>> +       vsc_sdp_data.content_type = DP_CONTENT_TYPE_GRAPHICS;
> >>>> +
> >>>> +       // rc = dp_utils_pack_vsc_sdp(&vsc_sdp_data, &sdp_header, gen_buffer, buff_size);
> >>>> +       len = dp_utils_pack_vsc_sdp(&vsc_sdp_data, &msm_dp_sdp);
> >>>> +       if (len < 0) {
> >>>> +               DRM_ERROR("unable to pack vsc sdp\n");
> >>>> +               return len;
> >>>> +       }
> >>>> +
> >>>> +       dp_catalog_panel_enable_vsc_sdp(catalog, &msm_dp_sdp);
> >>>> +
> >>>> +       return rc;
> >>>> +}
> >>>> +
> >>>>    void dp_panel_dump_regs(struct dp_panel *dp_panel)
> >>>>    {
> >>>>           struct dp_catalog *catalog;
> >>>> @@ -344,6 +395,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_yuv_420(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..2983756c125cd 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_VALID                 (0x00010000)
> >>>>
> >>>>    #define MMSS_DP_AUDIO_STREAM_0                 (0x00000240)
> >>>>    #define MMSS_DP_AUDIO_STREAM_1                 (0x00000244)
> >>>> diff --git a/drivers/gpu/drm/msm/dp/dp_utils.c b/drivers/gpu/drm/msm/dp/dp_utils.c
> >>>> index 3a44fe738c004..81601f3c414fc 100644
> >>>> --- a/drivers/gpu/drm/msm/dp/dp_utils.c
> >>>> +++ b/drivers/gpu/drm/msm/dp/dp_utils.c
> >>>> @@ -4,6 +4,7 @@
> >>>>     */
> >>>>
> >>>>    #include <linux/types.h>
> >>>> +#include <drm/drm_print.h>
> >>>>
> >>>>    #include "dp_utils.h"
> >>>>
> >>>> @@ -71,3 +72,50 @@ u8 dp_utils_calculate_parity(u32 data)
> >>>>
> >>>>           return parity_byte;
> >>>>    }
> >>>> +
> >>>> +ssize_t dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, struct msm_dp_vsc_sdp_parity *pb,
> >>>> +                                size_t size)
> >>>> +{
> >>>> +       u8 header;
> >>>> +
> >>>> +       size_t length = sizeof(struct msm_dp_vsc_sdp_parity);
> >>>> +
> >>>> +       if (size < length)
> >>>> +               return -ENOSPC;
> >>>> +
> >>>> +       memset(pb, 0, size);
> >>>> +
> >>>> +       header = sdp_header->HB0;
> >>>> +       pb->PB0 = dp_utils_calculate_parity(header);
> >>>> +
> >>>> +       header = sdp_header->HB1;
> >>>> +       pb->PB1 = dp_utils_calculate_parity(header);
> >>>> +
> >>>> +       header = sdp_header->HB2;
> >>>> +       pb->PB2 = dp_utils_calculate_parity(header);
> >>>> +
> >>>> +       header = sdp_header->HB3;
> >>>> +       pb->PB3 = dp_utils_calculate_parity(header);
> >>>> +
> >>>> +       return length;
> >>>> +}
> >>>> +
> >>>> +ssize_t dp_utils_pack_vsc_sdp(struct drm_dp_vsc_sdp *vsc, struct msm_dp_sdp_with_parity *msm_dp_sdp)
> >>>> +{
> >>>> +       ssize_t len;
> >>>> +
> >>>> +       len = drm_dp_vsc_sdp_pack(vsc, &msm_dp_sdp->vsc_sdp, sizeof(msm_dp_sdp->vsc_sdp));
> >>>> +       if (len < 0) {
> >>>> +               DRM_ERROR("unable to pack vsc sdp\n");
> >>>> +               return len;
> >>>> +       }
> >>>> +
> >>>> +       len = dp_utils_pack_sdp_header(&msm_dp_sdp->vsc_sdp.sdp_header, &msm_dp_sdp->pb,
> >>>> +                                      sizeof(msm_dp_sdp->pb));
> >>>> +       if (len < 0) {
> >>>> +               DRM_ERROR("unable to pack sdp header\n");
> >>>> +               return len;
> >>>> +       }
> >>>> +
> >>>> +       return len;
> >>>> +}
> >>>> diff --git a/drivers/gpu/drm/msm/dp/dp_utils.h b/drivers/gpu/drm/msm/dp/dp_utils.h
> >>>> index 5a505cbf3432b..6946bc51cae97 100644
> >>>> --- a/drivers/gpu/drm/msm/dp/dp_utils.h
> >>>> +++ b/drivers/gpu/drm/msm/dp/dp_utils.h
> >>>> @@ -6,6 +6,8 @@
> >>>>    #ifndef _DP_UTILS_H_
> >>>>    #define _DP_UTILS_H_
> >>>>
> >>>> +#include <drm/display/drm_dp_helper.h>
> >>>> +
> >>>>    #define HEADER_BYTE_0_BIT       0
> >>>>    #define PARITY_BYTE_0_BIT       8
> >>>>    #define HEADER_BYTE_1_BIT      16
> >>>> @@ -15,8 +17,24 @@
> >>>>    #define HEADER_BYTE_3_BIT      16
> >>>>    #define PARITY_BYTE_3_BIT      24
> >>>>
> >>>> +struct msm_dp_vsc_sdp_parity {
> >>>> +       u8 PB0;
> >>>> +       u8 PB1;
> >>>> +       u8 PB2;
> >>>> +       u8 PB3;
> >>>> +} __packed;
> >>>> +
> >>>> +struct msm_dp_sdp_with_parity {
> >>>> +       struct dp_sdp vsc_sdp;
> >>>> +       struct msm_dp_vsc_sdp_parity pb;
> >>>> +};
> >>>> +
> >>>>    u8 dp_utils_get_g0_value(u8 data);
> >>>>    u8 dp_utils_get_g1_value(u8 data);
> >>>>    u8 dp_utils_calculate_parity(u32 data);
> >>>> +ssize_t dp_utils_pack_sdp_header(struct dp_sdp_header *sdp_header, struct msm_dp_vsc_sdp_parity *pb,
> >>>> +                                size_t size);
> >>>> +ssize_t dp_utils_pack_vsc_sdp(struct drm_dp_vsc_sdp *vsc,
> >>>> +                             struct msm_dp_sdp_with_parity *msm_dp_sdp);
> >>>>
> >>>>    #endif /* _DP_UTILS_H_ */
> >>>> --
> >>>> 2.39.2
> >>>>
> >>>
> >>>
> >
> >
> >



-- 
With best wishes
Dmitry

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

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


On 2/15/2024 7:47 AM, Abhinav Kumar wrote:
>
>
> On 2/15/2024 12:45 AM, Dmitry Baryshkov wrote:
>> On Wed, 14 Feb 2024 at 20:04, Paloma Arellano 
>> <quic_parellan@quicinc.com> wrote:
>>>
>>> Adjust the encoder format programming in the case of video mode for DP
>>> to accommodate CDM related changes.
>>>
>>> Changes in v2:
>>>          - Move timing engine programming to a separate patch from this
>>>            one
>>>          - Move update_pending_flush_periph() invocation completely to
>>>            this patch
>>>          - Change the logic of dpu_encoder_get_drm_fmt() so that it 
>>> only
>>>            calls drm_mode_is_420_only() instead of doing additional
>>>            unnecessary checks
>>>          - Create new functions msm_dp_needs_periph_flush() and it's
>>>            supporting function dpu_encoder_needs_periph_flush() to 
>>> check
>>>            if the mode is YUV420 and VSC SDP is enabled before doing a
>>>            peripheral flush
>>>
>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
>>> ---
>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 35 
>>> +++++++++++++++++++
>>>   .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  | 13 +++++++
>>>   .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 19 ++++++++++
>>>   drivers/gpu/drm/msm/dp/dp_display.c           | 18 ++++++++++
>>>   drivers/gpu/drm/msm/msm_drv.h                 | 17 ++++++++-
>>>   5 files changed, 101 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>> index 7e7796561009a..6280c6be6dca9 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>> @@ -222,6 +222,41 @@ 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(struct dpu_encoder_phys *phys_enc)
>>> +{
>>> +       struct drm_encoder *drm_enc;
>>> +       struct dpu_encoder_virt *dpu_enc;
>>> +       struct drm_display_info *info;
>>> +       struct drm_display_mode *mode;
>>> +
>>> +       drm_enc = phys_enc->parent;
>>> +       dpu_enc = to_dpu_encoder_virt(drm_enc);
>>> +       info = &dpu_enc->connector->display_info;
>>> +       mode = &phys_enc->cached_mode;
>>> +
>>> +       if (drm_mode_is_420_only(info, mode))
>>> +               return DRM_FORMAT_YUV420;
>>> +
>>> +       return DRM_FORMAT_RGB888;
>>> +}
>>> +
>>> +bool dpu_encoder_needs_periph_flush(struct dpu_encoder_phys *phys_enc)
>>> +{
>>> +       struct drm_encoder *drm_enc;
>>> +       struct dpu_encoder_virt *dpu_enc;
>>> +       struct msm_display_info *disp_info;
>>> +       struct msm_drm_private *priv;
>>> +       struct drm_display_mode *mode;
>>> +
>>> +       drm_enc = phys_enc->parent;
>>> +       dpu_enc = to_dpu_encoder_virt(drm_enc);
>>> +       disp_info = &dpu_enc->disp_info;
>>> +       priv = drm_enc->dev->dev_private;
>>> +       mode = &phys_enc->cached_mode;
>>> +
>>> +       return phys_enc->hw_intf->cap->type == INTF_DP && 
>>> phys_enc->hw_cdm &&
>>> + msm_dp_needs_periph_flush(priv->dp[disp_info->h_tile_instance[0]], 
>>> mode);
>>> +}
>>>
>>>   bool dpu_encoder_is_widebus_enabled(const struct drm_encoder 
>>> *drm_enc)
>>>   {
>>> 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 f43d57d9c74e1..211a3d90eb690 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>>> @@ -341,6 +341,19 @@ static inline enum dpu_3d_blend_mode 
>>> dpu_encoder_helper_get_3d_blend_mode(
>>>    */
>>>   unsigned int dpu_encoder_helper_get_dsc(struct dpu_encoder_phys 
>>> *phys_enc);
>>>
>>> +/**
>>> + * dpu_encoder_get_drm_fmt - return DRM fourcc format
>>> + * @phys_enc: Pointer to physical encoder structure
>>> + */
>>> +u32 dpu_encoder_get_drm_fmt(struct dpu_encoder_phys *phys_enc);
>>> +
>>> +/**
>>> + * dpu_encoder_needs_periph_flush - return true if physical encoder 
>>> requires
>>> + *     peripheral flush
>>> + * @phys_enc: Pointer to physical encoder structure
>>> + */
>>> +bool dpu_encoder_needs_periph_flush(struct dpu_encoder_phys 
>>> *phys_enc);
>>> +
>>>   /**
>>>    * dpu_encoder_helper_split_config - split display configuration 
>>> helper function
>>>    *     This helper function may be used by physical encoders to 
>>> configure
>>> 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 f02411b062c4c..e29bc4bd39208 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
>>> @@ -415,8 +415,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)
>>
>> I thought that Abhinav proposed to drop the if(hw_cdm) condition here.
>> LGTM otherwise.
>>
>
> Yes I did.
>
> This needs to be fixed in v4.


Ack, I must have forgotten to drop it, but I'll do it in the v4

>
>>> +               fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc);
>>> +       fmt = dpu_get_dpu_format(fmt_fourcc);
>>>
>>>          DPU_DEBUG_VIDENC(phys_enc, "\n");
>>>
>>> @@ -425,6 +432,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);
>>>
>>>          /*
>>> @@ -440,6 +449,16 @@ 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_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 && 
>>> dpu_encoder_needs_periph_flush(phys_enc))
>>> +               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/dp/dp_display.c 
>>> b/drivers/gpu/drm/msm/dp/dp_display.c
>>> index 4b04388719363..ebcc76ef1d590 100644
>>> --- a/drivers/gpu/drm/msm/dp/dp_display.c
>>> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
>>> @@ -1397,6 +1397,24 @@ 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 && 
>>> drm_mode_is_420_only(info, mode);
>>> +}
>>> +
>>> +bool msm_dp_needs_periph_flush(const struct msm_dp *dp_display,
>>> +                              const struct drm_display_mode *mode)
>>> +{
>>> +       return msm_dp_is_yuv_420_enabled(dp_display, 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..b876ebd48effe 100644
>>> --- a/drivers/gpu/drm/msm/msm_drv.h
>>> +++ b/drivers/gpu/drm/msm/msm_drv.h
>>> @@ -387,7 +387,10 @@ 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_needs_periph_flush(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 +412,18 @@ 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_needs_periph_flush(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	[flat|nested] 33+ messages in thread

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

On Thu, 15 Feb 2024 at 19:03, Dmitry Baryshkov
<dmitry.baryshkov@linaro.org> wrote:
>
> On Thu, 15 Feb 2024 at 18:39, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >
> >
> >
> > On 2/15/2024 12:40 AM, Dmitry Baryshkov wrote:
> > > On Wed, 14 Feb 2024 at 22:15, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> > >>
> > >>
> > >>
> > >> On 2/14/2024 11:39 AM, Dmitry Baryshkov wrote:
> > >>> On Wed, 14 Feb 2024 at 20:04, Paloma Arellano <quic_parellan@quicinc.com> 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.
> > >>>>
> > >>>> Changes in v3:
> > >>>>           - Create a new struct, msm_dp_sdp_with_parity, which holds the
> > >>>>             packing information for VSC SDP
> > >>>>           - Use drm_dp_vsc_sdp_pack() to pack the data into the new
> > >>>>             msm_dp_sdp_with_parity struct instead of specifically packing
> > >>>>             for YUV420 format
> > >>>>           - Modify dp_catalog_panel_send_vsc_sdp() to send the VSC SDP
> > >>>>             data using the new msm_dp_sdp_with_parity struct
> > >>>>
> > >>>> Changes in v2:
> > >>>>           - Rename GENERIC0_SDPSIZE macro to GENERIC0_SDPSIZE_VALID
> > >>>>           - Remove dp_sdp from the dp_catalog struct since this data is
> > >>>>             being allocated at the point used
> > >>>>           - Create a new function in dp_utils to pack the VSC SDP data
> > >>>>             into a buffer
> > >>>>           - Create a new function that packs the SDP header bytes into a
> > >>>>             buffer. This function is made generic so that it can be
> > >>>>             utilized by dp_audio
> > >>>>             header bytes into a buffer
> > >>>>           - Create a new function in dp_utils that takes the packed buffer
> > >>>>             and writes to the DP_GENERIC0_* registers
> > >>>>           - Split the dp_catalog_panel_config_vsc_sdp() function into two
> > >>>>             to disable/enable sending VSC SDP packets
> > >>>>           - Check the DP HW version using the original useage of
> > >>>>             dp_catalog_hw_revision() and correct the version checking
> > >>>>             logic
> > >>>>           - Rename dp_panel_setup_vsc_sdp() to
> > >>>>             dp_panel_setup_vsc_sdp_yuv_420() to explicitly state that
> > >>>>             currently VSC SDP is only being set up to support YUV420 modes
> > >>>>
> > >>>> Signed-off-by: Paloma Arellano <quic_parellan@quicinc.com>
> > >>>> ---
> > >>>>    drivers/gpu/drm/msm/dp/dp_catalog.c | 113 ++++++++++++++++++++++++++++
> > >>>>    drivers/gpu/drm/msm/dp/dp_catalog.h |   7 ++
> > >>>>    drivers/gpu/drm/msm/dp/dp_ctrl.c    |   4 +
> > >>>>    drivers/gpu/drm/msm/dp/dp_panel.c   |  55 ++++++++++++++
> > >>>>    drivers/gpu/drm/msm/dp/dp_reg.h     |   3 +
> > >>>>    drivers/gpu/drm/msm/dp/dp_utils.c   |  48 ++++++++++++
> > >>>>    drivers/gpu/drm/msm/dp/dp_utils.h   |  18 +++++
> > >>>>    7 files changed, 248 insertions(+)
> > >>>>
> > >>>> diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
> > >>>> index 5d84c089e520a..61d5317efe683 100644
> > >>>> --- a/drivers/gpu/drm/msm/dp/dp_catalog.c
> > >>>> +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
> > >>>> @@ -901,6 +901,119 @@ int dp_catalog_panel_timing_cfg(struct dp_catalog *dp_catalog)
> > >>>>           return 0;
> > >>>>    }
> > >>>>
> > >>>> +static void dp_catalog_panel_send_vsc_sdp(struct dp_catalog *dp_catalog,
> > >>>> +                                         struct msm_dp_sdp_with_parity *msm_dp_sdp)
> > >>>> +{
> > >>>> +       struct dp_catalog_private *catalog;
> > >>>> +       u32 val;
> > >>>> +
> > >>>> +       if (!dp_catalog) {
> > >>>> +               DRM_ERROR("invalid input\n");
> > >>>> +               return;
> > >>>> +       }
> > >>>> +
> > >>>> +       catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog);
> > >>>> +
> > >>>> +       val = ((msm_dp_sdp->vsc_sdp.sdp_header.HB0) << HEADER_BYTE_0_BIT |
> > >>>> +              (msm_dp_sdp->pb.PB0 << PARITY_BYTE_0_BIT) |
> > >>>> +              (msm_dp_sdp->vsc_sdp.sdp_header.HB1) << HEADER_BYTE_1_BIT |
> > >>>> +              (msm_dp_sdp->pb.PB1 << PARITY_BYTE_1_BIT));
> > >>>> +       dp_write_link(catalog, MMSS_DP_GENERIC0_0, val);
> > >>>> +
> > >>>> +       val = ((msm_dp_sdp->vsc_sdp.sdp_header.HB2) << HEADER_BYTE_2_BIT |
> > >>>> +              (msm_dp_sdp->pb.PB2 << PARITY_BYTE_2_BIT) |
> > >>>> +              (msm_dp_sdp->vsc_sdp.sdp_header.HB3) << HEADER_BYTE_3_BIT |
> > >>>> +              (msm_dp_sdp->pb.PB3 << PARITY_BYTE_3_BIT));
> > >>>> +       dp_write_link(catalog, MMSS_DP_GENERIC0_1, val);
> > >>>
> > >>> I still think that this is not the way to do it. Could you please
> > >>> extract the function that takes struct dp_sdp_header, calculates
> > >>> padding and writes resulting data to the hardware? This way we can
> > >>> reuse it later for all the dp_audio stuff.
> > >>>
> > >>
> > >> hmmm ... dp_utils_pack_sdp_header() does that you are asking for right?
> > >>
> > >> OR are you asking for another function like:
> > >>
> > >> 1) rename dp_utils_pack_sdp_header() to dp_utils_calc_sdp_parity()
> > >> 2) dp_utils_pack_sdp() takes two u32 to pack the header and parity
> > >> together and we move the << HEADER_BYTE_xx | part to it
> > >>
> > >> dp_catalog_panel_send_vsc_sdp() just uses these two u32 to write the
> > >> headers.
> > >
> > > I'm really looking for the following function:
> > >
> > > void dp_catalog_panel_send_vsc_sdp(struct dp_catalog *dp_catalog,
> > > struct dp_sdp *dp_sdp)
> > > {
> > >      dp_write_vsc_header(dp_catalog, MMSS_DP_GENERIC0_0, &dp_sdp->sdp_header);
> > >      dp_write_vsc_packet(dp_catalog, MMSS_DP_GENERIC0_2, dp_sdp);
> > > }
> > >
> > > Then dp_audio functions will be able to fill struct dp_sdp_header and
> > > call dp_write_vsc_header (or whatever other name for that function)
> > > directly.
> > >
> >
> > I think there is some misunderstanding here.
> >
> > Audio does not write or use generic_0 registers. It uses audio infoframe
> > SDP registers. So the catalog function of audio will not change.
>
> Sure, that's why I added the register to the `dp_write_vsc_header` prototype.
>
> E.g.:
>
> void dp_audio_stream_sdp(...)
> {
>     struct dp_sdp_header hdr;
>     hdr.HB0 = 0;
>     hdr.HB1 = 0x2;
>     hdr.HB2 = ...;
>     hdr.HB3 = audio->nchannels - 1;
>     dp_write_vsc_header(dp_catalog, MMSS_DP_AUDIO_STREAM_0, &hdr);
> }
>
>
> >
> > The only part common between audio and vsc sdp is the parity byte
> > calculation and the packing of parity and header bytes into 2 u32s.
> >
> > Thats why I wrote that we will have a common util between audio and vsc
> > sdp only to pack the data but the catalog functions will be different.
> >

After an offline discussion, let's start with the dp_util function
packing struct dp_sdp_header into u32[2], then we can decide on the
fate of the dp_audio stuff later on.


-- 
With best wishes
Dmitry

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

end of thread, other threads:[~2024-02-15 18:40 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-02-14 18:03 [PATCH v3 00/19] Add support for CDM over DP Paloma Arellano
2024-02-14 18:03 ` [PATCH v3 01/19] drm/msm/dpu: allow certain formats for CDM for DP Paloma Arellano
2024-02-14 18:03 ` [PATCH v3 02/19] drm/msm/dpu: add division of drm_display_mode's hskew parameter Paloma Arellano
2024-02-15  8:56   ` Dmitry Baryshkov
2024-02-14 18:03 ` [PATCH v3 03/19] drm/msm/dpu: pass mode dimensions instead of fb size in CDM setup Paloma Arellano
2024-02-14 18:03 ` [PATCH v3 04/19] drm/msm/dpu: allow dpu_encoder_helper_phys_setup_cdm to work for DP Paloma Arellano
2024-02-14 18:03 ` [PATCH v3 05/19] drm/msm/dpu: move dpu_encoder_helper_phys_setup_cdm to dpu_encoder Paloma Arellano
2024-02-14 18:03 ` [PATCH v3 06/19] drm/msm/dp: rename wide_bus_en to wide_bus_supported Paloma Arellano
2024-02-14 18:03 ` [PATCH v3 07/19] drm/msm/dp: store mode YUV420 information to be used by rest of DP Paloma Arellano
2024-02-14 18:03 ` [PATCH v3 08/19] drm/msm/dp: check if VSC SDP is supported in DP programming Paloma Arellano
2024-02-14 18:03 ` [PATCH v3 09/19] drm/msm/dpu: move widebus logic to its own API Paloma Arellano
2024-02-14 18:03 ` [PATCH v3 10/19] drm/msm/dp: program config ctrl for YUV420 over DP Paloma Arellano
2024-02-14 18:03 ` [PATCH v3 11/19] drm/msm/dp: change clock related programming " Paloma Arellano
2024-02-14 18:03 ` [PATCH v3 12/19] drm/msm/dp: move parity calculation to dp_utils Paloma Arellano
2024-02-14 18:03 ` [PATCH v3 13/19] drm/msm/dp: add VSC SDP support for YUV420 over DP Paloma Arellano
2024-02-14 19:39   ` Dmitry Baryshkov
2024-02-14 20:15     ` Abhinav Kumar
2024-02-15  8:40       ` Dmitry Baryshkov
2024-02-15 16:39         ` Abhinav Kumar
2024-02-15 17:03           ` Dmitry Baryshkov
2024-02-15 18:40             ` Dmitry Baryshkov
2024-02-14 18:03 ` [PATCH v3 14/19] drm/msm/dpu: add support of new peripheral flush mechanism Paloma Arellano
2024-02-14 18:03 ` [PATCH v3 15/19] drm/msm/dp: enable SDP and SDE periph flush update Paloma Arellano
2024-02-14 19:41   ` Dmitry Baryshkov
2024-02-14 18:03 ` [PATCH v3 16/19] drm/msm/dpu: modify encoder programming for CDM over DP Paloma Arellano
2024-02-15  8:45   ` Dmitry Baryshkov
2024-02-15 15:47     ` Abhinav Kumar
2024-02-15 18:37       ` Paloma Arellano
2024-02-14 18:03 ` [PATCH v3 17/19] drm/msm/dpu: modify timing engine programming for YUV420 " Paloma Arellano
2024-02-15  8:55   ` Dmitry Baryshkov
2024-02-14 18:03 ` [PATCH v3 18/19] drm/msm/dpu: reserve CDM blocks for DP if mode is YUV420 Paloma Arellano
2024-02-14 18:03 ` [PATCH v3 19/19] drm/msm/dp: allow YUV420 mode for DP connector when CDM available Paloma Arellano
2024-02-15  8:57   ` Dmitry Baryshkov

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).