All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/16] Add CDM support for MSM writeback
@ 2023-08-30 22:48 Abhinav Kumar
  2023-08-30 22:48   ` Abhinav Kumar
                   ` (15 more replies)
  0 siblings, 16 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:48 UTC (permalink / raw)
  To: freedreno
  Cc: quic_jesszhan, quic_parellan, Abhinav Kumar, dri-devel, quic_khsieh

Chroma Down Sampling (CDM) block is a hardware block in the DPU pipeline
which among other things has a CSC block that can convert RGB input
from the DPU to YUV data.

This block can be used with either HDMI, DP or writeback interface.

In this series, lets first add the support for CDM block to be used
with writeback and then follow-up with support for other interfaces such
as DP.

This was validated by adding support to pass custom output format to the
IGT's kms_writeback test-case, specifically only for the output dump
test-case [1].

The usage for this is:

./kms_writeback -d -f <name of the DRM YUV fmt from igt_fb>

So for NV12, this can be verified with the below command:

./kms_writeback -d -f NV12

[1] : https://patchwork.freedesktop.org/series/122125/


Abhinav Kumar (16):
  drm/msm/dpu: fix writeback programming for YUV cases
  drm/msm/dpu: add formats check for writeback encoder
  drm/msm/dpu: rename dpu_encoder_phys_wb_setup_cdp to match its
    functionality
  drm/msm/dpu: add cdm blocks to sc7280 dpu_hw_catalog
  drm/msm/dpu: add cdm blocks to sm8250 dpu_hw_catalog
  drm/msm/dpu: add dpu_hw_cdm abstraction for CDM block
  drm/msm/dpu: add cdm blocks to RM
  drm/msm/dpu: add support to allocate CDM from RM
  drm/msm/dpu: add CDM related logic to dpu_hw_ctl layer
  drm/msm/dpu: add support to disable CDM block during encoder cleanup
  drm/msm/dpu: add an API to setup the CDM block for writeback
  drm/msm/dpu: plug-in the cdm related bits to writeback setup
  drm/msm/dpu: reserve cdm blocks for writeback in case of YUV output
  drm/msm/dpu: do not allow YUV formats if no CDM block is present
  drm/msm/dpu: add NV12 in the list of supported WB formats
  drm/msm/dpu: add cdm blocks to dpu snapshot

 drivers/gpu/drm/msm/Makefile                  |   1 +
 .../msm/disp/dpu1/catalog/dpu_6_0_sm8250.h    |   9 +
 .../msm/disp/dpu1/catalog/dpu_7_2_sc7280.h    |   9 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   |  43 ++-
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   5 +
 .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 150 +++++++++-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c    |   1 +
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |  13 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c    | 272 ++++++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h    | 135 +++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c    |  34 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h    |  11 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |   7 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c     |   3 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c       |   4 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h       |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c        |  62 +++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h        |   6 +-
 18 files changed, 758 insertions(+), 8 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h

-- 
2.40.1


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

* [PATCH 01/16] drm/msm/dpu: fix writeback programming for YUV cases
  2023-08-30 22:48 [PATCH 00/16] Add CDM support for MSM writeback Abhinav Kumar
@ 2023-08-30 22:48   ` Abhinav Kumar
  2023-08-30 22:48   ` Abhinav Kumar
                     ` (14 subsequent siblings)
  15 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:48 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: dri-devel, quic_jesszhan, quic_parellan, quic_khsieh,
	linux-arm-msm, linux-kernel

For YUV cases, setting the required format bits was missed
out in the register programming. Lets fix it now in preparation
of adding YUV formats support for writeback.

Fixes: 84a33d0fd921 ("drm/msm/dpu: add dpu_hw_wb abstraction for writeback blocks")
Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
index ebc416400382..0aa598b355e9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
@@ -86,6 +86,9 @@ static void dpu_hw_wb_setup_format(struct dpu_hw_wb *ctx,
 			dst_format |= BIT(14); /* DST_ALPHA_X */
 	}
 
+	if (DPU_FORMAT_IS_YUV(fmt))
+		dst_format |= BIT(15);
+
 	pattern = (fmt->element[3] << 24) |
 		(fmt->element[2] << 16) |
 		(fmt->element[1] << 8)  |
-- 
2.40.1


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

* [PATCH 01/16] drm/msm/dpu: fix writeback programming for YUV cases
@ 2023-08-30 22:48   ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:48 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan

For YUV cases, setting the required format bits was missed
out in the register programming. Lets fix it now in preparation
of adding YUV formats support for writeback.

Fixes: 84a33d0fd921 ("drm/msm/dpu: add dpu_hw_wb abstraction for writeback blocks")
Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
index ebc416400382..0aa598b355e9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
@@ -86,6 +86,9 @@ static void dpu_hw_wb_setup_format(struct dpu_hw_wb *ctx,
 			dst_format |= BIT(14); /* DST_ALPHA_X */
 	}
 
+	if (DPU_FORMAT_IS_YUV(fmt))
+		dst_format |= BIT(15);
+
 	pattern = (fmt->element[3] << 24) |
 		(fmt->element[2] << 16) |
 		(fmt->element[1] << 8)  |
-- 
2.40.1


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

* [PATCH 02/16] drm/msm/dpu: add formats check for writeback encoder
  2023-08-30 22:48 [PATCH 00/16] Add CDM support for MSM writeback Abhinav Kumar
@ 2023-08-30 22:48   ` Abhinav Kumar
  2023-08-30 22:48   ` Abhinav Kumar
                     ` (14 subsequent siblings)
  15 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:48 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: dri-devel, quic_jesszhan, quic_parellan, quic_khsieh,
	linux-arm-msm, linux-kernel

In preparation of adding more formats to dpu writeback add
format validation to it to fail any unsupported formats.

Fixes: d7d0e73f7de3 ("drm/msm/dpu: introduce the dpu_encoder_phys_* for writeback")
Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 7 +++++++
 1 file changed, 7 insertions(+)

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 284a88060221..6a1f8e34f18a 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
@@ -238,6 +238,7 @@ static int dpu_encoder_phys_wb_atomic_check(
 {
 	struct drm_framebuffer *fb;
 	const struct drm_display_mode *mode = &crtc_state->mode;
+	int ret;
 
 	DPU_DEBUG("[atomic_check:%d, \"%s\",%d,%d]\n",
 			phys_enc->hw_wb->idx, mode->name, mode->hdisplay, mode->vdisplay);
@@ -274,6 +275,12 @@ static int dpu_encoder_phys_wb_atomic_check(
 		return -EINVAL;
 	}
 
+	ret = drm_atomic_helper_check_wb_encoder_state(phys_enc->parent, conn_state);
+	if (ret < 0) {
+		DPU_ERROR("invalid pixel format %p4cc\n", &fb->format->format);
+		return ret;
+	}
+
 	return 0;
 }
 
-- 
2.40.1


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

* [PATCH 02/16] drm/msm/dpu: add formats check for writeback encoder
@ 2023-08-30 22:48   ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:48 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan

In preparation of adding more formats to dpu writeback add
format validation to it to fail any unsupported formats.

Fixes: d7d0e73f7de3 ("drm/msm/dpu: introduce the dpu_encoder_phys_* for writeback")
Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 7 +++++++
 1 file changed, 7 insertions(+)

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 284a88060221..6a1f8e34f18a 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
@@ -238,6 +238,7 @@ static int dpu_encoder_phys_wb_atomic_check(
 {
 	struct drm_framebuffer *fb;
 	const struct drm_display_mode *mode = &crtc_state->mode;
+	int ret;
 
 	DPU_DEBUG("[atomic_check:%d, \"%s\",%d,%d]\n",
 			phys_enc->hw_wb->idx, mode->name, mode->hdisplay, mode->vdisplay);
@@ -274,6 +275,12 @@ static int dpu_encoder_phys_wb_atomic_check(
 		return -EINVAL;
 	}
 
+	ret = drm_atomic_helper_check_wb_encoder_state(phys_enc->parent, conn_state);
+	if (ret < 0) {
+		DPU_ERROR("invalid pixel format %p4cc\n", &fb->format->format);
+		return ret;
+	}
+
 	return 0;
 }
 
-- 
2.40.1


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

* [PATCH 03/16] drm/msm/dpu: rename dpu_encoder_phys_wb_setup_cdp to match its functionality
  2023-08-30 22:48 [PATCH 00/16] Add CDM support for MSM writeback Abhinav Kumar
@ 2023-08-30 22:48   ` Abhinav Kumar
  2023-08-30 22:48   ` Abhinav Kumar
                     ` (14 subsequent siblings)
  15 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:48 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: dri-devel, quic_jesszhan, quic_parellan, quic_khsieh,
	linux-arm-msm, linux-kernel

dpu_encoder_phys_wb_setup_cdp() is not programming the chroma down
prefetch block. Its setting up the display ctl path for writeback.

Hence rename it to dpu_encoder_phys_wb_setup_ctl() to match what its
actually doing.

Fixes: d7d0e73f7de3 ("drm/msm/dpu: introduce the dpu_encoder_phys_* for writeback")
Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 6 +++---
 1 file changed, 3 insertions(+), 3 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 6a1f8e34f18a..4c2736c3ee6d 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
@@ -173,10 +173,10 @@ static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc,
 }
 
 /**
- * dpu_encoder_phys_wb_setup_cdp - setup chroma down prefetch block
+ * dpu_encoder_phys_wb_setup_ctl - setup wb pipeline for ctl path
  * @phys_enc:Pointer to physical encoder
  */
-static void dpu_encoder_phys_wb_setup_cdp(struct dpu_encoder_phys *phys_enc)
+static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
 {
 	struct dpu_hw_wb *hw_wb;
 	struct dpu_hw_ctl *ctl;
@@ -348,7 +348,7 @@ static void dpu_encoder_phys_wb_setup(
 
 	dpu_encoder_phys_wb_setup_fb(phys_enc, fb);
 
-	dpu_encoder_phys_wb_setup_cdp(phys_enc);
+	dpu_encoder_phys_wb_setup_ctl(phys_enc);
 
 }
 
-- 
2.40.1


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

* [PATCH 03/16] drm/msm/dpu: rename dpu_encoder_phys_wb_setup_cdp to match its functionality
@ 2023-08-30 22:48   ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:48 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan

dpu_encoder_phys_wb_setup_cdp() is not programming the chroma down
prefetch block. Its setting up the display ctl path for writeback.

Hence rename it to dpu_encoder_phys_wb_setup_ctl() to match what its
actually doing.

Fixes: d7d0e73f7de3 ("drm/msm/dpu: introduce the dpu_encoder_phys_* for writeback")
Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 6 +++---
 1 file changed, 3 insertions(+), 3 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 6a1f8e34f18a..4c2736c3ee6d 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
@@ -173,10 +173,10 @@ static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc,
 }
 
 /**
- * dpu_encoder_phys_wb_setup_cdp - setup chroma down prefetch block
+ * dpu_encoder_phys_wb_setup_ctl - setup wb pipeline for ctl path
  * @phys_enc:Pointer to physical encoder
  */
-static void dpu_encoder_phys_wb_setup_cdp(struct dpu_encoder_phys *phys_enc)
+static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
 {
 	struct dpu_hw_wb *hw_wb;
 	struct dpu_hw_ctl *ctl;
@@ -348,7 +348,7 @@ static void dpu_encoder_phys_wb_setup(
 
 	dpu_encoder_phys_wb_setup_fb(phys_enc, fb);
 
-	dpu_encoder_phys_wb_setup_cdp(phys_enc);
+	dpu_encoder_phys_wb_setup_ctl(phys_enc);
 
 }
 
-- 
2.40.1


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

* [PATCH 04/16] drm/msm/dpu: add cdm blocks to sc7280 dpu_hw_catalog
  2023-08-30 22:48 [PATCH 00/16] Add CDM support for MSM writeback Abhinav Kumar
@ 2023-08-30 22:48   ` Abhinav Kumar
  2023-08-30 22:48   ` Abhinav Kumar
                     ` (14 subsequent siblings)
  15 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:48 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: dri-devel, quic_jesszhan, quic_parellan, quic_khsieh,
	linux-arm-msm, linux-kernel

Add CDM blocks to the sc7280 dpu_hw_catalog to support
YUV format output from writeback block.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 .../gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h  |  9 +++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h      | 13 +++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h         |  5 +++++
 3 files changed, 27 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
index 3b5061c4402a..5252170f216d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
@@ -251,10 +251,19 @@ static const struct dpu_mdss_version sc7280_mdss_ver = {
 	.core_minor_ver = 2,
 };
 
+static const struct dpu_cdm_cfg sc7280_cdm = {
+	.name = "cdm_0",
+	.id = CDM_0,
+	.len = 0x228,
+	.base = 0x79200,
+	.features = 0,
+};
+
 const struct dpu_mdss_cfg dpu_sc7280_cfg = {
 	.mdss_ver = &sc7280_mdss_ver,
 	.caps = &sc7280_dpu_caps,
 	.mdp = &sc7280_mdp,
+	.cdm = &sc7280_cdm,
 	.ctl_count = ARRAY_SIZE(sc7280_ctl),
 	.ctl = sc7280_ctl,
 	.sspp_count = ARRAY_SIZE(sc7280_sspp),
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index 6c9634209e9f..4ea7c3f85a95 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -693,6 +693,17 @@ struct dpu_vbif_cfg {
 	u32 memtype[MAX_XIN_COUNT];
 };
 
+/**
+ * struct dpu_cdm_cfg - information of chroma down blocks
+ * @name               string name for debug purposes
+ * @id                 enum identifying this block
+ * @base               register offset of this block
+ * @features           bit mask identifying sub-blocks/features
+ */
+struct dpu_cdm_cfg {
+	DPU_HW_BLK_INFO;
+};
+
 /**
  * Define CDP use cases
  * @DPU_PERF_CDP_UDAGE_RT: real-time use cases
@@ -816,6 +827,8 @@ struct dpu_mdss_cfg {
 	u32 wb_count;
 	const struct dpu_wb_cfg *wb;
 
+	const struct dpu_cdm_cfg *cdm;
+
 	u32 ad_count;
 
 	u32 dspp_count;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
index d85157acfbf8..4d6dba18caf0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -185,6 +185,11 @@ enum dpu_dsc {
 	DSC_MAX
 };
 
+enum dpu_cdm {
+	CDM_0 = 1,
+	CDM_MAX
+};
+
 enum dpu_pingpong {
 	PINGPONG_NONE,
 	PINGPONG_0,
-- 
2.40.1


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

* [PATCH 04/16] drm/msm/dpu: add cdm blocks to sc7280 dpu_hw_catalog
@ 2023-08-30 22:48   ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:48 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan

Add CDM blocks to the sc7280 dpu_hw_catalog to support
YUV format output from writeback block.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 .../gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h  |  9 +++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h      | 13 +++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h         |  5 +++++
 3 files changed, 27 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
index 3b5061c4402a..5252170f216d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
@@ -251,10 +251,19 @@ static const struct dpu_mdss_version sc7280_mdss_ver = {
 	.core_minor_ver = 2,
 };
 
+static const struct dpu_cdm_cfg sc7280_cdm = {
+	.name = "cdm_0",
+	.id = CDM_0,
+	.len = 0x228,
+	.base = 0x79200,
+	.features = 0,
+};
+
 const struct dpu_mdss_cfg dpu_sc7280_cfg = {
 	.mdss_ver = &sc7280_mdss_ver,
 	.caps = &sc7280_dpu_caps,
 	.mdp = &sc7280_mdp,
+	.cdm = &sc7280_cdm,
 	.ctl_count = ARRAY_SIZE(sc7280_ctl),
 	.ctl = sc7280_ctl,
 	.sspp_count = ARRAY_SIZE(sc7280_sspp),
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index 6c9634209e9f..4ea7c3f85a95 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -693,6 +693,17 @@ struct dpu_vbif_cfg {
 	u32 memtype[MAX_XIN_COUNT];
 };
 
+/**
+ * struct dpu_cdm_cfg - information of chroma down blocks
+ * @name               string name for debug purposes
+ * @id                 enum identifying this block
+ * @base               register offset of this block
+ * @features           bit mask identifying sub-blocks/features
+ */
+struct dpu_cdm_cfg {
+	DPU_HW_BLK_INFO;
+};
+
 /**
  * Define CDP use cases
  * @DPU_PERF_CDP_UDAGE_RT: real-time use cases
@@ -816,6 +827,8 @@ struct dpu_mdss_cfg {
 	u32 wb_count;
 	const struct dpu_wb_cfg *wb;
 
+	const struct dpu_cdm_cfg *cdm;
+
 	u32 ad_count;
 
 	u32 dspp_count;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
index d85157acfbf8..4d6dba18caf0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -185,6 +185,11 @@ enum dpu_dsc {
 	DSC_MAX
 };
 
+enum dpu_cdm {
+	CDM_0 = 1,
+	CDM_MAX
+};
+
 enum dpu_pingpong {
 	PINGPONG_NONE,
 	PINGPONG_0,
-- 
2.40.1


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

* [PATCH 05/16] drm/msm/dpu: add cdm blocks to sm8250 dpu_hw_catalog
  2023-08-30 22:48 [PATCH 00/16] Add CDM support for MSM writeback Abhinav Kumar
@ 2023-08-30 22:48   ` Abhinav Kumar
  2023-08-30 22:48   ` Abhinav Kumar
                     ` (14 subsequent siblings)
  15 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:48 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: dri-devel, quic_jesszhan, quic_parellan, quic_khsieh,
	linux-arm-msm, linux-kernel

Add CDM blocks to the sm8250 dpu_hw_catalog to support
YUV format output from writeback block.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h
index 5f9b437b82a6..2d98d14a0f68 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h
@@ -389,10 +389,19 @@ static const struct dpu_mdss_version sm8250_mdss_ver = {
 	.core_minor_ver = 0,
 };
 
+static const struct dpu_cdm_cfg sm8250_cdm = {
+	.name = "cdm_0",
+	.id = CDM_0,
+	.len = 0x228,
+	.base = 0x79200,
+	.features = 0,
+};
+
 const struct dpu_mdss_cfg dpu_sm8250_cfg = {
 	.mdss_ver = &sm8250_mdss_ver,
 	.caps = &sm8250_dpu_caps,
 	.mdp = &sm8250_mdp,
+	.cdm = &sm8250_cdm,
 	.ctl_count = ARRAY_SIZE(sm8250_ctl),
 	.ctl = sm8250_ctl,
 	.sspp_count = ARRAY_SIZE(sm8250_sspp),
-- 
2.40.1


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

* [PATCH 05/16] drm/msm/dpu: add cdm blocks to sm8250 dpu_hw_catalog
@ 2023-08-30 22:48   ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:48 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan

Add CDM blocks to the sm8250 dpu_hw_catalog to support
YUV format output from writeback block.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h
index 5f9b437b82a6..2d98d14a0f68 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h
@@ -389,10 +389,19 @@ static const struct dpu_mdss_version sm8250_mdss_ver = {
 	.core_minor_ver = 0,
 };
 
+static const struct dpu_cdm_cfg sm8250_cdm = {
+	.name = "cdm_0",
+	.id = CDM_0,
+	.len = 0x228,
+	.base = 0x79200,
+	.features = 0,
+};
+
 const struct dpu_mdss_cfg dpu_sm8250_cfg = {
 	.mdss_ver = &sm8250_mdss_ver,
 	.caps = &sm8250_dpu_caps,
 	.mdp = &sm8250_mdp,
+	.cdm = &sm8250_cdm,
 	.ctl_count = ARRAY_SIZE(sm8250_ctl),
 	.ctl = sm8250_ctl,
 	.sspp_count = ARRAY_SIZE(sm8250_sspp),
-- 
2.40.1


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

* [PATCH 06/16] drm/msm/dpu: add dpu_hw_cdm abstraction for CDM block
  2023-08-30 22:48 [PATCH 00/16] Add CDM support for MSM writeback Abhinav Kumar
@ 2023-08-30 22:48   ` Abhinav Kumar
  2023-08-30 22:48   ` Abhinav Kumar
                     ` (14 subsequent siblings)
  15 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:48 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: dri-devel, quic_jesszhan, quic_parellan, quic_khsieh,
	linux-kernel, linux-arm-msm

CDM block comes with its own set of registers and operations
which can be done. In-line with other hardware sub-blocks, this
change adds the dpu_hw_cdm abstraction for the CDM block.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/Makefile                |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c  | 272 ++++++++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h  | 135 ++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h |   1 +
 4 files changed, 409 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 8d02d8c33069..2010cb1ca995 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -63,6 +63,7 @@ msm-$(CONFIG_DRM_MSM_DPU) += \
 	disp/dpu1/dpu_encoder_phys_wb.o \
 	disp/dpu1/dpu_formats.o \
 	disp/dpu1/dpu_hw_catalog.o \
+	disp/dpu1/dpu_hw_cdm.o \
 	disp/dpu1/dpu_hw_ctl.o \
 	disp/dpu1/dpu_hw_dsc.o \
 	disp/dpu1/dpu_hw_dsc_1_2.o \
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
new file mode 100644
index 000000000000..a2f7ee8f54e4
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
@@ -0,0 +1,272 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023, The Linux Foundation. All rights reserved.
+ */
+
+#include <drm/drm_managed.h>
+
+#include "dpu_hw_mdss.h"
+#include "dpu_hw_util.h"
+#include "dpu_hw_catalog.h"
+#include "dpu_hw_cdm.h"
+#include "dpu_kms.h"
+
+#define CDM_CSC_10_OPMODE                  0x000
+#define CDM_CSC_10_BASE                    0x004
+
+#define CDM_CDWN2_OP_MODE                  0x100
+#define CDM_CDWN2_CLAMP_OUT                0x104
+#define CDM_CDWN2_PARAMS_3D_0              0x108
+#define CDM_CDWN2_PARAMS_3D_1              0x10C
+#define CDM_CDWN2_COEFF_COSITE_H_0         0x110
+#define CDM_CDWN2_COEFF_COSITE_H_1         0x114
+#define CDM_CDWN2_COEFF_COSITE_H_2         0x118
+#define CDM_CDWN2_COEFF_OFFSITE_H_0        0x11C
+#define CDM_CDWN2_COEFF_OFFSITE_H_1        0x120
+#define CDM_CDWN2_COEFF_OFFSITE_H_2        0x124
+#define CDM_CDWN2_COEFF_COSITE_V           0x128
+#define CDM_CDWN2_COEFF_OFFSITE_V          0x12C
+#define CDM_CDWN2_OUT_SIZE                 0x130
+
+#define CDM_HDMI_PACK_OP_MODE              0x200
+#define CDM_CSC_10_MATRIX_COEFF_0          0x004
+
+#define CDM_MUX                            0x224
+
+/**
+ * Horizontal coefficients for cosite chroma downscale
+ * s13 representation of coefficients
+ */
+static u32 cosite_h_coeff[] = {0x00000016, 0x000001cc, 0x0100009e};
+
+/**
+ * Horizontal coefficients for offsite chroma downscale
+ */
+static u32 offsite_h_coeff[] = {0x000b0005, 0x01db01eb, 0x00e40046};
+
+/**
+ * Vertical coefficients for cosite chroma downscale
+ */
+static u32 cosite_v_coeff[] = {0x00080004};
+/**
+ * Vertical coefficients for offsite chroma downscale
+ */
+static u32 offsite_v_coeff[] = {0x00060002};
+
+static int dpu_hw_cdm_setup_csc_10bit(struct dpu_hw_cdm *ctx, struct dpu_csc_cfg *data)
+{
+	dpu_hw_csc_setup(&ctx->hw, CDM_CSC_10_MATRIX_COEFF_0, data, true);
+
+	return 0;
+}
+
+static int dpu_hw_cdm_setup_cdwn(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cfg)
+{
+	struct dpu_hw_blk_reg_map *c = &ctx->hw;
+	u32 opmode = 0;
+	u32 out_size = 0;
+
+	if (cfg->output_bit_depth == CDM_CDWN_OUTPUT_10BIT)
+		opmode &= ~BIT(7);
+	else
+		opmode |= BIT(7);
+
+	/* ENABLE DWNS_H bit */
+	opmode |= BIT(1);
+
+	switch (cfg->h_cdwn_type) {
+	case CDM_CDWN_DISABLE:
+		/* CLEAR METHOD_H field */
+		opmode &= ~(0x18);
+		/* CLEAR DWNS_H bit */
+		opmode &= ~BIT(1);
+		break;
+	case CDM_CDWN_PIXEL_DROP:
+		/* Clear METHOD_H field (pixel drop is 0) */
+		opmode &= ~(0x18);
+		break;
+	case CDM_CDWN_AVG:
+		/* Clear METHOD_H field (Average is 0x1) */
+		opmode &= ~(0x18);
+		opmode |= (0x1 << 0x3);
+		break;
+	case CDM_CDWN_COSITE:
+		/* Clear METHOD_H field (Average is 0x2) */
+		opmode &= ~(0x18);
+		opmode |= (0x2 << 0x3);
+		/* Co-site horizontal coefficients */
+		DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_0,
+				cosite_h_coeff[0]);
+		DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_1,
+				cosite_h_coeff[1]);
+		DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_2,
+				cosite_h_coeff[2]);
+		break;
+	case CDM_CDWN_OFFSITE:
+		/* Clear METHOD_H field (Average is 0x3) */
+		opmode &= ~(0x18);
+		opmode |= (0x3 << 0x3);
+
+		/* Off-site horizontal coefficients */
+		DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_0,
+				offsite_h_coeff[0]);
+		DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_1,
+				offsite_h_coeff[1]);
+		DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_2,
+				offsite_h_coeff[2]);
+		break;
+	default:
+		pr_err("%s invalid horz down sampling type\n", __func__);
+		return -EINVAL;
+	}
+
+	/* ENABLE DWNS_V bit */
+	opmode |= BIT(2);
+
+	switch (cfg->v_cdwn_type) {
+	case CDM_CDWN_DISABLE:
+		/* CLEAR METHOD_V field */
+		opmode &= ~(0x60);
+		/* CLEAR DWNS_V bit */
+		opmode &= ~BIT(2);
+		break;
+	case CDM_CDWN_PIXEL_DROP:
+		/* Clear METHOD_V field (pixel drop is 0) */
+		opmode &= ~(0x60);
+		break;
+	case CDM_CDWN_AVG:
+		/* Clear METHOD_V field (Average is 0x1) */
+		opmode &= ~(0x60);
+		opmode |= (0x1 << 0x5);
+		break;
+	case CDM_CDWN_COSITE:
+		/* Clear METHOD_V field (Average is 0x2) */
+		opmode &= ~(0x60);
+		opmode |= (0x2 << 0x5);
+		/* Co-site vertical coefficients */
+		DPU_REG_WRITE(c,
+				CDM_CDWN2_COEFF_COSITE_V,
+				cosite_v_coeff[0]);
+		break;
+	case CDM_CDWN_OFFSITE:
+		/* Clear METHOD_V field (Average is 0x3) */
+		opmode &= ~(0x60);
+		opmode |= (0x3 << 0x5);
+
+		/* Off-site vertical coefficients */
+		DPU_REG_WRITE(c,
+				CDM_CDWN2_COEFF_OFFSITE_V,
+				offsite_v_coeff[0]);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (cfg->v_cdwn_type || cfg->h_cdwn_type)
+		opmode |= BIT(0); /* EN CDWN module */
+	else
+		opmode &= ~BIT(0);
+
+	out_size = (cfg->output_width & 0xFFFF) |
+		((cfg->output_height & 0xFFFF) << 16);
+	DPU_REG_WRITE(c, CDM_CDWN2_OUT_SIZE, out_size);
+	DPU_REG_WRITE(c, CDM_CDWN2_OP_MODE, opmode);
+	DPU_REG_WRITE(c, CDM_CDWN2_CLAMP_OUT,
+			((0x3FF << 16) | 0x0));
+
+	return 0;
+}
+
+int dpu_hw_cdm_enable(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cdm)
+{
+	struct dpu_hw_blk_reg_map *c = &ctx->hw;
+	const struct dpu_format *fmt;
+	u32 opmode = 0;
+	u32 csc = 0;
+
+	if (!ctx || !cdm)
+		return -EINVAL;
+
+	fmt = cdm->output_fmt;
+
+	if (!DPU_FORMAT_IS_YUV(fmt))
+		return -EINVAL;
+
+	if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
+		if (fmt->chroma_sample != DPU_CHROMA_H1V2)
+			return -EINVAL; /*unsupported format */
+		opmode = BIT(0);
+		opmode |= (fmt->chroma_sample << 1);
+	}
+
+	csc |= BIT(2);
+	csc &= ~BIT(1);
+	csc |= BIT(0);
+
+	if (ctx && ctx->ops.bind_pingpong_blk)
+		ctx->ops.bind_pingpong_blk(ctx, true,
+				cdm->pp_id);
+
+	DPU_REG_WRITE(c, CDM_CSC_10_OPMODE, csc);
+	DPU_REG_WRITE(c, CDM_HDMI_PACK_OP_MODE, opmode);
+	return 0;
+}
+
+void dpu_hw_cdm_disable(struct dpu_hw_cdm *ctx)
+{
+	if (!ctx)
+		return;
+
+	if (ctx && ctx->ops.bind_pingpong_blk)
+		ctx->ops.bind_pingpong_blk(ctx, false, 0);
+}
+
+static void dpu_hw_cdm_bind_pingpong_blk(struct dpu_hw_cdm *ctx, bool enable,
+					 const enum dpu_pingpong pp)
+{
+	struct dpu_hw_blk_reg_map *c;
+	int mux_cfg = 0xF;
+
+	if (!ctx || (enable && (pp < PINGPONG_0 || pp >= PINGPONG_MAX)))
+		return;
+
+	c = &ctx->hw;
+
+	if (enable)
+		mux_cfg = (pp - PINGPONG_0) & 0x7;
+
+	DPU_REG_WRITE(c, CDM_MUX, mux_cfg);
+}
+
+static void _setup_cdm_ops(struct dpu_hw_cdm_ops *ops, unsigned long features)
+{
+	ops->setup_csc_data = dpu_hw_cdm_setup_csc_10bit;
+	ops->setup_cdwn = dpu_hw_cdm_setup_cdwn;
+	ops->enable = dpu_hw_cdm_enable;
+	ops->disable = dpu_hw_cdm_disable;
+	ops->bind_pingpong_blk = dpu_hw_cdm_bind_pingpong_blk;
+}
+
+struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cfg, void __iomem *addr)
+{
+	struct dpu_hw_cdm *c;
+
+	c = kzalloc(sizeof(*c), GFP_KERNEL);
+	if (!c)
+		return ERR_PTR(-ENOMEM);
+
+	c->hw.blk_addr = addr + cfg->base;
+	c->hw.log_mask = DPU_DBG_MASK_CDM;
+
+	/* Assign ops */
+	c->idx = cfg->id;
+	c->caps = cfg;
+	_setup_cdm_ops(&c->ops, c->caps->features);
+
+	return c;
+}
+
+void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm)
+{
+	kfree(cdm);
+}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
new file mode 100644
index 000000000000..da60893a5c02
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
@@ -0,0 +1,135 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2023, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DPU_HW_CDM_H
+#define _DPU_HW_CDM_H
+
+#include "dpu_hw_mdss.h"
+#include "dpu_hw_top.h"
+
+struct dpu_hw_cdm;
+
+struct dpu_hw_cdm_cfg {
+	u32 output_width;
+	u32 output_height;
+	u32 output_bit_depth;
+	u32 h_cdwn_type;
+	u32 v_cdwn_type;
+	const struct dpu_format *output_fmt;
+	u32 output_type;
+	int pp_id;
+};
+
+enum dpu_hw_cdwn_type {
+	CDM_CDWN_DISABLE,
+	CDM_CDWN_PIXEL_DROP,
+	CDM_CDWN_AVG,
+	CDM_CDWN_COSITE,
+	CDM_CDWN_OFFSITE,
+};
+
+enum dpu_hw_cdwn_output_type {
+	CDM_CDWN_OUTPUT_HDMI,
+	CDM_CDWN_OUTPUT_WB,
+};
+
+enum dpu_hw_cdwn_output_bit_depth {
+	CDM_CDWN_OUTPUT_8BIT,
+	CDM_CDWN_OUTPUT_10BIT,
+};
+
+/**
+ * struct dpu_hw_cdm_ops : Interface to the chroma down Hw driver functions
+ *                         Assumption is these functions will be called after
+ *                         clocks are enabled
+ *  @setup_csc:            Programs the csc matrix
+ *  @setup_cdwn:           Sets up the chroma down sub module
+ *  @enable:               Enables the output to interface and programs the
+ *                         output packer
+ *  @disable:              Puts the cdm in bypass mode
+ *  @bind_pingpong_blk:    enable/disable the connection with pingpong which
+ *                         will feed pixels to this cdm
+ */
+struct dpu_hw_cdm_ops {
+	/**
+	 * Programs the CSC matrix for conversion from RGB space to YUV space,
+	 * it is optional to call this function as this matrix is automatically
+	 * set during initialization, user should call this if it wants
+	 * to program a different matrix than default matrix.
+	 * @cdm:          Pointer to the chroma down context structure
+	 * @data          Pointer to CSC configuration data
+	 * return:        0 if success; error code otherwise
+	 */
+	int (*setup_csc_data)(struct dpu_hw_cdm *cdm, struct dpu_csc_cfg *data);
+
+	/**
+	 * Programs the Chroma downsample part.
+	 * @cdm         Pointer to chroma down context
+	 * @cfg         Pointer to the cdm configuration data
+	 */
+	int (*setup_cdwn)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
+
+	/**
+	 * Enable the CDM module
+	 * @cdm         Pointer to chroma down context
+	 */
+	int (*enable)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
+
+	/**
+	 * Disable the CDM module
+	 * @cdm         Pointer to chroma down context
+	 */
+	void (*disable)(struct dpu_hw_cdm *cdm);
+
+	/**
+	 * Enable/disable the connection with pingpong
+	 * @cdm         Pointer to chroma down context
+	 * @enable      Enable/disable control
+	 * @pp          pingpong block id.
+	 */
+	void (*bind_pingpong_blk)(struct dpu_hw_cdm *cdm, bool enable,
+				  const enum dpu_pingpong pp);
+};
+
+/**
+ * struct dpu_hw_cdm - cdm description
+ * @base: Hardware block base structure
+ * @hw: Block hardware details
+ * @idx: CDM index
+ * @caps: Pointer to cdm_cfg
+ * @ops: handle to operations possible for this CDM
+ */
+struct dpu_hw_cdm {
+	struct dpu_hw_blk base;
+	struct dpu_hw_blk_reg_map hw;
+
+	/* chroma down */
+	const struct dpu_cdm_cfg *caps;
+	enum  dpu_cdm  idx;
+
+	/* ops */
+	struct dpu_hw_cdm_ops ops;
+};
+
+/**
+ * dpu_hw_cdm_init - initializes the cdm hw driver object.
+ * should be called once before accessing every cdm.
+ * @cdm: CDM catalog entry for which driver object is required
+ * @addr :   mapped register io address of MDSS
+ */
+struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cdm, void __iomem *addr);
+
+/**
+ * dpu_hw_cdm_destroy - destroys cdm driver context
+ * @cdm:   Pointer to cdm driver context returned by dpu_hw_cdm_init
+ */
+void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm);
+
+static inline struct dpu_hw_cdm *to_dpu_hw_cdm(struct dpu_hw_blk *hw)
+{
+	return container_of(hw, struct dpu_hw_cdm, base);
+}
+
+#endif /*_DPU_HW_CDM_H */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
index 4d6dba18caf0..34f943102499 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -463,6 +463,7 @@ struct dpu_mdss_color {
 #define DPU_DBG_MASK_ROT      (1 << 9)
 #define DPU_DBG_MASK_DSPP     (1 << 10)
 #define DPU_DBG_MASK_DSC      (1 << 11)
+#define DPU_DBG_MASK_CDM      (1 << 12)
 
 /**
  * struct dpu_hw_tear_check - Struct contains parameters to configure
-- 
2.40.1


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

* [PATCH 06/16] drm/msm/dpu: add dpu_hw_cdm abstraction for CDM block
@ 2023-08-30 22:48   ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:48 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan

CDM block comes with its own set of registers and operations
which can be done. In-line with other hardware sub-blocks, this
change adds the dpu_hw_cdm abstraction for the CDM block.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/Makefile                |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c  | 272 ++++++++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h  | 135 ++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h |   1 +
 4 files changed, 409 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 8d02d8c33069..2010cb1ca995 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -63,6 +63,7 @@ msm-$(CONFIG_DRM_MSM_DPU) += \
 	disp/dpu1/dpu_encoder_phys_wb.o \
 	disp/dpu1/dpu_formats.o \
 	disp/dpu1/dpu_hw_catalog.o \
+	disp/dpu1/dpu_hw_cdm.o \
 	disp/dpu1/dpu_hw_ctl.o \
 	disp/dpu1/dpu_hw_dsc.o \
 	disp/dpu1/dpu_hw_dsc_1_2.o \
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
new file mode 100644
index 000000000000..a2f7ee8f54e4
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
@@ -0,0 +1,272 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2023, The Linux Foundation. All rights reserved.
+ */
+
+#include <drm/drm_managed.h>
+
+#include "dpu_hw_mdss.h"
+#include "dpu_hw_util.h"
+#include "dpu_hw_catalog.h"
+#include "dpu_hw_cdm.h"
+#include "dpu_kms.h"
+
+#define CDM_CSC_10_OPMODE                  0x000
+#define CDM_CSC_10_BASE                    0x004
+
+#define CDM_CDWN2_OP_MODE                  0x100
+#define CDM_CDWN2_CLAMP_OUT                0x104
+#define CDM_CDWN2_PARAMS_3D_0              0x108
+#define CDM_CDWN2_PARAMS_3D_1              0x10C
+#define CDM_CDWN2_COEFF_COSITE_H_0         0x110
+#define CDM_CDWN2_COEFF_COSITE_H_1         0x114
+#define CDM_CDWN2_COEFF_COSITE_H_2         0x118
+#define CDM_CDWN2_COEFF_OFFSITE_H_0        0x11C
+#define CDM_CDWN2_COEFF_OFFSITE_H_1        0x120
+#define CDM_CDWN2_COEFF_OFFSITE_H_2        0x124
+#define CDM_CDWN2_COEFF_COSITE_V           0x128
+#define CDM_CDWN2_COEFF_OFFSITE_V          0x12C
+#define CDM_CDWN2_OUT_SIZE                 0x130
+
+#define CDM_HDMI_PACK_OP_MODE              0x200
+#define CDM_CSC_10_MATRIX_COEFF_0          0x004
+
+#define CDM_MUX                            0x224
+
+/**
+ * Horizontal coefficients for cosite chroma downscale
+ * s13 representation of coefficients
+ */
+static u32 cosite_h_coeff[] = {0x00000016, 0x000001cc, 0x0100009e};
+
+/**
+ * Horizontal coefficients for offsite chroma downscale
+ */
+static u32 offsite_h_coeff[] = {0x000b0005, 0x01db01eb, 0x00e40046};
+
+/**
+ * Vertical coefficients for cosite chroma downscale
+ */
+static u32 cosite_v_coeff[] = {0x00080004};
+/**
+ * Vertical coefficients for offsite chroma downscale
+ */
+static u32 offsite_v_coeff[] = {0x00060002};
+
+static int dpu_hw_cdm_setup_csc_10bit(struct dpu_hw_cdm *ctx, struct dpu_csc_cfg *data)
+{
+	dpu_hw_csc_setup(&ctx->hw, CDM_CSC_10_MATRIX_COEFF_0, data, true);
+
+	return 0;
+}
+
+static int dpu_hw_cdm_setup_cdwn(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cfg)
+{
+	struct dpu_hw_blk_reg_map *c = &ctx->hw;
+	u32 opmode = 0;
+	u32 out_size = 0;
+
+	if (cfg->output_bit_depth == CDM_CDWN_OUTPUT_10BIT)
+		opmode &= ~BIT(7);
+	else
+		opmode |= BIT(7);
+
+	/* ENABLE DWNS_H bit */
+	opmode |= BIT(1);
+
+	switch (cfg->h_cdwn_type) {
+	case CDM_CDWN_DISABLE:
+		/* CLEAR METHOD_H field */
+		opmode &= ~(0x18);
+		/* CLEAR DWNS_H bit */
+		opmode &= ~BIT(1);
+		break;
+	case CDM_CDWN_PIXEL_DROP:
+		/* Clear METHOD_H field (pixel drop is 0) */
+		opmode &= ~(0x18);
+		break;
+	case CDM_CDWN_AVG:
+		/* Clear METHOD_H field (Average is 0x1) */
+		opmode &= ~(0x18);
+		opmode |= (0x1 << 0x3);
+		break;
+	case CDM_CDWN_COSITE:
+		/* Clear METHOD_H field (Average is 0x2) */
+		opmode &= ~(0x18);
+		opmode |= (0x2 << 0x3);
+		/* Co-site horizontal coefficients */
+		DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_0,
+				cosite_h_coeff[0]);
+		DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_1,
+				cosite_h_coeff[1]);
+		DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_2,
+				cosite_h_coeff[2]);
+		break;
+	case CDM_CDWN_OFFSITE:
+		/* Clear METHOD_H field (Average is 0x3) */
+		opmode &= ~(0x18);
+		opmode |= (0x3 << 0x3);
+
+		/* Off-site horizontal coefficients */
+		DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_0,
+				offsite_h_coeff[0]);
+		DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_1,
+				offsite_h_coeff[1]);
+		DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_2,
+				offsite_h_coeff[2]);
+		break;
+	default:
+		pr_err("%s invalid horz down sampling type\n", __func__);
+		return -EINVAL;
+	}
+
+	/* ENABLE DWNS_V bit */
+	opmode |= BIT(2);
+
+	switch (cfg->v_cdwn_type) {
+	case CDM_CDWN_DISABLE:
+		/* CLEAR METHOD_V field */
+		opmode &= ~(0x60);
+		/* CLEAR DWNS_V bit */
+		opmode &= ~BIT(2);
+		break;
+	case CDM_CDWN_PIXEL_DROP:
+		/* Clear METHOD_V field (pixel drop is 0) */
+		opmode &= ~(0x60);
+		break;
+	case CDM_CDWN_AVG:
+		/* Clear METHOD_V field (Average is 0x1) */
+		opmode &= ~(0x60);
+		opmode |= (0x1 << 0x5);
+		break;
+	case CDM_CDWN_COSITE:
+		/* Clear METHOD_V field (Average is 0x2) */
+		opmode &= ~(0x60);
+		opmode |= (0x2 << 0x5);
+		/* Co-site vertical coefficients */
+		DPU_REG_WRITE(c,
+				CDM_CDWN2_COEFF_COSITE_V,
+				cosite_v_coeff[0]);
+		break;
+	case CDM_CDWN_OFFSITE:
+		/* Clear METHOD_V field (Average is 0x3) */
+		opmode &= ~(0x60);
+		opmode |= (0x3 << 0x5);
+
+		/* Off-site vertical coefficients */
+		DPU_REG_WRITE(c,
+				CDM_CDWN2_COEFF_OFFSITE_V,
+				offsite_v_coeff[0]);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (cfg->v_cdwn_type || cfg->h_cdwn_type)
+		opmode |= BIT(0); /* EN CDWN module */
+	else
+		opmode &= ~BIT(0);
+
+	out_size = (cfg->output_width & 0xFFFF) |
+		((cfg->output_height & 0xFFFF) << 16);
+	DPU_REG_WRITE(c, CDM_CDWN2_OUT_SIZE, out_size);
+	DPU_REG_WRITE(c, CDM_CDWN2_OP_MODE, opmode);
+	DPU_REG_WRITE(c, CDM_CDWN2_CLAMP_OUT,
+			((0x3FF << 16) | 0x0));
+
+	return 0;
+}
+
+int dpu_hw_cdm_enable(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cdm)
+{
+	struct dpu_hw_blk_reg_map *c = &ctx->hw;
+	const struct dpu_format *fmt;
+	u32 opmode = 0;
+	u32 csc = 0;
+
+	if (!ctx || !cdm)
+		return -EINVAL;
+
+	fmt = cdm->output_fmt;
+
+	if (!DPU_FORMAT_IS_YUV(fmt))
+		return -EINVAL;
+
+	if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
+		if (fmt->chroma_sample != DPU_CHROMA_H1V2)
+			return -EINVAL; /*unsupported format */
+		opmode = BIT(0);
+		opmode |= (fmt->chroma_sample << 1);
+	}
+
+	csc |= BIT(2);
+	csc &= ~BIT(1);
+	csc |= BIT(0);
+
+	if (ctx && ctx->ops.bind_pingpong_blk)
+		ctx->ops.bind_pingpong_blk(ctx, true,
+				cdm->pp_id);
+
+	DPU_REG_WRITE(c, CDM_CSC_10_OPMODE, csc);
+	DPU_REG_WRITE(c, CDM_HDMI_PACK_OP_MODE, opmode);
+	return 0;
+}
+
+void dpu_hw_cdm_disable(struct dpu_hw_cdm *ctx)
+{
+	if (!ctx)
+		return;
+
+	if (ctx && ctx->ops.bind_pingpong_blk)
+		ctx->ops.bind_pingpong_blk(ctx, false, 0);
+}
+
+static void dpu_hw_cdm_bind_pingpong_blk(struct dpu_hw_cdm *ctx, bool enable,
+					 const enum dpu_pingpong pp)
+{
+	struct dpu_hw_blk_reg_map *c;
+	int mux_cfg = 0xF;
+
+	if (!ctx || (enable && (pp < PINGPONG_0 || pp >= PINGPONG_MAX)))
+		return;
+
+	c = &ctx->hw;
+
+	if (enable)
+		mux_cfg = (pp - PINGPONG_0) & 0x7;
+
+	DPU_REG_WRITE(c, CDM_MUX, mux_cfg);
+}
+
+static void _setup_cdm_ops(struct dpu_hw_cdm_ops *ops, unsigned long features)
+{
+	ops->setup_csc_data = dpu_hw_cdm_setup_csc_10bit;
+	ops->setup_cdwn = dpu_hw_cdm_setup_cdwn;
+	ops->enable = dpu_hw_cdm_enable;
+	ops->disable = dpu_hw_cdm_disable;
+	ops->bind_pingpong_blk = dpu_hw_cdm_bind_pingpong_blk;
+}
+
+struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cfg, void __iomem *addr)
+{
+	struct dpu_hw_cdm *c;
+
+	c = kzalloc(sizeof(*c), GFP_KERNEL);
+	if (!c)
+		return ERR_PTR(-ENOMEM);
+
+	c->hw.blk_addr = addr + cfg->base;
+	c->hw.log_mask = DPU_DBG_MASK_CDM;
+
+	/* Assign ops */
+	c->idx = cfg->id;
+	c->caps = cfg;
+	_setup_cdm_ops(&c->ops, c->caps->features);
+
+	return c;
+}
+
+void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm)
+{
+	kfree(cdm);
+}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
new file mode 100644
index 000000000000..da60893a5c02
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
@@ -0,0 +1,135 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2023, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DPU_HW_CDM_H
+#define _DPU_HW_CDM_H
+
+#include "dpu_hw_mdss.h"
+#include "dpu_hw_top.h"
+
+struct dpu_hw_cdm;
+
+struct dpu_hw_cdm_cfg {
+	u32 output_width;
+	u32 output_height;
+	u32 output_bit_depth;
+	u32 h_cdwn_type;
+	u32 v_cdwn_type;
+	const struct dpu_format *output_fmt;
+	u32 output_type;
+	int pp_id;
+};
+
+enum dpu_hw_cdwn_type {
+	CDM_CDWN_DISABLE,
+	CDM_CDWN_PIXEL_DROP,
+	CDM_CDWN_AVG,
+	CDM_CDWN_COSITE,
+	CDM_CDWN_OFFSITE,
+};
+
+enum dpu_hw_cdwn_output_type {
+	CDM_CDWN_OUTPUT_HDMI,
+	CDM_CDWN_OUTPUT_WB,
+};
+
+enum dpu_hw_cdwn_output_bit_depth {
+	CDM_CDWN_OUTPUT_8BIT,
+	CDM_CDWN_OUTPUT_10BIT,
+};
+
+/**
+ * struct dpu_hw_cdm_ops : Interface to the chroma down Hw driver functions
+ *                         Assumption is these functions will be called after
+ *                         clocks are enabled
+ *  @setup_csc:            Programs the csc matrix
+ *  @setup_cdwn:           Sets up the chroma down sub module
+ *  @enable:               Enables the output to interface and programs the
+ *                         output packer
+ *  @disable:              Puts the cdm in bypass mode
+ *  @bind_pingpong_blk:    enable/disable the connection with pingpong which
+ *                         will feed pixels to this cdm
+ */
+struct dpu_hw_cdm_ops {
+	/**
+	 * Programs the CSC matrix for conversion from RGB space to YUV space,
+	 * it is optional to call this function as this matrix is automatically
+	 * set during initialization, user should call this if it wants
+	 * to program a different matrix than default matrix.
+	 * @cdm:          Pointer to the chroma down context structure
+	 * @data          Pointer to CSC configuration data
+	 * return:        0 if success; error code otherwise
+	 */
+	int (*setup_csc_data)(struct dpu_hw_cdm *cdm, struct dpu_csc_cfg *data);
+
+	/**
+	 * Programs the Chroma downsample part.
+	 * @cdm         Pointer to chroma down context
+	 * @cfg         Pointer to the cdm configuration data
+	 */
+	int (*setup_cdwn)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
+
+	/**
+	 * Enable the CDM module
+	 * @cdm         Pointer to chroma down context
+	 */
+	int (*enable)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
+
+	/**
+	 * Disable the CDM module
+	 * @cdm         Pointer to chroma down context
+	 */
+	void (*disable)(struct dpu_hw_cdm *cdm);
+
+	/**
+	 * Enable/disable the connection with pingpong
+	 * @cdm         Pointer to chroma down context
+	 * @enable      Enable/disable control
+	 * @pp          pingpong block id.
+	 */
+	void (*bind_pingpong_blk)(struct dpu_hw_cdm *cdm, bool enable,
+				  const enum dpu_pingpong pp);
+};
+
+/**
+ * struct dpu_hw_cdm - cdm description
+ * @base: Hardware block base structure
+ * @hw: Block hardware details
+ * @idx: CDM index
+ * @caps: Pointer to cdm_cfg
+ * @ops: handle to operations possible for this CDM
+ */
+struct dpu_hw_cdm {
+	struct dpu_hw_blk base;
+	struct dpu_hw_blk_reg_map hw;
+
+	/* chroma down */
+	const struct dpu_cdm_cfg *caps;
+	enum  dpu_cdm  idx;
+
+	/* ops */
+	struct dpu_hw_cdm_ops ops;
+};
+
+/**
+ * dpu_hw_cdm_init - initializes the cdm hw driver object.
+ * should be called once before accessing every cdm.
+ * @cdm: CDM catalog entry for which driver object is required
+ * @addr :   mapped register io address of MDSS
+ */
+struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cdm, void __iomem *addr);
+
+/**
+ * dpu_hw_cdm_destroy - destroys cdm driver context
+ * @cdm:   Pointer to cdm driver context returned by dpu_hw_cdm_init
+ */
+void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm);
+
+static inline struct dpu_hw_cdm *to_dpu_hw_cdm(struct dpu_hw_blk *hw)
+{
+	return container_of(hw, struct dpu_hw_cdm, base);
+}
+
+#endif /*_DPU_HW_CDM_H */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
index 4d6dba18caf0..34f943102499 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -463,6 +463,7 @@ struct dpu_mdss_color {
 #define DPU_DBG_MASK_ROT      (1 << 9)
 #define DPU_DBG_MASK_DSPP     (1 << 10)
 #define DPU_DBG_MASK_DSC      (1 << 11)
+#define DPU_DBG_MASK_CDM      (1 << 12)
 
 /**
  * struct dpu_hw_tear_check - Struct contains parameters to configure
-- 
2.40.1


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

* [PATCH 07/16] drm/msm/dpu: add cdm blocks to RM
  2023-08-30 22:48 [PATCH 00/16] Add CDM support for MSM writeback Abhinav Kumar
@ 2023-08-30 22:49   ` Abhinav Kumar
  2023-08-30 22:48   ` Abhinav Kumar
                     ` (14 subsequent siblings)
  15 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:49 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: dri-devel, quic_jesszhan, quic_parellan, quic_khsieh,
	linux-arm-msm, linux-kernel

Add the RM APIs necessary to initialize and allocate CDM
blocks by the rest of the DPU pipeline.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 17 +++++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h |  2 ++
 2 files changed, 19 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index f9215643c71a..7b6444a3fcb1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -8,6 +8,7 @@
 #include "dpu_kms.h"
 #include "dpu_hw_lm.h"
 #include "dpu_hw_ctl.h"
+#include "dpu_hw_cdm.h"
 #include "dpu_hw_pingpong.h"
 #include "dpu_hw_sspp.h"
 #include "dpu_hw_intf.h"
@@ -90,6 +91,9 @@ int dpu_rm_destroy(struct dpu_rm *rm)
 		}
 	}
 
+	if (rm->cdm_blk)
+		dpu_hw_cdm_destroy(to_dpu_hw_cdm(rm->cdm_blk));
+
 	for (i = 0; i < ARRAY_SIZE(rm->hw_wb); i++)
 		dpu_hw_wb_destroy(rm->hw_wb[i]);
 
@@ -240,6 +244,19 @@ int dpu_rm_init(struct dpu_rm *rm,
 		rm->hw_sspp[sspp->id - SSPP_NONE] = hw;
 	}
 
+	if (cat->cdm) {
+		struct dpu_hw_cdm *hw;
+
+		hw = dpu_hw_cdm_init(cat->cdm, mmio);
+		/* CDM is optional so no need to bail out */
+		if (IS_ERR(hw)) {
+			rc = PTR_ERR(hw);
+			DPU_DEBUG("failed cdm object creation: err %d\n", rc);
+		} else {
+			rm->cdm_blk = &hw->base;
+		}
+	}
+
 	return 0;
 
 fail:
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index 2b551566cbf4..29b221491926 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -22,6 +22,7 @@ struct dpu_global_state;
  * @hw_wb: array of wb hardware resources
  * @dspp_blks: array of dspp hardware resources
  * @hw_sspp: array of sspp hardware resources
+ * @cdm_blk: cdm hardware resource
  */
 struct dpu_rm {
 	struct dpu_hw_blk *pingpong_blks[PINGPONG_MAX - PINGPONG_0];
@@ -33,6 +34,7 @@ struct dpu_rm {
 	struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0];
 	struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0];
 	struct dpu_hw_sspp *hw_sspp[SSPP_MAX - SSPP_NONE];
+	struct dpu_hw_blk *cdm_blk;
 };
 
 /**
-- 
2.40.1


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

* [PATCH 07/16] drm/msm/dpu: add cdm blocks to RM
@ 2023-08-30 22:49   ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:49 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan

Add the RM APIs necessary to initialize and allocate CDM
blocks by the rest of the DPU pipeline.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 17 +++++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h |  2 ++
 2 files changed, 19 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index f9215643c71a..7b6444a3fcb1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -8,6 +8,7 @@
 #include "dpu_kms.h"
 #include "dpu_hw_lm.h"
 #include "dpu_hw_ctl.h"
+#include "dpu_hw_cdm.h"
 #include "dpu_hw_pingpong.h"
 #include "dpu_hw_sspp.h"
 #include "dpu_hw_intf.h"
@@ -90,6 +91,9 @@ int dpu_rm_destroy(struct dpu_rm *rm)
 		}
 	}
 
+	if (rm->cdm_blk)
+		dpu_hw_cdm_destroy(to_dpu_hw_cdm(rm->cdm_blk));
+
 	for (i = 0; i < ARRAY_SIZE(rm->hw_wb); i++)
 		dpu_hw_wb_destroy(rm->hw_wb[i]);
 
@@ -240,6 +244,19 @@ int dpu_rm_init(struct dpu_rm *rm,
 		rm->hw_sspp[sspp->id - SSPP_NONE] = hw;
 	}
 
+	if (cat->cdm) {
+		struct dpu_hw_cdm *hw;
+
+		hw = dpu_hw_cdm_init(cat->cdm, mmio);
+		/* CDM is optional so no need to bail out */
+		if (IS_ERR(hw)) {
+			rc = PTR_ERR(hw);
+			DPU_DEBUG("failed cdm object creation: err %d\n", rc);
+		} else {
+			rm->cdm_blk = &hw->base;
+		}
+	}
+
 	return 0;
 
 fail:
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index 2b551566cbf4..29b221491926 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -22,6 +22,7 @@ struct dpu_global_state;
  * @hw_wb: array of wb hardware resources
  * @dspp_blks: array of dspp hardware resources
  * @hw_sspp: array of sspp hardware resources
+ * @cdm_blk: cdm hardware resource
  */
 struct dpu_rm {
 	struct dpu_hw_blk *pingpong_blks[PINGPONG_MAX - PINGPONG_0];
@@ -33,6 +34,7 @@ struct dpu_rm {
 	struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0];
 	struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0];
 	struct dpu_hw_sspp *hw_sspp[SSPP_MAX - SSPP_NONE];
+	struct dpu_hw_blk *cdm_blk;
 };
 
 /**
-- 
2.40.1


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

* [PATCH 08/16] drm/msm/dpu: add support to allocate CDM from RM
  2023-08-30 22:48 [PATCH 00/16] Add CDM support for MSM writeback Abhinav Kumar
@ 2023-08-30 22:49   ` Abhinav Kumar
  2023-08-30 22:48   ` Abhinav Kumar
                     ` (14 subsequent siblings)
  15 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:49 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: dri-devel, quic_jesszhan, quic_parellan, quic_khsieh,
	linux-arm-msm, linux-kernel

Even though there is usually only one CDM block, it can be
used by either HDMI, DisplayPort OR Writeback interfaces.

Hence its allocation needs to be tracked properly by the
resource manager to ensure appropriate availability of the
block.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  2 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h |  1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h     |  1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c      | 45 +++++++++++++++++++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h      |  4 +-
 5 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 6cf6597148fd..582680804016 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -663,7 +663,7 @@ static int dpu_encoder_virt_atomic_check(
 
 		if (!crtc_state->active_changed || crtc_state->enable)
 			ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
-					drm_enc, crtc_state, topology);
+					drm_enc, crtc_state, topology, false);
 	}
 
 	trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
index 34f943102499..07f75f295844 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -98,6 +98,7 @@ enum dpu_hw_blk_type {
 	DPU_HW_BLK_DSPP,
 	DPU_HW_BLK_MERGE_3D,
 	DPU_HW_BLK_DSC,
+	DPU_HW_BLK_CDM,
 	DPU_HW_BLK_MAX,
 };
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index b6f53ca6e962..61aa58643fda 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -136,6 +136,7 @@ struct dpu_global_state {
 	uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
 	uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
 	uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
+	uint32_t cdm_to_enc_id;
 };
 
 struct dpu_global_state
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 7b6444a3fcb1..e7d4beb4661e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -29,10 +29,12 @@ static inline bool reserved_by_other(uint32_t *res_map, int idx,
 /**
  * struct dpu_rm_requirements - Reservation requirements parameter bundle
  * @topology:  selected topology for the display
+ * @needs_cdm: whether the display needs a CDM block for the current mode
  * @hw_res:	   Hardware resources required as reported by the encoders
  */
 struct dpu_rm_requirements {
 	struct msm_display_topology topology;
+	bool needs_cdm;
 };
 
 int dpu_rm_destroy(struct dpu_rm *rm)
@@ -505,6 +507,26 @@ static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
 	return 0;
 }
 
+static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
+			       struct dpu_global_state *global_state,
+			       struct drm_encoder *enc)
+{
+	/* try allocating only one CDM block */
+	if (!rm->cdm_blk) {
+		DPU_ERROR("CDM block does not exist\n");
+		return -EIO;
+	}
+
+	if (global_state->cdm_to_enc_id) {
+		DPU_ERROR("CDM_0 is already allocated\n");
+		return -EIO;
+	}
+
+	global_state->cdm_to_enc_id = enc->base.id;
+
+	return 0;
+}
+
 static int _dpu_rm_make_reservation(
 		struct dpu_rm *rm,
 		struct dpu_global_state *global_state,
@@ -530,15 +552,25 @@ static int _dpu_rm_make_reservation(
 	if (ret)
 		return ret;
 
+	if (reqs->needs_cdm) {
+		ret = _dpu_rm_reserve_cdm(rm, global_state, enc);
+		if (ret) {
+			DPU_ERROR("unable to find CDM blk\n");
+			return ret;
+		}
+	}
+
 	return ret;
 }
 
 static int _dpu_rm_populate_requirements(
 		struct drm_encoder *enc,
 		struct dpu_rm_requirements *reqs,
-		struct msm_display_topology req_topology)
+		struct msm_display_topology req_topology,
+		bool needs_cdm)
 {
 	reqs->topology = req_topology;
+	reqs->needs_cdm = needs_cdm;
 
 	DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
 		      reqs->topology.num_lm, reqs->topology.num_dsc,
@@ -571,6 +603,7 @@ void dpu_rm_release(struct dpu_global_state *global_state,
 		ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
 	_dpu_rm_clear_mapping(global_state->dspp_to_enc_id,
 		ARRAY_SIZE(global_state->dspp_to_enc_id), enc->base.id);
+	_dpu_rm_clear_mapping(&global_state->cdm_to_enc_id, 1, enc->base.id);
 }
 
 int dpu_rm_reserve(
@@ -578,7 +611,8 @@ int dpu_rm_reserve(
 		struct dpu_global_state *global_state,
 		struct drm_encoder *enc,
 		struct drm_crtc_state *crtc_state,
-		struct msm_display_topology topology)
+		struct msm_display_topology topology,
+		bool needs_cdm)
 {
 	struct dpu_rm_requirements reqs;
 	int ret;
@@ -595,7 +629,7 @@ int dpu_rm_reserve(
 	DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
 		      enc->base.id, crtc_state->crtc->base.id);
 
-	ret = _dpu_rm_populate_requirements(enc, &reqs, topology);
+	ret = _dpu_rm_populate_requirements(enc, &reqs, topology, needs_cdm);
 	if (ret) {
 		DPU_ERROR("failed to populate hw requirements\n");
 		return ret;
@@ -644,6 +678,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
 		hw_to_enc_id = global_state->dsc_to_enc_id;
 		max_blks = ARRAY_SIZE(rm->dsc_blks);
 		break;
+	case DPU_HW_BLK_CDM:
+		hw_blks = &rm->cdm_blk;
+		hw_to_enc_id = &global_state->cdm_to_enc_id;
+		max_blks = 1;
+		break;
 	default:
 		DPU_ERROR("blk type %d not managed by rm\n", type);
 		return 0;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index 29b221491926..74262d3cb6c3 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -69,13 +69,15 @@ int dpu_rm_destroy(struct dpu_rm *rm);
  * @drm_enc: DRM Encoder handle
  * @crtc_state: Proposed Atomic DRM CRTC State handle
  * @topology: Pointer to topology info for the display
+ * @needs_cdm: bool to indicate whether current encoder needs CDM
  * @Return: 0 on Success otherwise -ERROR
  */
 int dpu_rm_reserve(struct dpu_rm *rm,
 		struct dpu_global_state *global_state,
 		struct drm_encoder *drm_enc,
 		struct drm_crtc_state *crtc_state,
-		struct msm_display_topology topology);
+		struct msm_display_topology topology,
+		bool needs_cdm);
 
 /**
  * dpu_rm_reserve - Given the encoder for the display chain, release any
-- 
2.40.1


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

* [PATCH 08/16] drm/msm/dpu: add support to allocate CDM from RM
@ 2023-08-30 22:49   ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:49 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan

Even though there is usually only one CDM block, it can be
used by either HDMI, DisplayPort OR Writeback interfaces.

Hence its allocation needs to be tracked properly by the
resource manager to ensure appropriate availability of the
block.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  2 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h |  1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h     |  1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c      | 45 +++++++++++++++++++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h      |  4 +-
 5 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 6cf6597148fd..582680804016 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -663,7 +663,7 @@ static int dpu_encoder_virt_atomic_check(
 
 		if (!crtc_state->active_changed || crtc_state->enable)
 			ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
-					drm_enc, crtc_state, topology);
+					drm_enc, crtc_state, topology, false);
 	}
 
 	trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
index 34f943102499..07f75f295844 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -98,6 +98,7 @@ enum dpu_hw_blk_type {
 	DPU_HW_BLK_DSPP,
 	DPU_HW_BLK_MERGE_3D,
 	DPU_HW_BLK_DSC,
+	DPU_HW_BLK_CDM,
 	DPU_HW_BLK_MAX,
 };
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index b6f53ca6e962..61aa58643fda 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -136,6 +136,7 @@ struct dpu_global_state {
 	uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
 	uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
 	uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
+	uint32_t cdm_to_enc_id;
 };
 
 struct dpu_global_state
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 7b6444a3fcb1..e7d4beb4661e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -29,10 +29,12 @@ static inline bool reserved_by_other(uint32_t *res_map, int idx,
 /**
  * struct dpu_rm_requirements - Reservation requirements parameter bundle
  * @topology:  selected topology for the display
+ * @needs_cdm: whether the display needs a CDM block for the current mode
  * @hw_res:	   Hardware resources required as reported by the encoders
  */
 struct dpu_rm_requirements {
 	struct msm_display_topology topology;
+	bool needs_cdm;
 };
 
 int dpu_rm_destroy(struct dpu_rm *rm)
@@ -505,6 +507,26 @@ static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
 	return 0;
 }
 
+static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
+			       struct dpu_global_state *global_state,
+			       struct drm_encoder *enc)
+{
+	/* try allocating only one CDM block */
+	if (!rm->cdm_blk) {
+		DPU_ERROR("CDM block does not exist\n");
+		return -EIO;
+	}
+
+	if (global_state->cdm_to_enc_id) {
+		DPU_ERROR("CDM_0 is already allocated\n");
+		return -EIO;
+	}
+
+	global_state->cdm_to_enc_id = enc->base.id;
+
+	return 0;
+}
+
 static int _dpu_rm_make_reservation(
 		struct dpu_rm *rm,
 		struct dpu_global_state *global_state,
@@ -530,15 +552,25 @@ static int _dpu_rm_make_reservation(
 	if (ret)
 		return ret;
 
+	if (reqs->needs_cdm) {
+		ret = _dpu_rm_reserve_cdm(rm, global_state, enc);
+		if (ret) {
+			DPU_ERROR("unable to find CDM blk\n");
+			return ret;
+		}
+	}
+
 	return ret;
 }
 
 static int _dpu_rm_populate_requirements(
 		struct drm_encoder *enc,
 		struct dpu_rm_requirements *reqs,
-		struct msm_display_topology req_topology)
+		struct msm_display_topology req_topology,
+		bool needs_cdm)
 {
 	reqs->topology = req_topology;
+	reqs->needs_cdm = needs_cdm;
 
 	DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
 		      reqs->topology.num_lm, reqs->topology.num_dsc,
@@ -571,6 +603,7 @@ void dpu_rm_release(struct dpu_global_state *global_state,
 		ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
 	_dpu_rm_clear_mapping(global_state->dspp_to_enc_id,
 		ARRAY_SIZE(global_state->dspp_to_enc_id), enc->base.id);
+	_dpu_rm_clear_mapping(&global_state->cdm_to_enc_id, 1, enc->base.id);
 }
 
 int dpu_rm_reserve(
@@ -578,7 +611,8 @@ int dpu_rm_reserve(
 		struct dpu_global_state *global_state,
 		struct drm_encoder *enc,
 		struct drm_crtc_state *crtc_state,
-		struct msm_display_topology topology)
+		struct msm_display_topology topology,
+		bool needs_cdm)
 {
 	struct dpu_rm_requirements reqs;
 	int ret;
@@ -595,7 +629,7 @@ int dpu_rm_reserve(
 	DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
 		      enc->base.id, crtc_state->crtc->base.id);
 
-	ret = _dpu_rm_populate_requirements(enc, &reqs, topology);
+	ret = _dpu_rm_populate_requirements(enc, &reqs, topology, needs_cdm);
 	if (ret) {
 		DPU_ERROR("failed to populate hw requirements\n");
 		return ret;
@@ -644,6 +678,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
 		hw_to_enc_id = global_state->dsc_to_enc_id;
 		max_blks = ARRAY_SIZE(rm->dsc_blks);
 		break;
+	case DPU_HW_BLK_CDM:
+		hw_blks = &rm->cdm_blk;
+		hw_to_enc_id = &global_state->cdm_to_enc_id;
+		max_blks = 1;
+		break;
 	default:
 		DPU_ERROR("blk type %d not managed by rm\n", type);
 		return 0;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index 29b221491926..74262d3cb6c3 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -69,13 +69,15 @@ int dpu_rm_destroy(struct dpu_rm *rm);
  * @drm_enc: DRM Encoder handle
  * @crtc_state: Proposed Atomic DRM CRTC State handle
  * @topology: Pointer to topology info for the display
+ * @needs_cdm: bool to indicate whether current encoder needs CDM
  * @Return: 0 on Success otherwise -ERROR
  */
 int dpu_rm_reserve(struct dpu_rm *rm,
 		struct dpu_global_state *global_state,
 		struct drm_encoder *drm_enc,
 		struct drm_crtc_state *crtc_state,
-		struct msm_display_topology topology);
+		struct msm_display_topology topology,
+		bool needs_cdm);
 
 /**
  * dpu_rm_reserve - Given the encoder for the display chain, release any
-- 
2.40.1


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

* [PATCH 09/16] drm/msm/dpu: add CDM related logic to dpu_hw_ctl layer
  2023-08-30 22:48 [PATCH 00/16] Add CDM support for MSM writeback Abhinav Kumar
@ 2023-08-30 22:49   ` Abhinav Kumar
  2023-08-30 22:48   ` Abhinav Kumar
                     ` (14 subsequent siblings)
  15 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:49 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: dri-devel, quic_jesszhan, quic_parellan, quic_khsieh,
	linux-arm-msm, linux-kernel

CDM block will need its own logic to program the flush and active
bits in the dpu_hw_ctl layer.

Make necessary changes in dpu_hw_ctl to support CDM programming.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 34 ++++++++++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 11 +++++++
 2 files changed, 45 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 c278fb9d2b5b..beced9f19740 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -29,11 +29,13 @@
 #define   CTL_DSC_ACTIVE                0x0E8
 #define   CTL_WB_ACTIVE                 0x0EC
 #define   CTL_INTF_ACTIVE               0x0F4
+#define   CTL_CDM_ACTIVE                0x0F8
 #define   CTL_FETCH_PIPE_ACTIVE         0x0FC
 #define   CTL_MERGE_3D_FLUSH            0x100
 #define   CTL_DSC_FLUSH                0x104
 #define   CTL_WB_FLUSH                  0x108
 #define   CTL_INTF_FLUSH                0x110
+#define   CTL_CDM_FLUSH                0x114
 #define   CTL_INTF_MASTER               0x134
 #define   CTL_DSPP_n_FLUSH(n)           ((0x13C) + ((n) * 4))
 
@@ -43,6 +45,7 @@
 #define DPU_REG_RESET_TIMEOUT_US        2000
 #define  MERGE_3D_IDX   23
 #define  DSC_IDX        22
+#define CDM_IDX         26
 #define  INTF_IDX       31
 #define WB_IDX          16
 #define  DSPP_IDX       29  /* From DPU hw rev 7.x.x */
@@ -104,6 +107,7 @@ static inline void dpu_hw_ctl_clear_pending_flush(struct dpu_hw_ctl *ctx)
 	ctx->pending_wb_flush_mask = 0;
 	ctx->pending_merge_3d_flush_mask = 0;
 	ctx->pending_dsc_flush_mask = 0;
+	ctx->pending_cdm_flush_mask = 0;
 
 	memset(ctx->pending_dspp_flush_mask, 0,
 		sizeof(ctx->pending_dspp_flush_mask));
@@ -148,6 +152,10 @@ static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
 		DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH,
 			      ctx->pending_dsc_flush_mask);
 
+	if (ctx->pending_flush_mask & BIT(CDM_IDX))
+		DPU_REG_WRITE(&ctx->hw, CTL_CDM_FLUSH,
+			      ctx->pending_cdm_flush_mask);
+
 	DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask);
 }
 
@@ -273,6 +281,12 @@ static void dpu_hw_ctl_update_pending_flush_wb(struct dpu_hw_ctl *ctx,
 	}
 }
 
+static void dpu_hw_ctl_update_pending_flush_cdm(struct dpu_hw_ctl *ctx)
+{
+	ctx->pending_flush_mask |= BIT(CDM_IDX);
+
+}
+
 static void dpu_hw_ctl_update_pending_flush_wb_v1(struct dpu_hw_ctl *ctx,
 		enum dpu_wb wb)
 {
@@ -301,6 +315,12 @@ static void dpu_hw_ctl_update_pending_flush_dsc_v1(struct dpu_hw_ctl *ctx,
 	ctx->pending_flush_mask |= BIT(DSC_IDX);
 }
 
+static void dpu_hw_ctl_update_pending_flush_cdm_v1(struct dpu_hw_ctl *ctx)
+{
+	ctx->pending_cdm_flush_mask |= BIT(0);
+	ctx->pending_flush_mask |= BIT(CDM_IDX);
+}
+
 static void dpu_hw_ctl_update_pending_flush_dspp(struct dpu_hw_ctl *ctx,
 	enum dpu_dspp dspp, u32 dspp_sub_blk)
 {
@@ -504,6 +524,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
 	u32 intf_active = 0;
 	u32 wb_active = 0;
 	u32 mode_sel = 0;
+	u32 cdm_active = 0;
 
 	/* CTL_TOP[31:28] carries group_id to collate CTL paths
 	 * per VM. Explicitly disable it until VM support is
@@ -517,6 +538,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
 
 	intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE);
 	wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE);
+	cdm_active = DPU_REG_READ(c, CTL_CDM_ACTIVE);
 
 	if (cfg->intf)
 		intf_active |= BIT(cfg->intf - INTF_0);
@@ -534,6 +556,9 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
 
 	if (cfg->dsc)
 		DPU_REG_WRITE(c, CTL_DSC_ACTIVE, cfg->dsc);
+
+	if (cfg->cdm)
+		DPU_REG_WRITE(c, CTL_CDM_ACTIVE, cfg->cdm);
 }
 
 static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
@@ -577,6 +602,7 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx,
 	u32 wb_active = 0;
 	u32 merge3d_active = 0;
 	u32 dsc_active;
+	u32 cdm_active;
 
 	/*
 	 * This API resets each portion of the CTL path namely,
@@ -612,6 +638,12 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx,
 		dsc_active &= ~cfg->dsc;
 		DPU_REG_WRITE(c, CTL_DSC_ACTIVE, dsc_active);
 	}
+
+	if (cfg->cdm) {
+		cdm_active = DPU_REG_READ(c, CTL_CDM_ACTIVE);
+		cdm_active &= ~cfg->cdm;
+		DPU_REG_WRITE(c, CTL_CDM_ACTIVE, cdm_active);
+	}
 }
 
 static void dpu_hw_ctl_set_fetch_pipe_active(struct dpu_hw_ctl *ctx,
@@ -645,12 +677,14 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
 		ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb_v1;
 		ops->update_pending_flush_dsc =
 			dpu_hw_ctl_update_pending_flush_dsc_v1;
+		ops->update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm_v1;
 	} else {
 		ops->trigger_flush = dpu_hw_ctl_trigger_flush;
 		ops->setup_intf_cfg = dpu_hw_ctl_intf_cfg;
 		ops->update_pending_flush_intf =
 			dpu_hw_ctl_update_pending_flush_intf;
 		ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb;
+		ops->update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm;
 	}
 	ops->clear_pending_flush = dpu_hw_ctl_clear_pending_flush;
 	ops->update_pending_flush = dpu_hw_ctl_update_pending_flush;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
index 1c242298ff2e..6dd44dfdfb61 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -39,6 +39,7 @@ struct dpu_hw_stage_cfg {
  * @mode_3d:               3d mux configuration
  * @merge_3d:              3d merge block used
  * @intf_mode_sel:         Interface mode, cmd / vid
+ * @cdm:                   CDM block used
  * @stream_sel:            Stream selection for multi-stream interfaces
  * @dsc:                   DSC BIT masks used
  */
@@ -48,6 +49,7 @@ struct dpu_hw_intf_cfg {
 	enum dpu_3d_blend_mode mode_3d;
 	enum dpu_merge_3d merge_3d;
 	enum dpu_ctl_mode_sel intf_mode_sel;
+	enum dpu_cdm cdm;
 	int stream_sel;
 	unsigned int dsc;
 };
@@ -166,6 +168,13 @@ struct dpu_hw_ctl_ops {
 	void (*update_pending_flush_dsc)(struct dpu_hw_ctl *ctx,
 					 enum dpu_dsc blk);
 
+	/**
+	 * OR in the given flushbits to the cached pending_(cdm_)flush_mask
+	 * No effect on hardware
+	 * @ctx: ctl path ctx pointer
+	 */
+	void (*update_pending_flush_cdm)(struct dpu_hw_ctl *ctx);
+
 	/**
 	 * Write the value of the pending_flush_mask to hardware
 	 * @ctx       : ctl path ctx pointer
@@ -239,6 +248,7 @@ struct dpu_hw_ctl_ops {
  * @pending_intf_flush_mask: pending INTF flush
  * @pending_wb_flush_mask: pending WB flush
  * @pending_dsc_flush_mask: pending DSC flush
+ * @pending_cdm_flush_mask: pending CDM flush
  * @ops: operation list
  */
 struct dpu_hw_ctl {
@@ -256,6 +266,7 @@ struct dpu_hw_ctl {
 	u32 pending_merge_3d_flush_mask;
 	u32 pending_dspp_flush_mask[DSPP_MAX - DSPP_0];
 	u32 pending_dsc_flush_mask;
+	u32 pending_cdm_flush_mask;
 
 	/* ops */
 	struct dpu_hw_ctl_ops ops;
-- 
2.40.1


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

* [PATCH 09/16] drm/msm/dpu: add CDM related logic to dpu_hw_ctl layer
@ 2023-08-30 22:49   ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:49 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan

CDM block will need its own logic to program the flush and active
bits in the dpu_hw_ctl layer.

Make necessary changes in dpu_hw_ctl to support CDM programming.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 34 ++++++++++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 11 +++++++
 2 files changed, 45 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 c278fb9d2b5b..beced9f19740 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -29,11 +29,13 @@
 #define   CTL_DSC_ACTIVE                0x0E8
 #define   CTL_WB_ACTIVE                 0x0EC
 #define   CTL_INTF_ACTIVE               0x0F4
+#define   CTL_CDM_ACTIVE                0x0F8
 #define   CTL_FETCH_PIPE_ACTIVE         0x0FC
 #define   CTL_MERGE_3D_FLUSH            0x100
 #define   CTL_DSC_FLUSH                0x104
 #define   CTL_WB_FLUSH                  0x108
 #define   CTL_INTF_FLUSH                0x110
+#define   CTL_CDM_FLUSH                0x114
 #define   CTL_INTF_MASTER               0x134
 #define   CTL_DSPP_n_FLUSH(n)           ((0x13C) + ((n) * 4))
 
@@ -43,6 +45,7 @@
 #define DPU_REG_RESET_TIMEOUT_US        2000
 #define  MERGE_3D_IDX   23
 #define  DSC_IDX        22
+#define CDM_IDX         26
 #define  INTF_IDX       31
 #define WB_IDX          16
 #define  DSPP_IDX       29  /* From DPU hw rev 7.x.x */
@@ -104,6 +107,7 @@ static inline void dpu_hw_ctl_clear_pending_flush(struct dpu_hw_ctl *ctx)
 	ctx->pending_wb_flush_mask = 0;
 	ctx->pending_merge_3d_flush_mask = 0;
 	ctx->pending_dsc_flush_mask = 0;
+	ctx->pending_cdm_flush_mask = 0;
 
 	memset(ctx->pending_dspp_flush_mask, 0,
 		sizeof(ctx->pending_dspp_flush_mask));
@@ -148,6 +152,10 @@ static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
 		DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH,
 			      ctx->pending_dsc_flush_mask);
 
+	if (ctx->pending_flush_mask & BIT(CDM_IDX))
+		DPU_REG_WRITE(&ctx->hw, CTL_CDM_FLUSH,
+			      ctx->pending_cdm_flush_mask);
+
 	DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask);
 }
 
@@ -273,6 +281,12 @@ static void dpu_hw_ctl_update_pending_flush_wb(struct dpu_hw_ctl *ctx,
 	}
 }
 
+static void dpu_hw_ctl_update_pending_flush_cdm(struct dpu_hw_ctl *ctx)
+{
+	ctx->pending_flush_mask |= BIT(CDM_IDX);
+
+}
+
 static void dpu_hw_ctl_update_pending_flush_wb_v1(struct dpu_hw_ctl *ctx,
 		enum dpu_wb wb)
 {
@@ -301,6 +315,12 @@ static void dpu_hw_ctl_update_pending_flush_dsc_v1(struct dpu_hw_ctl *ctx,
 	ctx->pending_flush_mask |= BIT(DSC_IDX);
 }
 
+static void dpu_hw_ctl_update_pending_flush_cdm_v1(struct dpu_hw_ctl *ctx)
+{
+	ctx->pending_cdm_flush_mask |= BIT(0);
+	ctx->pending_flush_mask |= BIT(CDM_IDX);
+}
+
 static void dpu_hw_ctl_update_pending_flush_dspp(struct dpu_hw_ctl *ctx,
 	enum dpu_dspp dspp, u32 dspp_sub_blk)
 {
@@ -504,6 +524,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
 	u32 intf_active = 0;
 	u32 wb_active = 0;
 	u32 mode_sel = 0;
+	u32 cdm_active = 0;
 
 	/* CTL_TOP[31:28] carries group_id to collate CTL paths
 	 * per VM. Explicitly disable it until VM support is
@@ -517,6 +538,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
 
 	intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE);
 	wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE);
+	cdm_active = DPU_REG_READ(c, CTL_CDM_ACTIVE);
 
 	if (cfg->intf)
 		intf_active |= BIT(cfg->intf - INTF_0);
@@ -534,6 +556,9 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
 
 	if (cfg->dsc)
 		DPU_REG_WRITE(c, CTL_DSC_ACTIVE, cfg->dsc);
+
+	if (cfg->cdm)
+		DPU_REG_WRITE(c, CTL_CDM_ACTIVE, cfg->cdm);
 }
 
 static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
@@ -577,6 +602,7 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx,
 	u32 wb_active = 0;
 	u32 merge3d_active = 0;
 	u32 dsc_active;
+	u32 cdm_active;
 
 	/*
 	 * This API resets each portion of the CTL path namely,
@@ -612,6 +638,12 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx,
 		dsc_active &= ~cfg->dsc;
 		DPU_REG_WRITE(c, CTL_DSC_ACTIVE, dsc_active);
 	}
+
+	if (cfg->cdm) {
+		cdm_active = DPU_REG_READ(c, CTL_CDM_ACTIVE);
+		cdm_active &= ~cfg->cdm;
+		DPU_REG_WRITE(c, CTL_CDM_ACTIVE, cdm_active);
+	}
 }
 
 static void dpu_hw_ctl_set_fetch_pipe_active(struct dpu_hw_ctl *ctx,
@@ -645,12 +677,14 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
 		ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb_v1;
 		ops->update_pending_flush_dsc =
 			dpu_hw_ctl_update_pending_flush_dsc_v1;
+		ops->update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm_v1;
 	} else {
 		ops->trigger_flush = dpu_hw_ctl_trigger_flush;
 		ops->setup_intf_cfg = dpu_hw_ctl_intf_cfg;
 		ops->update_pending_flush_intf =
 			dpu_hw_ctl_update_pending_flush_intf;
 		ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb;
+		ops->update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm;
 	}
 	ops->clear_pending_flush = dpu_hw_ctl_clear_pending_flush;
 	ops->update_pending_flush = dpu_hw_ctl_update_pending_flush;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
index 1c242298ff2e..6dd44dfdfb61 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -39,6 +39,7 @@ struct dpu_hw_stage_cfg {
  * @mode_3d:               3d mux configuration
  * @merge_3d:              3d merge block used
  * @intf_mode_sel:         Interface mode, cmd / vid
+ * @cdm:                   CDM block used
  * @stream_sel:            Stream selection for multi-stream interfaces
  * @dsc:                   DSC BIT masks used
  */
@@ -48,6 +49,7 @@ struct dpu_hw_intf_cfg {
 	enum dpu_3d_blend_mode mode_3d;
 	enum dpu_merge_3d merge_3d;
 	enum dpu_ctl_mode_sel intf_mode_sel;
+	enum dpu_cdm cdm;
 	int stream_sel;
 	unsigned int dsc;
 };
@@ -166,6 +168,13 @@ struct dpu_hw_ctl_ops {
 	void (*update_pending_flush_dsc)(struct dpu_hw_ctl *ctx,
 					 enum dpu_dsc blk);
 
+	/**
+	 * OR in the given flushbits to the cached pending_(cdm_)flush_mask
+	 * No effect on hardware
+	 * @ctx: ctl path ctx pointer
+	 */
+	void (*update_pending_flush_cdm)(struct dpu_hw_ctl *ctx);
+
 	/**
 	 * Write the value of the pending_flush_mask to hardware
 	 * @ctx       : ctl path ctx pointer
@@ -239,6 +248,7 @@ struct dpu_hw_ctl_ops {
  * @pending_intf_flush_mask: pending INTF flush
  * @pending_wb_flush_mask: pending WB flush
  * @pending_dsc_flush_mask: pending DSC flush
+ * @pending_cdm_flush_mask: pending CDM flush
  * @ops: operation list
  */
 struct dpu_hw_ctl {
@@ -256,6 +266,7 @@ struct dpu_hw_ctl {
 	u32 pending_merge_3d_flush_mask;
 	u32 pending_dspp_flush_mask[DSPP_MAX - DSPP_0];
 	u32 pending_dsc_flush_mask;
+	u32 pending_cdm_flush_mask;
 
 	/* ops */
 	struct dpu_hw_ctl_ops ops;
-- 
2.40.1


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

* [PATCH 10/16] drm/msm/dpu: add support to disable CDM block during encoder cleanup
  2023-08-30 22:48 [PATCH 00/16] Add CDM support for MSM writeback Abhinav Kumar
@ 2023-08-30 22:49   ` Abhinav Kumar
  2023-08-30 22:48   ` Abhinav Kumar
                     ` (14 subsequent siblings)
  15 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:49 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: dri-devel, quic_jesszhan, quic_parellan, quic_khsieh,
	linux-arm-msm, linux-kernel

In preparation of setting up CDM block, add the logic to disable it
properly during encoder cleanup.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c      | 8 ++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 2 ++
 2 files changed, 10 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 582680804016..1b1e07292a9e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -26,6 +26,7 @@
 #include "dpu_hw_dspp.h"
 #include "dpu_hw_dsc.h"
 #include "dpu_hw_merge3d.h"
+#include "dpu_hw_cdm.h"
 #include "dpu_formats.h"
 #include "dpu_encoder_phys.h"
 #include "dpu_crtc.h"
@@ -2097,6 +2098,13 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
 					phys_enc->hw_pp->merge_3d->idx);
 	}
 
+	if (phys_enc->hw_cdm && phys_enc->hw_cdm->ops.bind_pingpong_blk && phys_enc->hw_pp) {
+		phys_enc->hw_cdm->ops.bind_pingpong_blk(phys_enc->hw_cdm,
+							false, phys_enc->hw_pp->idx);
+		if (phys_enc->hw_ctl->ops.update_pending_flush_cdm)
+			phys_enc->hw_ctl->ops.update_pending_flush_cdm(phys_enc->hw_ctl);
+	}
+
 	if (dpu_enc->dsc) {
 		dpu_encoder_unprep_dsc(dpu_enc);
 		dpu_enc->dsc = NULL;
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 24dbc28be4f8..510c1c41ddbc 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -150,6 +150,7 @@ enum dpu_intr_idx {
  * @hw_pp:		Hardware interface to the ping pong registers
  * @hw_intf:		Hardware interface to the intf registers
  * @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
  * @cached_mode:	DRM mode cached at mode_set time, acted on in enable
  * @enabled:		Whether the encoder has enabled and running a mode
@@ -178,6 +179,7 @@ struct dpu_encoder_phys {
 	struct dpu_hw_pingpong *hw_pp;
 	struct dpu_hw_intf *hw_intf;
 	struct dpu_hw_wb *hw_wb;
+	struct dpu_hw_cdm *hw_cdm;
 	struct dpu_kms *dpu_kms;
 	struct drm_display_mode cached_mode;
 	enum dpu_enc_split_role split_role;
-- 
2.40.1


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

* [PATCH 10/16] drm/msm/dpu: add support to disable CDM block during encoder cleanup
@ 2023-08-30 22:49   ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:49 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan

In preparation of setting up CDM block, add the logic to disable it
properly during encoder cleanup.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c      | 8 ++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 2 ++
 2 files changed, 10 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 582680804016..1b1e07292a9e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -26,6 +26,7 @@
 #include "dpu_hw_dspp.h"
 #include "dpu_hw_dsc.h"
 #include "dpu_hw_merge3d.h"
+#include "dpu_hw_cdm.h"
 #include "dpu_formats.h"
 #include "dpu_encoder_phys.h"
 #include "dpu_crtc.h"
@@ -2097,6 +2098,13 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
 					phys_enc->hw_pp->merge_3d->idx);
 	}
 
+	if (phys_enc->hw_cdm && phys_enc->hw_cdm->ops.bind_pingpong_blk && phys_enc->hw_pp) {
+		phys_enc->hw_cdm->ops.bind_pingpong_blk(phys_enc->hw_cdm,
+							false, phys_enc->hw_pp->idx);
+		if (phys_enc->hw_ctl->ops.update_pending_flush_cdm)
+			phys_enc->hw_ctl->ops.update_pending_flush_cdm(phys_enc->hw_ctl);
+	}
+
 	if (dpu_enc->dsc) {
 		dpu_encoder_unprep_dsc(dpu_enc);
 		dpu_enc->dsc = NULL;
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 24dbc28be4f8..510c1c41ddbc 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -150,6 +150,7 @@ enum dpu_intr_idx {
  * @hw_pp:		Hardware interface to the ping pong registers
  * @hw_intf:		Hardware interface to the intf registers
  * @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
  * @cached_mode:	DRM mode cached at mode_set time, acted on in enable
  * @enabled:		Whether the encoder has enabled and running a mode
@@ -178,6 +179,7 @@ struct dpu_encoder_phys {
 	struct dpu_hw_pingpong *hw_pp;
 	struct dpu_hw_intf *hw_intf;
 	struct dpu_hw_wb *hw_wb;
+	struct dpu_hw_cdm *hw_cdm;
 	struct dpu_kms *dpu_kms;
 	struct drm_display_mode cached_mode;
 	enum dpu_enc_split_role split_role;
-- 
2.40.1


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

* [PATCH 11/16] drm/msm/dpu: add an API to setup the CDM block for writeback
  2023-08-30 22:48 [PATCH 00/16] Add CDM support for MSM writeback Abhinav Kumar
@ 2023-08-30 22:49   ` Abhinav Kumar
  2023-08-30 22:48   ` Abhinav Kumar
                     ` (14 subsequent siblings)
  15 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:49 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: dri-devel, quic_jesszhan, quic_parellan, quic_khsieh,
	linux-arm-msm, linux-kernel

Add an API dpu_encoder_helper_phys_setup_cdm() which can be used by
the writeback encoder to setup the CDM block.

Currently, this is defined and used within the writeback's physical
encoder layer however, the function can be modified to be used to setup
the CDM block even for non-writeback interfaces.

Until those modifications are planned and made, keep it local to
writeback.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   3 +
 .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 123 +++++++++++++++++-
 2 files changed, 125 insertions(+), 1 deletion(-)

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 510c1c41ddbc..93a8ae67beff 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -16,6 +16,7 @@
 #include "dpu_hw_pingpong.h"
 #include "dpu_hw_ctl.h"
 #include "dpu_hw_top.h"
+#include "dpu_hw_cdm.h"
 #include "dpu_encoder.h"
 #include "dpu_crtc.h"
 
@@ -209,6 +210,7 @@ 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
@@ -218,6 +220,7 @@ 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 4c2736c3ee6d..11935aac9fd5 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
@@ -24,6 +24,20 @@
 #define to_dpu_encoder_phys_wb(x) \
 	container_of(x, struct dpu_encoder_phys_wb, base)
 
+#define TO_S15D16(_x_)((_x_) << 7)
+
+static struct dpu_csc_cfg dpu_encoder_phys_wb_rgb2yuv_601l = {
+	{
+		TO_S15D16(0x0083), TO_S15D16(0x0102), TO_S15D16(0x0032),
+		TO_S15D16(0x1fb5), TO_S15D16(0x1f6c), TO_S15D16(0x00e1),
+		TO_S15D16(0x00e1), TO_S15D16(0x1f45), TO_S15D16(0x1fdc)
+	},
+	{ 0x00, 0x00, 0x00 },
+	{ 0x0040, 0x0200, 0x0200 },
+	{ 0x000, 0x3ff, 0x000, 0x3ff, 0x000, 0x3ff },
+	{ 0x040, 0x3ac, 0x040, 0x3c0, 0x040, 0x3c0 },
+};
+
 /**
  * dpu_encoder_phys_wb_is_master - report wb always as master encoder
  * @phys_enc:	Pointer to physical encoder
@@ -225,6 +239,112 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
 	}
 }
 
+/**
+ * dpu_encoder_phys_wb_setup_cdp - setup chroma down sampling block
+ * @phys_enc:Pointer to physical encoder
+ */
+static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
+{
+	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;
+	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;
+
+	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.disable)
+			hw_cdm->ops.disable(hw_cdm);
+
+		return;
+	}
+
+	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_fmt = dpu_fmt;
+	cdm_cfg->output_type = CDM_CDWN_OUTPUT_WB;
+	cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
+			CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
+
+	/* 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 && hw_cdm->ops.setup_csc_data) {
+		ret = hw_cdm->ops.setup_csc_data(hw_cdm, &dpu_encoder_phys_wb_rgb2yuv_601l);
+		if (ret < 0) {
+			DPU_ERROR("[enc:%d] failed to setup CSC; ret:%d\n",
+				  DRMID(phys_enc->parent), ret);
+			return;
+		}
+	}
+
+	if (hw_cdm && hw_cdm->ops.setup_cdwn) {
+		ret = hw_cdm->ops.setup_cdwn(hw_cdm, cdm_cfg);
+		if (ret < 0) {
+			DPU_ERROR("[enc:%d] failed to setup CDWN; ret:%d\n",
+				  DRMID(phys_enc->parent), ret);
+			return;
+		}
+	}
+
+	if (hw_cdm && hw_pp && 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
@@ -348,8 +468,9 @@ static void dpu_encoder_phys_wb_setup(
 
 	dpu_encoder_phys_wb_setup_fb(phys_enc, fb);
 
-	dpu_encoder_phys_wb_setup_ctl(phys_enc);
+	dpu_encoder_helper_phys_setup_cdm(phys_enc);
 
+	dpu_encoder_phys_wb_setup_ctl(phys_enc);
 }
 
 static void _dpu_encoder_phys_wb_frame_done_helper(void *arg)
-- 
2.40.1


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

* [PATCH 11/16] drm/msm/dpu: add an API to setup the CDM block for writeback
@ 2023-08-30 22:49   ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:49 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan

Add an API dpu_encoder_helper_phys_setup_cdm() which can be used by
the writeback encoder to setup the CDM block.

Currently, this is defined and used within the writeback's physical
encoder layer however, the function can be modified to be used to setup
the CDM block even for non-writeback interfaces.

Until those modifications are planned and made, keep it local to
writeback.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   3 +
 .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 123 +++++++++++++++++-
 2 files changed, 125 insertions(+), 1 deletion(-)

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 510c1c41ddbc..93a8ae67beff 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -16,6 +16,7 @@
 #include "dpu_hw_pingpong.h"
 #include "dpu_hw_ctl.h"
 #include "dpu_hw_top.h"
+#include "dpu_hw_cdm.h"
 #include "dpu_encoder.h"
 #include "dpu_crtc.h"
 
@@ -209,6 +210,7 @@ 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
@@ -218,6 +220,7 @@ 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 4c2736c3ee6d..11935aac9fd5 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
@@ -24,6 +24,20 @@
 #define to_dpu_encoder_phys_wb(x) \
 	container_of(x, struct dpu_encoder_phys_wb, base)
 
+#define TO_S15D16(_x_)((_x_) << 7)
+
+static struct dpu_csc_cfg dpu_encoder_phys_wb_rgb2yuv_601l = {
+	{
+		TO_S15D16(0x0083), TO_S15D16(0x0102), TO_S15D16(0x0032),
+		TO_S15D16(0x1fb5), TO_S15D16(0x1f6c), TO_S15D16(0x00e1),
+		TO_S15D16(0x00e1), TO_S15D16(0x1f45), TO_S15D16(0x1fdc)
+	},
+	{ 0x00, 0x00, 0x00 },
+	{ 0x0040, 0x0200, 0x0200 },
+	{ 0x000, 0x3ff, 0x000, 0x3ff, 0x000, 0x3ff },
+	{ 0x040, 0x3ac, 0x040, 0x3c0, 0x040, 0x3c0 },
+};
+
 /**
  * dpu_encoder_phys_wb_is_master - report wb always as master encoder
  * @phys_enc:	Pointer to physical encoder
@@ -225,6 +239,112 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
 	}
 }
 
+/**
+ * dpu_encoder_phys_wb_setup_cdp - setup chroma down sampling block
+ * @phys_enc:Pointer to physical encoder
+ */
+static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
+{
+	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;
+	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;
+
+	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.disable)
+			hw_cdm->ops.disable(hw_cdm);
+
+		return;
+	}
+
+	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_fmt = dpu_fmt;
+	cdm_cfg->output_type = CDM_CDWN_OUTPUT_WB;
+	cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
+			CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
+
+	/* 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 && hw_cdm->ops.setup_csc_data) {
+		ret = hw_cdm->ops.setup_csc_data(hw_cdm, &dpu_encoder_phys_wb_rgb2yuv_601l);
+		if (ret < 0) {
+			DPU_ERROR("[enc:%d] failed to setup CSC; ret:%d\n",
+				  DRMID(phys_enc->parent), ret);
+			return;
+		}
+	}
+
+	if (hw_cdm && hw_cdm->ops.setup_cdwn) {
+		ret = hw_cdm->ops.setup_cdwn(hw_cdm, cdm_cfg);
+		if (ret < 0) {
+			DPU_ERROR("[enc:%d] failed to setup CDWN; ret:%d\n",
+				  DRMID(phys_enc->parent), ret);
+			return;
+		}
+	}
+
+	if (hw_cdm && hw_pp && 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
@@ -348,8 +468,9 @@ static void dpu_encoder_phys_wb_setup(
 
 	dpu_encoder_phys_wb_setup_fb(phys_enc, fb);
 
-	dpu_encoder_phys_wb_setup_ctl(phys_enc);
+	dpu_encoder_helper_phys_setup_cdm(phys_enc);
 
+	dpu_encoder_phys_wb_setup_ctl(phys_enc);
 }
 
 static void _dpu_encoder_phys_wb_frame_done_helper(void *arg)
-- 
2.40.1


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

* [PATCH 12/16] drm/msm/dpu: plug-in the cdm related bits to writeback setup
  2023-08-30 22:48 [PATCH 00/16] Add CDM support for MSM writeback Abhinav Kumar
@ 2023-08-30 22:49   ` Abhinav Kumar
  2023-08-30 22:48   ` Abhinav Kumar
                     ` (14 subsequent siblings)
  15 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:49 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: dri-devel, quic_jesszhan, quic_parellan, quic_khsieh,
	linux-arm-msm, linux-kernel

To setup and enable CDM block for the writeback pipeline, lets
add the pieces together to set the active bits and the flush
bits for the CDM block.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

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 11935aac9fd5..7fc174b33ae2 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
@@ -194,6 +194,7 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
 {
 	struct dpu_hw_wb *hw_wb;
 	struct dpu_hw_ctl *ctl;
+	struct dpu_hw_cdm *hw_cdm;
 
 	if (!phys_enc) {
 		DPU_ERROR("invalid encoder\n");
@@ -202,6 +203,7 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
 
 	hw_wb = phys_enc->hw_wb;
 	ctl = phys_enc->hw_ctl;
+	hw_cdm = phys_enc->hw_cdm;
 
 	if (test_bit(DPU_CTL_ACTIVE_CFG, &ctl->caps->features) &&
 		(phys_enc->hw_ctl &&
@@ -218,6 +220,9 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
 		if (mode_3d && hw_pp && hw_pp->merge_3d)
 			intf_cfg.merge_3d = hw_pp->merge_3d->idx;
 
+		if (hw_cdm)
+			intf_cfg.cdm = hw_cdm->idx;
+
 		if (phys_enc->hw_pp->merge_3d && phys_enc->hw_pp->merge_3d->ops.setup_3d_mode)
 			phys_enc->hw_pp->merge_3d->ops.setup_3d_mode(phys_enc->hw_pp->merge_3d,
 					mode_3d);
@@ -414,6 +419,7 @@ static void _dpu_encoder_phys_wb_update_flush(struct dpu_encoder_phys *phys_enc)
 	struct dpu_hw_wb *hw_wb;
 	struct dpu_hw_ctl *hw_ctl;
 	struct dpu_hw_pingpong *hw_pp;
+	struct dpu_hw_cdm *hw_cdm;
 	u32 pending_flush = 0;
 
 	if (!phys_enc)
@@ -422,6 +428,7 @@ static void _dpu_encoder_phys_wb_update_flush(struct dpu_encoder_phys *phys_enc)
 	hw_wb = phys_enc->hw_wb;
 	hw_pp = phys_enc->hw_pp;
 	hw_ctl = phys_enc->hw_ctl;
+	hw_cdm = phys_enc->hw_cdm;
 
 	DPU_DEBUG("[wb:%d]\n", hw_wb->idx - WB_0);
 
@@ -437,6 +444,9 @@ static void _dpu_encoder_phys_wb_update_flush(struct dpu_encoder_phys *phys_enc)
 		hw_ctl->ops.update_pending_flush_merge_3d(hw_ctl,
 				hw_pp->merge_3d->idx);
 
+	if (hw_cdm && hw_ctl->ops.update_pending_flush_cdm)
+		hw_ctl->ops.update_pending_flush_cdm(hw_ctl);
+
 	if (hw_ctl->ops.get_pending_flush)
 		pending_flush = hw_ctl->ops.get_pending_flush(hw_ctl);
 
-- 
2.40.1


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

* [PATCH 12/16] drm/msm/dpu: plug-in the cdm related bits to writeback setup
@ 2023-08-30 22:49   ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:49 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan

To setup and enable CDM block for the writeback pipeline, lets
add the pieces together to set the active bits and the flush
bits for the CDM block.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

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 11935aac9fd5..7fc174b33ae2 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
@@ -194,6 +194,7 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
 {
 	struct dpu_hw_wb *hw_wb;
 	struct dpu_hw_ctl *ctl;
+	struct dpu_hw_cdm *hw_cdm;
 
 	if (!phys_enc) {
 		DPU_ERROR("invalid encoder\n");
@@ -202,6 +203,7 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
 
 	hw_wb = phys_enc->hw_wb;
 	ctl = phys_enc->hw_ctl;
+	hw_cdm = phys_enc->hw_cdm;
 
 	if (test_bit(DPU_CTL_ACTIVE_CFG, &ctl->caps->features) &&
 		(phys_enc->hw_ctl &&
@@ -218,6 +220,9 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
 		if (mode_3d && hw_pp && hw_pp->merge_3d)
 			intf_cfg.merge_3d = hw_pp->merge_3d->idx;
 
+		if (hw_cdm)
+			intf_cfg.cdm = hw_cdm->idx;
+
 		if (phys_enc->hw_pp->merge_3d && phys_enc->hw_pp->merge_3d->ops.setup_3d_mode)
 			phys_enc->hw_pp->merge_3d->ops.setup_3d_mode(phys_enc->hw_pp->merge_3d,
 					mode_3d);
@@ -414,6 +419,7 @@ static void _dpu_encoder_phys_wb_update_flush(struct dpu_encoder_phys *phys_enc)
 	struct dpu_hw_wb *hw_wb;
 	struct dpu_hw_ctl *hw_ctl;
 	struct dpu_hw_pingpong *hw_pp;
+	struct dpu_hw_cdm *hw_cdm;
 	u32 pending_flush = 0;
 
 	if (!phys_enc)
@@ -422,6 +428,7 @@ static void _dpu_encoder_phys_wb_update_flush(struct dpu_encoder_phys *phys_enc)
 	hw_wb = phys_enc->hw_wb;
 	hw_pp = phys_enc->hw_pp;
 	hw_ctl = phys_enc->hw_ctl;
+	hw_cdm = phys_enc->hw_cdm;
 
 	DPU_DEBUG("[wb:%d]\n", hw_wb->idx - WB_0);
 
@@ -437,6 +444,9 @@ static void _dpu_encoder_phys_wb_update_flush(struct dpu_encoder_phys *phys_enc)
 		hw_ctl->ops.update_pending_flush_merge_3d(hw_ctl,
 				hw_pp->merge_3d->idx);
 
+	if (hw_cdm && hw_ctl->ops.update_pending_flush_cdm)
+		hw_ctl->ops.update_pending_flush_cdm(hw_ctl);
+
 	if (hw_ctl->ops.get_pending_flush)
 		pending_flush = hw_ctl->ops.get_pending_flush(hw_ctl);
 
-- 
2.40.1


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

* [PATCH 13/16] drm/msm/dpu: reserve cdm blocks for writeback in case of YUV output
  2023-08-30 22:48 [PATCH 00/16] Add CDM support for MSM writeback Abhinav Kumar
@ 2023-08-30 22:49   ` Abhinav Kumar
  2023-08-30 22:48   ` Abhinav Kumar
                     ` (14 subsequent siblings)
  15 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:49 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan

Reserve CDM blocks for writeback if the format of the output fb
is YUV. At the moment, the reservation is done only for writeback
but can easily be extended by relaxing the checks once other
interfaces are ready to output YUV.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 35 ++++++++++++++++++++-
 1 file changed, 34 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 1b1e07292a9e..7a3d179bdfba 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -16,6 +16,7 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_file.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_framebuffer.h>
 
 #include "msm_drv.h"
 #include "dpu_kms.h"
@@ -615,9 +616,11 @@ static int dpu_encoder_virt_atomic_check(
 	struct drm_display_mode *adj_mode;
 	struct msm_display_topology topology;
 	struct dpu_global_state *global_state;
+	struct drm_framebuffer *fb;
 	struct drm_dsc_config *dsc;
 	int i = 0;
 	int ret = 0;
+	bool needs_cdm = false;
 
 	if (!drm_enc || !crtc_state || !conn_state) {
 		DPU_ERROR("invalid arg(s), drm_enc %d, crtc/conn state %d/%d\n",
@@ -655,6 +658,22 @@ 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()
+	 * earlier.
+	 */
+	if (dpu_enc->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))))
+			needs_cdm = true;
+		if (needs_cdm && !dpu_enc->cur_master->hw_cdm)
+			crtc_state->mode_changed = true;
+		else if (!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.
@@ -664,7 +683,7 @@ static int dpu_encoder_virt_atomic_check(
 
 		if (!crtc_state->active_changed || crtc_state->enable)
 			ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
-					drm_enc, crtc_state, topology, false);
+					drm_enc, crtc_state, topology, needs_cdm);
 	}
 
 	trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
@@ -1126,6 +1145,20 @@ 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) {
+		struct dpu_hw_blk *hw_cdm = NULL;
+		struct drm_framebuffer *fb;
+
+		fb = conn_state->writeback_job->fb;
+
+		if (fb && DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(fb)))) {
+			dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
+						      drm_enc->base.id, DPU_HW_BLK_CDM,
+						      &hw_cdm, 1);
+		}
+		dpu_enc->cur_master->hw_cdm = hw_cdm ? to_dpu_hw_cdm(hw_cdm) : NULL;
+	}
+
 	cstate = to_dpu_crtc_state(crtc_state);
 
 	for (i = 0; i < num_lm; i++) {
-- 
2.40.1


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

* [PATCH 13/16] drm/msm/dpu: reserve cdm blocks for writeback in case of YUV output
@ 2023-08-30 22:49   ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:49 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: dri-devel, quic_jesszhan, quic_parellan, quic_khsieh,
	linux-arm-msm, linux-kernel

Reserve CDM blocks for writeback if the format of the output fb
is YUV. At the moment, the reservation is done only for writeback
but can easily be extended by relaxing the checks once other
interfaces are ready to output YUV.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 35 ++++++++++++++++++++-
 1 file changed, 34 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 1b1e07292a9e..7a3d179bdfba 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -16,6 +16,7 @@
 #include <drm/drm_crtc.h>
 #include <drm/drm_file.h>
 #include <drm/drm_probe_helper.h>
+#include <drm/drm_framebuffer.h>
 
 #include "msm_drv.h"
 #include "dpu_kms.h"
@@ -615,9 +616,11 @@ static int dpu_encoder_virt_atomic_check(
 	struct drm_display_mode *adj_mode;
 	struct msm_display_topology topology;
 	struct dpu_global_state *global_state;
+	struct drm_framebuffer *fb;
 	struct drm_dsc_config *dsc;
 	int i = 0;
 	int ret = 0;
+	bool needs_cdm = false;
 
 	if (!drm_enc || !crtc_state || !conn_state) {
 		DPU_ERROR("invalid arg(s), drm_enc %d, crtc/conn state %d/%d\n",
@@ -655,6 +658,22 @@ 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()
+	 * earlier.
+	 */
+	if (dpu_enc->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))))
+			needs_cdm = true;
+		if (needs_cdm && !dpu_enc->cur_master->hw_cdm)
+			crtc_state->mode_changed = true;
+		else if (!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.
@@ -664,7 +683,7 @@ static int dpu_encoder_virt_atomic_check(
 
 		if (!crtc_state->active_changed || crtc_state->enable)
 			ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
-					drm_enc, crtc_state, topology, false);
+					drm_enc, crtc_state, topology, needs_cdm);
 	}
 
 	trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
@@ -1126,6 +1145,20 @@ 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) {
+		struct dpu_hw_blk *hw_cdm = NULL;
+		struct drm_framebuffer *fb;
+
+		fb = conn_state->writeback_job->fb;
+
+		if (fb && DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(fb)))) {
+			dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
+						      drm_enc->base.id, DPU_HW_BLK_CDM,
+						      &hw_cdm, 1);
+		}
+		dpu_enc->cur_master->hw_cdm = hw_cdm ? to_dpu_hw_cdm(hw_cdm) : NULL;
+	}
+
 	cstate = to_dpu_crtc_state(crtc_state);
 
 	for (i = 0; i < num_lm; i++) {
-- 
2.40.1


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

* [PATCH 14/16] drm/msm/dpu: do not allow YUV formats if no CDM block is present
  2023-08-30 22:48 [PATCH 00/16] Add CDM support for MSM writeback Abhinav Kumar
@ 2023-08-30 22:49   ` Abhinav Kumar
  2023-08-30 22:48   ` Abhinav Kumar
                     ` (14 subsequent siblings)
  15 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:49 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan

On chipsets where CDM block is not available OR where support has
not been added yet do not allow YUV formats for writeback block.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 6 ++++++
 1 file changed, 6 insertions(+)

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 7fc174b33ae2..d8edca9bc964 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
@@ -406,6 +406,12 @@ static int dpu_encoder_phys_wb_atomic_check(
 		return ret;
 	}
 
+	if (DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(fb))) &&
+	    !phys_enc->dpu_kms->catalog->cdm) {
+		DPU_ERROR("cannot support YUV formats without CDM block\n");
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
-- 
2.40.1


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

* [PATCH 14/16] drm/msm/dpu: do not allow YUV formats if no CDM block is present
@ 2023-08-30 22:49   ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:49 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: dri-devel, quic_jesszhan, quic_parellan, quic_khsieh,
	linux-arm-msm, linux-kernel

On chipsets where CDM block is not available OR where support has
not been added yet do not allow YUV formats for writeback block.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 6 ++++++
 1 file changed, 6 insertions(+)

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 7fc174b33ae2..d8edca9bc964 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
@@ -406,6 +406,12 @@ static int dpu_encoder_phys_wb_atomic_check(
 		return ret;
 	}
 
+	if (DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(fb))) &&
+	    !phys_enc->dpu_kms->catalog->cdm) {
+		DPU_ERROR("cannot support YUV formats without CDM block\n");
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
-- 
2.40.1


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

* [PATCH 15/16] drm/msm/dpu: add NV12 in the list of supported WB formats
  2023-08-30 22:48 [PATCH 00/16] Add CDM support for MSM writeback Abhinav Kumar
@ 2023-08-30 22:49   ` Abhinav Kumar
  2023-08-30 22:48   ` Abhinav Kumar
                     ` (14 subsequent siblings)
  15 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:49 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan

Since CDM block support has now been added for writeback blocks
add NV12 in the list of supported WB formats.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index 713dfc079718..978330c6678e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -244,6 +244,7 @@ static const uint32_t wb2_formats[] = {
 	DRM_FORMAT_BGRA4444,
 	DRM_FORMAT_BGRX4444,
 	DRM_FORMAT_XBGR4444,
+	DRM_FORMAT_NV12,
 };
 
 /*************************************************************
-- 
2.40.1


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

* [PATCH 15/16] drm/msm/dpu: add NV12 in the list of supported WB formats
@ 2023-08-30 22:49   ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:49 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: dri-devel, quic_jesszhan, quic_parellan, quic_khsieh,
	linux-arm-msm, linux-kernel

Since CDM block support has now been added for writeback blocks
add NV12 in the list of supported WB formats.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index 713dfc079718..978330c6678e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -244,6 +244,7 @@ static const uint32_t wb2_formats[] = {
 	DRM_FORMAT_BGRA4444,
 	DRM_FORMAT_BGRX4444,
 	DRM_FORMAT_XBGR4444,
+	DRM_FORMAT_NV12,
 };
 
 /*************************************************************
-- 
2.40.1


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

* [PATCH 16/16] drm/msm/dpu: add cdm blocks to dpu snapshot
  2023-08-30 22:48 [PATCH 00/16] Add CDM support for MSM writeback Abhinav Kumar
@ 2023-08-30 22:49   ` Abhinav Kumar
  2023-08-30 22:48   ` Abhinav Kumar
                     ` (14 subsequent siblings)
  15 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:49 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan

Now that CDM block support has been added to DPU lets also add its
entry to the DPU snapshot to help debugging.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index aa6ba2cf4b84..a207b18eb112 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -988,6 +988,10 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k
 		}
 	}
 
+	if (cat->cdm)
+		msm_disp_snapshot_add_block(disp_state, cat->cdm->len,
+					    dpu_kms->mmio + cat->cdm->base, cat->cdm->name);
+
 	pm_runtime_put_sync(&dpu_kms->pdev->dev);
 }
 
-- 
2.40.1


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

* [PATCH 16/16] drm/msm/dpu: add cdm blocks to dpu snapshot
@ 2023-08-30 22:49   ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-08-30 22:49 UTC (permalink / raw)
  To: freedreno, Rob Clark, Abhinav Kumar, Dmitry Baryshkov, Sean Paul,
	Marijn Suijten, David Airlie, Daniel Vetter
  Cc: dri-devel, quic_jesszhan, quic_parellan, quic_khsieh,
	linux-arm-msm, linux-kernel

Now that CDM block support has been added to DPU lets also add its
entry to the DPU snapshot to help debugging.

Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index aa6ba2cf4b84..a207b18eb112 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -988,6 +988,10 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k
 		}
 	}
 
+	if (cat->cdm)
+		msm_disp_snapshot_add_block(disp_state, cat->cdm->len,
+					    dpu_kms->mmio + cat->cdm->base, cat->cdm->name);
+
 	pm_runtime_put_sync(&dpu_kms->pdev->dev);
 }
 
-- 
2.40.1


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

* Re: [PATCH 04/16] drm/msm/dpu: add cdm blocks to sc7280 dpu_hw_catalog
  2023-08-30 22:48   ` Abhinav Kumar
@ 2023-08-30 22:57     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-30 22:57 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel

On Thu, 31 Aug 2023 at 01:49, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> Add CDM blocks to the sc7280 dpu_hw_catalog to support
> YUV format output from writeback block.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  .../gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h  |  9 +++++++++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h      | 13 +++++++++++++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h         |  5 +++++
>  3 files changed, 27 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
> index 3b5061c4402a..5252170f216d 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
> @@ -251,10 +251,19 @@ static const struct dpu_mdss_version sc7280_mdss_ver = {
>         .core_minor_ver = 2,
>  };
>
> +static const struct dpu_cdm_cfg sc7280_cdm = {
> +       .name = "cdm_0",
> +       .id = CDM_0,
> +       .len = 0x228,
> +       .base = 0x79200,
> +       .features = 0,

No need to.
Also, as the CDM block seems to be common to all existing platforms,
what about moving this definition to dpu_hw_catalog.c next to VBIF
settings?

> +};
> +
>  const struct dpu_mdss_cfg dpu_sc7280_cfg = {
>         .mdss_ver = &sc7280_mdss_ver,
>         .caps = &sc7280_dpu_caps,
>         .mdp = &sc7280_mdp,
> +       .cdm = &sc7280_cdm,
>         .ctl_count = ARRAY_SIZE(sc7280_ctl),
>         .ctl = sc7280_ctl,
>         .sspp_count = ARRAY_SIZE(sc7280_sspp),
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> index 6c9634209e9f..4ea7c3f85a95 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> @@ -693,6 +693,17 @@ struct dpu_vbif_cfg {
>         u32 memtype[MAX_XIN_COUNT];
>  };
>
> +/**
> + * struct dpu_cdm_cfg - information of chroma down blocks
> + * @name               string name for debug purposes
> + * @id                 enum identifying this block
> + * @base               register offset of this block
> + * @features           bit mask identifying sub-blocks/features
> + */
> +struct dpu_cdm_cfg {
> +       DPU_HW_BLK_INFO;
> +};
> +
>  /**
>   * Define CDP use cases
>   * @DPU_PERF_CDP_UDAGE_RT: real-time use cases
> @@ -816,6 +827,8 @@ struct dpu_mdss_cfg {
>         u32 wb_count;
>         const struct dpu_wb_cfg *wb;
>
> +       const struct dpu_cdm_cfg *cdm;
> +
>         u32 ad_count;
>
>         u32 dspp_count;
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> index d85157acfbf8..4d6dba18caf0 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> @@ -185,6 +185,11 @@ enum dpu_dsc {
>         DSC_MAX
>  };
>
> +enum dpu_cdm {
> +       CDM_0 = 1,
> +       CDM_MAX
> +};
> +
>  enum dpu_pingpong {
>         PINGPONG_NONE,
>         PINGPONG_0,
> --
> 2.40.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH 04/16] drm/msm/dpu: add cdm blocks to sc7280 dpu_hw_catalog
@ 2023-08-30 22:57     ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-30 22:57 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Thu, 31 Aug 2023 at 01:49, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> Add CDM blocks to the sc7280 dpu_hw_catalog to support
> YUV format output from writeback block.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  .../gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h  |  9 +++++++++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h      | 13 +++++++++++++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h         |  5 +++++
>  3 files changed, 27 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
> index 3b5061c4402a..5252170f216d 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
> @@ -251,10 +251,19 @@ static const struct dpu_mdss_version sc7280_mdss_ver = {
>         .core_minor_ver = 2,
>  };
>
> +static const struct dpu_cdm_cfg sc7280_cdm = {
> +       .name = "cdm_0",
> +       .id = CDM_0,
> +       .len = 0x228,
> +       .base = 0x79200,
> +       .features = 0,

No need to.
Also, as the CDM block seems to be common to all existing platforms,
what about moving this definition to dpu_hw_catalog.c next to VBIF
settings?

> +};
> +
>  const struct dpu_mdss_cfg dpu_sc7280_cfg = {
>         .mdss_ver = &sc7280_mdss_ver,
>         .caps = &sc7280_dpu_caps,
>         .mdp = &sc7280_mdp,
> +       .cdm = &sc7280_cdm,
>         .ctl_count = ARRAY_SIZE(sc7280_ctl),
>         .ctl = sc7280_ctl,
>         .sspp_count = ARRAY_SIZE(sc7280_sspp),
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> index 6c9634209e9f..4ea7c3f85a95 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> @@ -693,6 +693,17 @@ struct dpu_vbif_cfg {
>         u32 memtype[MAX_XIN_COUNT];
>  };
>
> +/**
> + * struct dpu_cdm_cfg - information of chroma down blocks
> + * @name               string name for debug purposes
> + * @id                 enum identifying this block
> + * @base               register offset of this block
> + * @features           bit mask identifying sub-blocks/features
> + */
> +struct dpu_cdm_cfg {
> +       DPU_HW_BLK_INFO;
> +};
> +
>  /**
>   * Define CDP use cases
>   * @DPU_PERF_CDP_UDAGE_RT: real-time use cases
> @@ -816,6 +827,8 @@ struct dpu_mdss_cfg {
>         u32 wb_count;
>         const struct dpu_wb_cfg *wb;
>
> +       const struct dpu_cdm_cfg *cdm;
> +
>         u32 ad_count;
>
>         u32 dspp_count;
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> index d85157acfbf8..4d6dba18caf0 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> @@ -185,6 +185,11 @@ enum dpu_dsc {
>         DSC_MAX
>  };
>
> +enum dpu_cdm {
> +       CDM_0 = 1,
> +       CDM_MAX
> +};
> +
>  enum dpu_pingpong {
>         PINGPONG_NONE,
>         PINGPONG_0,
> --
> 2.40.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH 01/16] drm/msm/dpu: fix writeback programming for YUV cases
  2023-08-30 22:48   ` Abhinav Kumar
@ 2023-08-30 23:38     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-30 23:38 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel

On Thu, 31 Aug 2023 at 01:49, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> For YUV cases, setting the required format bits was missed
> out in the register programming. Lets fix it now in preparation
> of adding YUV formats support for writeback.
>
> Fixes: 84a33d0fd921 ("drm/msm/dpu: add dpu_hw_wb abstraction for writeback blocks")

Since we were not exporting YUV formats, this tag is not correct. This
is a mere functional change, not a fix.

> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
> index ebc416400382..0aa598b355e9 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
> @@ -86,6 +86,9 @@ static void dpu_hw_wb_setup_format(struct dpu_hw_wb *ctx,
>                         dst_format |= BIT(14); /* DST_ALPHA_X */
>         }
>
> +       if (DPU_FORMAT_IS_YUV(fmt))
> +               dst_format |= BIT(15);
> +
>         pattern = (fmt->element[3] << 24) |
>                 (fmt->element[2] << 16) |
>                 (fmt->element[1] << 8)  |
> --
> 2.40.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH 01/16] drm/msm/dpu: fix writeback programming for YUV cases
@ 2023-08-30 23:38     ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-30 23:38 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Thu, 31 Aug 2023 at 01:49, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> For YUV cases, setting the required format bits was missed
> out in the register programming. Lets fix it now in preparation
> of adding YUV formats support for writeback.
>
> Fixes: 84a33d0fd921 ("drm/msm/dpu: add dpu_hw_wb abstraction for writeback blocks")

Since we were not exporting YUV formats, this tag is not correct. This
is a mere functional change, not a fix.

> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
> index ebc416400382..0aa598b355e9 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
> @@ -86,6 +86,9 @@ static void dpu_hw_wb_setup_format(struct dpu_hw_wb *ctx,
>                         dst_format |= BIT(14); /* DST_ALPHA_X */
>         }
>
> +       if (DPU_FORMAT_IS_YUV(fmt))
> +               dst_format |= BIT(15);
> +
>         pattern = (fmt->element[3] << 24) |
>                 (fmt->element[2] << 16) |
>                 (fmt->element[1] << 8)  |
> --
> 2.40.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH 02/16] drm/msm/dpu: add formats check for writeback encoder
  2023-08-30 22:48   ` Abhinav Kumar
@ 2023-08-30 23:39     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-30 23:39 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel

On Thu, 31 Aug 2023 at 01:49, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> In preparation of adding more formats to dpu writeback add

I think it is `preparation to'

Other than that:

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

> format validation to it to fail any unsupported formats.
>
> Fixes: d7d0e73f7de3 ("drm/msm/dpu: introduce the dpu_encoder_phys_* for writeback")
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 7 +++++++
>  1 file changed, 7 insertions(+)
>
> 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 284a88060221..6a1f8e34f18a 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
> @@ -238,6 +238,7 @@ static int dpu_encoder_phys_wb_atomic_check(
>  {
>         struct drm_framebuffer *fb;
>         const struct drm_display_mode *mode = &crtc_state->mode;
> +       int ret;
>
>         DPU_DEBUG("[atomic_check:%d, \"%s\",%d,%d]\n",
>                         phys_enc->hw_wb->idx, mode->name, mode->hdisplay, mode->vdisplay);
> @@ -274,6 +275,12 @@ static int dpu_encoder_phys_wb_atomic_check(
>                 return -EINVAL;
>         }
>
> +       ret = drm_atomic_helper_check_wb_encoder_state(phys_enc->parent, conn_state);
> +       if (ret < 0) {
> +               DPU_ERROR("invalid pixel format %p4cc\n", &fb->format->format);
> +               return ret;
> +       }
> +
>         return 0;
>  }
>
> --
> 2.40.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH 02/16] drm/msm/dpu: add formats check for writeback encoder
@ 2023-08-30 23:39     ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-30 23:39 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Thu, 31 Aug 2023 at 01:49, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> In preparation of adding more formats to dpu writeback add

I think it is `preparation to'

Other than that:

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

> format validation to it to fail any unsupported formats.
>
> Fixes: d7d0e73f7de3 ("drm/msm/dpu: introduce the dpu_encoder_phys_* for writeback")
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 7 +++++++
>  1 file changed, 7 insertions(+)
>
> 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 284a88060221..6a1f8e34f18a 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
> @@ -238,6 +238,7 @@ static int dpu_encoder_phys_wb_atomic_check(
>  {
>         struct drm_framebuffer *fb;
>         const struct drm_display_mode *mode = &crtc_state->mode;
> +       int ret;
>
>         DPU_DEBUG("[atomic_check:%d, \"%s\",%d,%d]\n",
>                         phys_enc->hw_wb->idx, mode->name, mode->hdisplay, mode->vdisplay);
> @@ -274,6 +275,12 @@ static int dpu_encoder_phys_wb_atomic_check(
>                 return -EINVAL;
>         }
>
> +       ret = drm_atomic_helper_check_wb_encoder_state(phys_enc->parent, conn_state);
> +       if (ret < 0) {
> +               DPU_ERROR("invalid pixel format %p4cc\n", &fb->format->format);
> +               return ret;
> +       }
> +
>         return 0;
>  }
>
> --
> 2.40.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH 03/16] drm/msm/dpu: rename dpu_encoder_phys_wb_setup_cdp to match its functionality
  2023-08-30 22:48   ` Abhinav Kumar
@ 2023-08-30 23:40     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-30 23:40 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel

On Thu, 31 Aug 2023 at 01:49, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> dpu_encoder_phys_wb_setup_cdp() is not programming the chroma down
> prefetch block. Its setting up the display ctl path for writeback.
>
> Hence rename it to dpu_encoder_phys_wb_setup_ctl() to match what its
> actually doing.
>
> Fixes: d7d0e73f7de3 ("drm/msm/dpu: introduce the dpu_encoder_phys_* for writeback")
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)

-- 
With best wishes
Dmitry

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

* Re: [PATCH 03/16] drm/msm/dpu: rename dpu_encoder_phys_wb_setup_cdp to match its functionality
@ 2023-08-30 23:40     ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-30 23:40 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Thu, 31 Aug 2023 at 01:49, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> dpu_encoder_phys_wb_setup_cdp() is not programming the chroma down
> prefetch block. Its setting up the display ctl path for writeback.
>
> Hence rename it to dpu_encoder_phys_wb_setup_ctl() to match what its
> actually doing.
>
> Fixes: d7d0e73f7de3 ("drm/msm/dpu: introduce the dpu_encoder_phys_* for writeback")
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)

-- 
With best wishes
Dmitry

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

* Re: [PATCH 07/16] drm/msm/dpu: add cdm blocks to RM
  2023-08-30 22:49   ` Abhinav Kumar
@ 2023-08-30 23:48     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-30 23:48 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> Add the RM APIs necessary to initialize and allocate CDM
> blocks by the rest of the DPU pipeline.

... to be used by the rest?

>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 17 +++++++++++++++++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h |  2 ++
>  2 files changed, 19 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> index f9215643c71a..7b6444a3fcb1 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> @@ -8,6 +8,7 @@
>  #include "dpu_kms.h"
>  #include "dpu_hw_lm.h"
>  #include "dpu_hw_ctl.h"
> +#include "dpu_hw_cdm.h"
>  #include "dpu_hw_pingpong.h"
>  #include "dpu_hw_sspp.h"
>  #include "dpu_hw_intf.h"
> @@ -90,6 +91,9 @@ int dpu_rm_destroy(struct dpu_rm *rm)
>                 }
>         }
>
> +       if (rm->cdm_blk)
> +               dpu_hw_cdm_destroy(to_dpu_hw_cdm(rm->cdm_blk));
> +
>         for (i = 0; i < ARRAY_SIZE(rm->hw_wb); i++)
>                 dpu_hw_wb_destroy(rm->hw_wb[i]);
>
> @@ -240,6 +244,19 @@ int dpu_rm_init(struct dpu_rm *rm,
>                 rm->hw_sspp[sspp->id - SSPP_NONE] = hw;
>         }
>
> +       if (cat->cdm) {
> +               struct dpu_hw_cdm *hw;
> +
> +               hw = dpu_hw_cdm_init(cat->cdm, mmio);
> +               /* CDM is optional so no need to bail out */
> +               if (IS_ERR(hw)) {
> +                       rc = PTR_ERR(hw);
> +                       DPU_DEBUG("failed cdm object creation: err %d\n", rc);

No. If it is a part of the catalog, we should fail here as we do in other cases.


> +               } else {
> +                       rm->cdm_blk = &hw->base;
> +               }
> +       }
> +
>         return 0;
>
>  fail:
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> index 2b551566cbf4..29b221491926 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> @@ -22,6 +22,7 @@ struct dpu_global_state;
>   * @hw_wb: array of wb hardware resources
>   * @dspp_blks: array of dspp hardware resources
>   * @hw_sspp: array of sspp hardware resources
> + * @cdm_blk: cdm hardware resource
>   */
>  struct dpu_rm {
>         struct dpu_hw_blk *pingpong_blks[PINGPONG_MAX - PINGPONG_0];
> @@ -33,6 +34,7 @@ struct dpu_rm {
>         struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0];
>         struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0];
>         struct dpu_hw_sspp *hw_sspp[SSPP_MAX - SSPP_NONE];
> +       struct dpu_hw_blk *cdm_blk;

struct dpu_hw_cdm *cdm (or cdm_blk), please.

>  };
>
>  /**
> --
> 2.40.1
>


--
With best wishes
Dmitry

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

* Re: [PATCH 07/16] drm/msm/dpu: add cdm blocks to RM
@ 2023-08-30 23:48     ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-30 23:48 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> Add the RM APIs necessary to initialize and allocate CDM
> blocks by the rest of the DPU pipeline.

... to be used by the rest?

>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 17 +++++++++++++++++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h |  2 ++
>  2 files changed, 19 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> index f9215643c71a..7b6444a3fcb1 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> @@ -8,6 +8,7 @@
>  #include "dpu_kms.h"
>  #include "dpu_hw_lm.h"
>  #include "dpu_hw_ctl.h"
> +#include "dpu_hw_cdm.h"
>  #include "dpu_hw_pingpong.h"
>  #include "dpu_hw_sspp.h"
>  #include "dpu_hw_intf.h"
> @@ -90,6 +91,9 @@ int dpu_rm_destroy(struct dpu_rm *rm)
>                 }
>         }
>
> +       if (rm->cdm_blk)
> +               dpu_hw_cdm_destroy(to_dpu_hw_cdm(rm->cdm_blk));
> +
>         for (i = 0; i < ARRAY_SIZE(rm->hw_wb); i++)
>                 dpu_hw_wb_destroy(rm->hw_wb[i]);
>
> @@ -240,6 +244,19 @@ int dpu_rm_init(struct dpu_rm *rm,
>                 rm->hw_sspp[sspp->id - SSPP_NONE] = hw;
>         }
>
> +       if (cat->cdm) {
> +               struct dpu_hw_cdm *hw;
> +
> +               hw = dpu_hw_cdm_init(cat->cdm, mmio);
> +               /* CDM is optional so no need to bail out */
> +               if (IS_ERR(hw)) {
> +                       rc = PTR_ERR(hw);
> +                       DPU_DEBUG("failed cdm object creation: err %d\n", rc);

No. If it is a part of the catalog, we should fail here as we do in other cases.


> +               } else {
> +                       rm->cdm_blk = &hw->base;
> +               }
> +       }
> +
>         return 0;
>
>  fail:
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> index 2b551566cbf4..29b221491926 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> @@ -22,6 +22,7 @@ struct dpu_global_state;
>   * @hw_wb: array of wb hardware resources
>   * @dspp_blks: array of dspp hardware resources
>   * @hw_sspp: array of sspp hardware resources
> + * @cdm_blk: cdm hardware resource
>   */
>  struct dpu_rm {
>         struct dpu_hw_blk *pingpong_blks[PINGPONG_MAX - PINGPONG_0];
> @@ -33,6 +34,7 @@ struct dpu_rm {
>         struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0];
>         struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0];
>         struct dpu_hw_sspp *hw_sspp[SSPP_MAX - SSPP_NONE];
> +       struct dpu_hw_blk *cdm_blk;

struct dpu_hw_cdm *cdm (or cdm_blk), please.

>  };
>
>  /**
> --
> 2.40.1
>


--
With best wishes
Dmitry

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

* Re: [PATCH 06/16] drm/msm/dpu: add dpu_hw_cdm abstraction for CDM block
  2023-08-30 22:48   ` Abhinav Kumar
@ 2023-08-31  0:00     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-31  0:00 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-kernel, linux-arm-msm

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> CDM block comes with its own set of registers and operations
> which can be done. In-line with other hardware sub-blocks, this
> change adds the dpu_hw_cdm abstraction for the CDM block.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  drivers/gpu/drm/msm/Makefile                |   1 +
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c  | 272 ++++++++++++++++++++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h  | 135 ++++++++++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h |   1 +
>  4 files changed, 409 insertions(+)
>  create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
>  create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
>
> diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
> index 8d02d8c33069..2010cb1ca995 100644
> --- a/drivers/gpu/drm/msm/Makefile
> +++ b/drivers/gpu/drm/msm/Makefile
> @@ -63,6 +63,7 @@ msm-$(CONFIG_DRM_MSM_DPU) += \
>         disp/dpu1/dpu_encoder_phys_wb.o \
>         disp/dpu1/dpu_formats.o \
>         disp/dpu1/dpu_hw_catalog.o \
> +       disp/dpu1/dpu_hw_cdm.o \
>         disp/dpu1/dpu_hw_ctl.o \
>         disp/dpu1/dpu_hw_dsc.o \
>         disp/dpu1/dpu_hw_dsc_1_2.o \
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
> new file mode 100644
> index 000000000000..a2f7ee8f54e4
> --- /dev/null
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
> @@ -0,0 +1,272 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2023, The Linux Foundation. All rights reserved.
> + */
> +
> +#include <drm/drm_managed.h>
> +
> +#include "dpu_hw_mdss.h"
> +#include "dpu_hw_util.h"
> +#include "dpu_hw_catalog.h"
> +#include "dpu_hw_cdm.h"
> +#include "dpu_kms.h"
> +
> +#define CDM_CSC_10_OPMODE                  0x000
> +#define CDM_CSC_10_BASE                    0x004
> +
> +#define CDM_CDWN2_OP_MODE                  0x100
> +#define CDM_CDWN2_CLAMP_OUT                0x104
> +#define CDM_CDWN2_PARAMS_3D_0              0x108
> +#define CDM_CDWN2_PARAMS_3D_1              0x10C
> +#define CDM_CDWN2_COEFF_COSITE_H_0         0x110
> +#define CDM_CDWN2_COEFF_COSITE_H_1         0x114
> +#define CDM_CDWN2_COEFF_COSITE_H_2         0x118
> +#define CDM_CDWN2_COEFF_OFFSITE_H_0        0x11C
> +#define CDM_CDWN2_COEFF_OFFSITE_H_1        0x120
> +#define CDM_CDWN2_COEFF_OFFSITE_H_2        0x124
> +#define CDM_CDWN2_COEFF_COSITE_V           0x128
> +#define CDM_CDWN2_COEFF_OFFSITE_V          0x12C
> +#define CDM_CDWN2_OUT_SIZE                 0x130
> +
> +#define CDM_HDMI_PACK_OP_MODE              0x200
> +#define CDM_CSC_10_MATRIX_COEFF_0          0x004
> +
> +#define CDM_MUX                            0x224
> +
> +/**
> + * Horizontal coefficients for cosite chroma downscale
> + * s13 representation of coefficients
> + */
> +static u32 cosite_h_coeff[] = {0x00000016, 0x000001cc, 0x0100009e};
> +
> +/**
> + * Horizontal coefficients for offsite chroma downscale
> + */
> +static u32 offsite_h_coeff[] = {0x000b0005, 0x01db01eb, 0x00e40046};
> +
> +/**
> + * Vertical coefficients for cosite chroma downscale
> + */
> +static u32 cosite_v_coeff[] = {0x00080004};
> +/**
> + * Vertical coefficients for offsite chroma downscale
> + */
> +static u32 offsite_v_coeff[] = {0x00060002};
> +
> +static int dpu_hw_cdm_setup_csc_10bit(struct dpu_hw_cdm *ctx, struct dpu_csc_cfg *data)
> +{
> +       dpu_hw_csc_setup(&ctx->hw, CDM_CSC_10_MATRIX_COEFF_0, data, true);

Where was this defined?

> +
> +       return 0;
> +}
> +
> +static int dpu_hw_cdm_setup_cdwn(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cfg)
> +{
> +       struct dpu_hw_blk_reg_map *c = &ctx->hw;
> +       u32 opmode = 0;
> +       u32 out_size = 0;
> +
> +       if (cfg->output_bit_depth == CDM_CDWN_OUTPUT_10BIT)
> +               opmode &= ~BIT(7);
> +       else
> +               opmode |= BIT(7);
> +
> +       /* ENABLE DWNS_H bit */
> +       opmode |= BIT(1);
> +
> +       switch (cfg->h_cdwn_type) {
> +       case CDM_CDWN_DISABLE:
> +               /* CLEAR METHOD_H field */
> +               opmode &= ~(0x18);
> +               /* CLEAR DWNS_H bit */
> +               opmode &= ~BIT(1);
> +               break;
> +       case CDM_CDWN_PIXEL_DROP:
> +               /* Clear METHOD_H field (pixel drop is 0) */
> +               opmode &= ~(0x18);
> +               break;
> +       case CDM_CDWN_AVG:
> +               /* Clear METHOD_H field (Average is 0x1) */
> +               opmode &= ~(0x18);
> +               opmode |= (0x1 << 0x3);
> +               break;
> +       case CDM_CDWN_COSITE:
> +               /* Clear METHOD_H field (Average is 0x2) */
> +               opmode &= ~(0x18);
> +               opmode |= (0x2 << 0x3);
> +               /* Co-site horizontal coefficients */
> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_0,
> +                               cosite_h_coeff[0]);
> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_1,
> +                               cosite_h_coeff[1]);
> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_2,
> +                               cosite_h_coeff[2]);
> +               break;
> +       case CDM_CDWN_OFFSITE:
> +               /* Clear METHOD_H field (Average is 0x3) */
> +               opmode &= ~(0x18);
> +               opmode |= (0x3 << 0x3);
> +
> +               /* Off-site horizontal coefficients */
> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_0,
> +                               offsite_h_coeff[0]);
> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_1,
> +                               offsite_h_coeff[1]);
> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_2,
> +                               offsite_h_coeff[2]);
> +               break;
> +       default:
> +               pr_err("%s invalid horz down sampling type\n", __func__);
> +               return -EINVAL;
> +       }
> +
> +       /* ENABLE DWNS_V bit */
> +       opmode |= BIT(2);
> +
> +       switch (cfg->v_cdwn_type) {
> +       case CDM_CDWN_DISABLE:
> +               /* CLEAR METHOD_V field */
> +               opmode &= ~(0x60);

#define, GENMASK

> +               /* CLEAR DWNS_V bit */
> +               opmode &= ~BIT(2);
> +               break;
> +       case CDM_CDWN_PIXEL_DROP:
> +               /* Clear METHOD_V field (pixel drop is 0) */
> +               opmode &= ~(0x60);
> +               break;
> +       case CDM_CDWN_AVG:
> +               /* Clear METHOD_V field (Average is 0x1) */
> +               opmode &= ~(0x60);
> +               opmode |= (0x1 << 0x5);

#define

> +               break;
> +       case CDM_CDWN_COSITE:
> +               /* Clear METHOD_V field (Average is 0x2) */
> +               opmode &= ~(0x60);
> +               opmode |= (0x2 << 0x5);
> +               /* Co-site vertical coefficients */
> +               DPU_REG_WRITE(c,
> +                               CDM_CDWN2_COEFF_COSITE_V,
> +                               cosite_v_coeff[0]);

align to opening bracket

> +               break;
> +       case CDM_CDWN_OFFSITE:
> +               /* Clear METHOD_V field (Average is 0x3) */
> +               opmode &= ~(0x60);
> +               opmode |= (0x3 << 0x5);
> +
> +               /* Off-site vertical coefficients */
> +               DPU_REG_WRITE(c,
> +                               CDM_CDWN2_COEFF_OFFSITE_V,
> +                               offsite_v_coeff[0]);

align to opening bracket

> +               break;
> +       default:
> +               return -EINVAL;
> +       }
> +
> +       if (cfg->v_cdwn_type || cfg->h_cdwn_type)
> +               opmode |= BIT(0); /* EN CDWN module */

#define

> +       else
> +               opmode &= ~BIT(0);
> +
> +       out_size = (cfg->output_width & 0xFFFF) |
> +               ((cfg->output_height & 0xFFFF) << 16);
> +       DPU_REG_WRITE(c, CDM_CDWN2_OUT_SIZE, out_size);
> +       DPU_REG_WRITE(c, CDM_CDWN2_OP_MODE, opmode);
> +       DPU_REG_WRITE(c, CDM_CDWN2_CLAMP_OUT,
> +                       ((0x3FF << 16) | 0x0));
> +
> +       return 0;
> +}
> +
> +int dpu_hw_cdm_enable(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cdm)
> +{
> +       struct dpu_hw_blk_reg_map *c = &ctx->hw;
> +       const struct dpu_format *fmt;
> +       u32 opmode = 0;
> +       u32 csc = 0;
> +
> +       if (!ctx || !cdm)
> +               return -EINVAL;
> +
> +       fmt = cdm->output_fmt;
> +
> +       if (!DPU_FORMAT_IS_YUV(fmt))
> +               return -EINVAL;
> +
> +       if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
> +               if (fmt->chroma_sample != DPU_CHROMA_H1V2)
> +                       return -EINVAL; /*unsupported format */
> +               opmode = BIT(0);
> +               opmode |= (fmt->chroma_sample << 1);
> +       }
> +
> +       csc |= BIT(2);
> +       csc &= ~BIT(1);
> +       csc |= BIT(0);

Can we get some sensible #defines for all this magic, please?

> +
> +       if (ctx && ctx->ops.bind_pingpong_blk)
> +               ctx->ops.bind_pingpong_blk(ctx, true,
> +                               cdm->pp_id);
> +
> +       DPU_REG_WRITE(c, CDM_CSC_10_OPMODE, csc);
> +       DPU_REG_WRITE(c, CDM_HDMI_PACK_OP_MODE, opmode);
> +       return 0;
> +}
> +
> +void dpu_hw_cdm_disable(struct dpu_hw_cdm *ctx)
> +{
> +       if (!ctx)
> +               return;
> +
> +       if (ctx && ctx->ops.bind_pingpong_blk)
> +               ctx->ops.bind_pingpong_blk(ctx, false, 0);

PINGPONG_NONE.

> +}
> +
> +static void dpu_hw_cdm_bind_pingpong_blk(struct dpu_hw_cdm *ctx, bool enable,
> +                                        const enum dpu_pingpong pp)
> +{
> +       struct dpu_hw_blk_reg_map *c;
> +       int mux_cfg = 0xF;
> +
> +       if (!ctx || (enable && (pp < PINGPONG_0 || pp >= PINGPONG_MAX)))
> +               return;

I'd say, this is useless. We don't have such checks in other
bind_pingpong_blk() callbacks.

Also there should be a guarding check for DPU >= 5.0 either here or at
the ops init.

> +
> +       c = &ctx->hw;
> +
> +       if (enable)
> +               mux_cfg = (pp - PINGPONG_0) & 0x7;
> +
> +       DPU_REG_WRITE(c, CDM_MUX, mux_cfg);
> +}
> +
> +static void _setup_cdm_ops(struct dpu_hw_cdm_ops *ops, unsigned long features)

Please inline

> +{
> +       ops->setup_csc_data = dpu_hw_cdm_setup_csc_10bit;
> +       ops->setup_cdwn = dpu_hw_cdm_setup_cdwn;
> +       ops->enable = dpu_hw_cdm_enable;
> +       ops->disable = dpu_hw_cdm_disable;
> +       ops->bind_pingpong_blk = dpu_hw_cdm_bind_pingpong_blk;

As you seem to call this function directly, we might as well drop the
callback from the ops.

> +}
> +
> +struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cfg, void __iomem *addr)
> +{
> +       struct dpu_hw_cdm *c;
> +
> +       c = kzalloc(sizeof(*c), GFP_KERNEL);
> +       if (!c)
> +               return ERR_PTR(-ENOMEM);
> +
> +       c->hw.blk_addr = addr + cfg->base;
> +       c->hw.log_mask = DPU_DBG_MASK_CDM;
> +
> +       /* Assign ops */
> +       c->idx = cfg->id;
> +       c->caps = cfg;
> +       _setup_cdm_ops(&c->ops, c->caps->features);
> +
> +       return c;
> +}
> +
> +void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm)
> +{
> +       kfree(cdm);

I'd prefer not to introduce another manual kzalloc/kfree pair, see
https://patchwork.freedesktop.org/series/120366/

> +}
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
> new file mode 100644
> index 000000000000..da60893a5c02
> --- /dev/null
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
> @@ -0,0 +1,135 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2023, The Linux Foundation. All rights reserved.
> + */
> +
> +#ifndef _DPU_HW_CDM_H
> +#define _DPU_HW_CDM_H
> +
> +#include "dpu_hw_mdss.h"
> +#include "dpu_hw_top.h"
> +
> +struct dpu_hw_cdm;
> +
> +struct dpu_hw_cdm_cfg {
> +       u32 output_width;
> +       u32 output_height;
> +       u32 output_bit_depth;
> +       u32 h_cdwn_type;
> +       u32 v_cdwn_type;
> +       const struct dpu_format *output_fmt;
> +       u32 output_type;
> +       int pp_id;
> +};
> +
> +enum dpu_hw_cdwn_type {
> +       CDM_CDWN_DISABLE,
> +       CDM_CDWN_PIXEL_DROP,
> +       CDM_CDWN_AVG,
> +       CDM_CDWN_COSITE,
> +       CDM_CDWN_OFFSITE,
> +};
> +
> +enum dpu_hw_cdwn_output_type {
> +       CDM_CDWN_OUTPUT_HDMI,
> +       CDM_CDWN_OUTPUT_WB,
> +};
> +
> +enum dpu_hw_cdwn_output_bit_depth {
> +       CDM_CDWN_OUTPUT_8BIT,
> +       CDM_CDWN_OUTPUT_10BIT,
> +};
> +
> +/**
> + * struct dpu_hw_cdm_ops : Interface to the chroma down Hw driver functions
> + *                         Assumption is these functions will be called after
> + *                         clocks are enabled
> + *  @setup_csc:            Programs the csc matrix
> + *  @setup_cdwn:           Sets up the chroma down sub module
> + *  @enable:               Enables the output to interface and programs the
> + *                         output packer
> + *  @disable:              Puts the cdm in bypass mode
> + *  @bind_pingpong_blk:    enable/disable the connection with pingpong which
> + *                         will feed pixels to this cdm
> + */
> +struct dpu_hw_cdm_ops {
> +       /**
> +        * Programs the CSC matrix for conversion from RGB space to YUV space,
> +        * it is optional to call this function as this matrix is automatically
> +        * set during initialization, user should call this if it wants
> +        * to program a different matrix than default matrix.
> +        * @cdm:          Pointer to the chroma down context structure
> +        * @data          Pointer to CSC configuration data
> +        * return:        0 if success; error code otherwise
> +        */
> +       int (*setup_csc_data)(struct dpu_hw_cdm *cdm, struct dpu_csc_cfg *data);
> +
> +       /**
> +        * Programs the Chroma downsample part.
> +        * @cdm         Pointer to chroma down context
> +        * @cfg         Pointer to the cdm configuration data
> +        */
> +       int (*setup_cdwn)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
> +
> +       /**
> +        * Enable the CDM module
> +        * @cdm         Pointer to chroma down context
> +        */
> +       int (*enable)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
> +
> +       /**
> +        * Disable the CDM module
> +        * @cdm         Pointer to chroma down context
> +        */
> +       void (*disable)(struct dpu_hw_cdm *cdm);
> +
> +       /**
> +        * Enable/disable the connection with pingpong
> +        * @cdm         Pointer to chroma down context
> +        * @enable      Enable/disable control
> +        * @pp          pingpong block id.
> +        */
> +       void (*bind_pingpong_blk)(struct dpu_hw_cdm *cdm, bool enable,
> +                                 const enum dpu_pingpong pp);
> +};
> +
> +/**
> + * struct dpu_hw_cdm - cdm description
> + * @base: Hardware block base structure
> + * @hw: Block hardware details
> + * @idx: CDM index
> + * @caps: Pointer to cdm_cfg
> + * @ops: handle to operations possible for this CDM
> + */
> +struct dpu_hw_cdm {
> +       struct dpu_hw_blk base;
> +       struct dpu_hw_blk_reg_map hw;
> +
> +       /* chroma down */
> +       const struct dpu_cdm_cfg *caps;
> +       enum  dpu_cdm  idx;
> +
> +       /* ops */
> +       struct dpu_hw_cdm_ops ops;
> +};
> +
> +/**
> + * dpu_hw_cdm_init - initializes the cdm hw driver object.
> + * should be called once before accessing every cdm.
> + * @cdm: CDM catalog entry for which driver object is required
> + * @addr :   mapped register io address of MDSS
> + */
> +struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cdm, void __iomem *addr);
> +
> +/**
> + * dpu_hw_cdm_destroy - destroys cdm driver context
> + * @cdm:   Pointer to cdm driver context returned by dpu_hw_cdm_init
> + */
> +void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm);
> +
> +static inline struct dpu_hw_cdm *to_dpu_hw_cdm(struct dpu_hw_blk *hw)
> +{
> +       return container_of(hw, struct dpu_hw_cdm, base);
> +}
> +
> +#endif /*_DPU_HW_CDM_H */
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> index 4d6dba18caf0..34f943102499 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> @@ -463,6 +463,7 @@ struct dpu_mdss_color {
>  #define DPU_DBG_MASK_ROT      (1 << 9)
>  #define DPU_DBG_MASK_DSPP     (1 << 10)
>  #define DPU_DBG_MASK_DSC      (1 << 11)
> +#define DPU_DBG_MASK_CDM      (1 << 12)
>
>  /**
>   * struct dpu_hw_tear_check - Struct contains parameters to configure
> --
> 2.40.1
>


--
With best wishes
Dmitry

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

* Re: [PATCH 06/16] drm/msm/dpu: add dpu_hw_cdm abstraction for CDM block
@ 2023-08-31  0:00     ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-31  0:00 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> CDM block comes with its own set of registers and operations
> which can be done. In-line with other hardware sub-blocks, this
> change adds the dpu_hw_cdm abstraction for the CDM block.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  drivers/gpu/drm/msm/Makefile                |   1 +
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c  | 272 ++++++++++++++++++++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h  | 135 ++++++++++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h |   1 +
>  4 files changed, 409 insertions(+)
>  create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
>  create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
>
> diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
> index 8d02d8c33069..2010cb1ca995 100644
> --- a/drivers/gpu/drm/msm/Makefile
> +++ b/drivers/gpu/drm/msm/Makefile
> @@ -63,6 +63,7 @@ msm-$(CONFIG_DRM_MSM_DPU) += \
>         disp/dpu1/dpu_encoder_phys_wb.o \
>         disp/dpu1/dpu_formats.o \
>         disp/dpu1/dpu_hw_catalog.o \
> +       disp/dpu1/dpu_hw_cdm.o \
>         disp/dpu1/dpu_hw_ctl.o \
>         disp/dpu1/dpu_hw_dsc.o \
>         disp/dpu1/dpu_hw_dsc_1_2.o \
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
> new file mode 100644
> index 000000000000..a2f7ee8f54e4
> --- /dev/null
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
> @@ -0,0 +1,272 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2023, The Linux Foundation. All rights reserved.
> + */
> +
> +#include <drm/drm_managed.h>
> +
> +#include "dpu_hw_mdss.h"
> +#include "dpu_hw_util.h"
> +#include "dpu_hw_catalog.h"
> +#include "dpu_hw_cdm.h"
> +#include "dpu_kms.h"
> +
> +#define CDM_CSC_10_OPMODE                  0x000
> +#define CDM_CSC_10_BASE                    0x004
> +
> +#define CDM_CDWN2_OP_MODE                  0x100
> +#define CDM_CDWN2_CLAMP_OUT                0x104
> +#define CDM_CDWN2_PARAMS_3D_0              0x108
> +#define CDM_CDWN2_PARAMS_3D_1              0x10C
> +#define CDM_CDWN2_COEFF_COSITE_H_0         0x110
> +#define CDM_CDWN2_COEFF_COSITE_H_1         0x114
> +#define CDM_CDWN2_COEFF_COSITE_H_2         0x118
> +#define CDM_CDWN2_COEFF_OFFSITE_H_0        0x11C
> +#define CDM_CDWN2_COEFF_OFFSITE_H_1        0x120
> +#define CDM_CDWN2_COEFF_OFFSITE_H_2        0x124
> +#define CDM_CDWN2_COEFF_COSITE_V           0x128
> +#define CDM_CDWN2_COEFF_OFFSITE_V          0x12C
> +#define CDM_CDWN2_OUT_SIZE                 0x130
> +
> +#define CDM_HDMI_PACK_OP_MODE              0x200
> +#define CDM_CSC_10_MATRIX_COEFF_0          0x004
> +
> +#define CDM_MUX                            0x224
> +
> +/**
> + * Horizontal coefficients for cosite chroma downscale
> + * s13 representation of coefficients
> + */
> +static u32 cosite_h_coeff[] = {0x00000016, 0x000001cc, 0x0100009e};
> +
> +/**
> + * Horizontal coefficients for offsite chroma downscale
> + */
> +static u32 offsite_h_coeff[] = {0x000b0005, 0x01db01eb, 0x00e40046};
> +
> +/**
> + * Vertical coefficients for cosite chroma downscale
> + */
> +static u32 cosite_v_coeff[] = {0x00080004};
> +/**
> + * Vertical coefficients for offsite chroma downscale
> + */
> +static u32 offsite_v_coeff[] = {0x00060002};
> +
> +static int dpu_hw_cdm_setup_csc_10bit(struct dpu_hw_cdm *ctx, struct dpu_csc_cfg *data)
> +{
> +       dpu_hw_csc_setup(&ctx->hw, CDM_CSC_10_MATRIX_COEFF_0, data, true);

Where was this defined?

> +
> +       return 0;
> +}
> +
> +static int dpu_hw_cdm_setup_cdwn(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cfg)
> +{
> +       struct dpu_hw_blk_reg_map *c = &ctx->hw;
> +       u32 opmode = 0;
> +       u32 out_size = 0;
> +
> +       if (cfg->output_bit_depth == CDM_CDWN_OUTPUT_10BIT)
> +               opmode &= ~BIT(7);
> +       else
> +               opmode |= BIT(7);
> +
> +       /* ENABLE DWNS_H bit */
> +       opmode |= BIT(1);
> +
> +       switch (cfg->h_cdwn_type) {
> +       case CDM_CDWN_DISABLE:
> +               /* CLEAR METHOD_H field */
> +               opmode &= ~(0x18);
> +               /* CLEAR DWNS_H bit */
> +               opmode &= ~BIT(1);
> +               break;
> +       case CDM_CDWN_PIXEL_DROP:
> +               /* Clear METHOD_H field (pixel drop is 0) */
> +               opmode &= ~(0x18);
> +               break;
> +       case CDM_CDWN_AVG:
> +               /* Clear METHOD_H field (Average is 0x1) */
> +               opmode &= ~(0x18);
> +               opmode |= (0x1 << 0x3);
> +               break;
> +       case CDM_CDWN_COSITE:
> +               /* Clear METHOD_H field (Average is 0x2) */
> +               opmode &= ~(0x18);
> +               opmode |= (0x2 << 0x3);
> +               /* Co-site horizontal coefficients */
> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_0,
> +                               cosite_h_coeff[0]);
> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_1,
> +                               cosite_h_coeff[1]);
> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_2,
> +                               cosite_h_coeff[2]);
> +               break;
> +       case CDM_CDWN_OFFSITE:
> +               /* Clear METHOD_H field (Average is 0x3) */
> +               opmode &= ~(0x18);
> +               opmode |= (0x3 << 0x3);
> +
> +               /* Off-site horizontal coefficients */
> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_0,
> +                               offsite_h_coeff[0]);
> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_1,
> +                               offsite_h_coeff[1]);
> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_2,
> +                               offsite_h_coeff[2]);
> +               break;
> +       default:
> +               pr_err("%s invalid horz down sampling type\n", __func__);
> +               return -EINVAL;
> +       }
> +
> +       /* ENABLE DWNS_V bit */
> +       opmode |= BIT(2);
> +
> +       switch (cfg->v_cdwn_type) {
> +       case CDM_CDWN_DISABLE:
> +               /* CLEAR METHOD_V field */
> +               opmode &= ~(0x60);

#define, GENMASK

> +               /* CLEAR DWNS_V bit */
> +               opmode &= ~BIT(2);
> +               break;
> +       case CDM_CDWN_PIXEL_DROP:
> +               /* Clear METHOD_V field (pixel drop is 0) */
> +               opmode &= ~(0x60);
> +               break;
> +       case CDM_CDWN_AVG:
> +               /* Clear METHOD_V field (Average is 0x1) */
> +               opmode &= ~(0x60);
> +               opmode |= (0x1 << 0x5);

#define

> +               break;
> +       case CDM_CDWN_COSITE:
> +               /* Clear METHOD_V field (Average is 0x2) */
> +               opmode &= ~(0x60);
> +               opmode |= (0x2 << 0x5);
> +               /* Co-site vertical coefficients */
> +               DPU_REG_WRITE(c,
> +                               CDM_CDWN2_COEFF_COSITE_V,
> +                               cosite_v_coeff[0]);

align to opening bracket

> +               break;
> +       case CDM_CDWN_OFFSITE:
> +               /* Clear METHOD_V field (Average is 0x3) */
> +               opmode &= ~(0x60);
> +               opmode |= (0x3 << 0x5);
> +
> +               /* Off-site vertical coefficients */
> +               DPU_REG_WRITE(c,
> +                               CDM_CDWN2_COEFF_OFFSITE_V,
> +                               offsite_v_coeff[0]);

align to opening bracket

> +               break;
> +       default:
> +               return -EINVAL;
> +       }
> +
> +       if (cfg->v_cdwn_type || cfg->h_cdwn_type)
> +               opmode |= BIT(0); /* EN CDWN module */

#define

> +       else
> +               opmode &= ~BIT(0);
> +
> +       out_size = (cfg->output_width & 0xFFFF) |
> +               ((cfg->output_height & 0xFFFF) << 16);
> +       DPU_REG_WRITE(c, CDM_CDWN2_OUT_SIZE, out_size);
> +       DPU_REG_WRITE(c, CDM_CDWN2_OP_MODE, opmode);
> +       DPU_REG_WRITE(c, CDM_CDWN2_CLAMP_OUT,
> +                       ((0x3FF << 16) | 0x0));
> +
> +       return 0;
> +}
> +
> +int dpu_hw_cdm_enable(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cdm)
> +{
> +       struct dpu_hw_blk_reg_map *c = &ctx->hw;
> +       const struct dpu_format *fmt;
> +       u32 opmode = 0;
> +       u32 csc = 0;
> +
> +       if (!ctx || !cdm)
> +               return -EINVAL;
> +
> +       fmt = cdm->output_fmt;
> +
> +       if (!DPU_FORMAT_IS_YUV(fmt))
> +               return -EINVAL;
> +
> +       if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
> +               if (fmt->chroma_sample != DPU_CHROMA_H1V2)
> +                       return -EINVAL; /*unsupported format */
> +               opmode = BIT(0);
> +               opmode |= (fmt->chroma_sample << 1);
> +       }
> +
> +       csc |= BIT(2);
> +       csc &= ~BIT(1);
> +       csc |= BIT(0);

Can we get some sensible #defines for all this magic, please?

> +
> +       if (ctx && ctx->ops.bind_pingpong_blk)
> +               ctx->ops.bind_pingpong_blk(ctx, true,
> +                               cdm->pp_id);
> +
> +       DPU_REG_WRITE(c, CDM_CSC_10_OPMODE, csc);
> +       DPU_REG_WRITE(c, CDM_HDMI_PACK_OP_MODE, opmode);
> +       return 0;
> +}
> +
> +void dpu_hw_cdm_disable(struct dpu_hw_cdm *ctx)
> +{
> +       if (!ctx)
> +               return;
> +
> +       if (ctx && ctx->ops.bind_pingpong_blk)
> +               ctx->ops.bind_pingpong_blk(ctx, false, 0);

PINGPONG_NONE.

> +}
> +
> +static void dpu_hw_cdm_bind_pingpong_blk(struct dpu_hw_cdm *ctx, bool enable,
> +                                        const enum dpu_pingpong pp)
> +{
> +       struct dpu_hw_blk_reg_map *c;
> +       int mux_cfg = 0xF;
> +
> +       if (!ctx || (enable && (pp < PINGPONG_0 || pp >= PINGPONG_MAX)))
> +               return;

I'd say, this is useless. We don't have such checks in other
bind_pingpong_blk() callbacks.

Also there should be a guarding check for DPU >= 5.0 either here or at
the ops init.

> +
> +       c = &ctx->hw;
> +
> +       if (enable)
> +               mux_cfg = (pp - PINGPONG_0) & 0x7;
> +
> +       DPU_REG_WRITE(c, CDM_MUX, mux_cfg);
> +}
> +
> +static void _setup_cdm_ops(struct dpu_hw_cdm_ops *ops, unsigned long features)

Please inline

> +{
> +       ops->setup_csc_data = dpu_hw_cdm_setup_csc_10bit;
> +       ops->setup_cdwn = dpu_hw_cdm_setup_cdwn;
> +       ops->enable = dpu_hw_cdm_enable;
> +       ops->disable = dpu_hw_cdm_disable;
> +       ops->bind_pingpong_blk = dpu_hw_cdm_bind_pingpong_blk;

As you seem to call this function directly, we might as well drop the
callback from the ops.

> +}
> +
> +struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cfg, void __iomem *addr)
> +{
> +       struct dpu_hw_cdm *c;
> +
> +       c = kzalloc(sizeof(*c), GFP_KERNEL);
> +       if (!c)
> +               return ERR_PTR(-ENOMEM);
> +
> +       c->hw.blk_addr = addr + cfg->base;
> +       c->hw.log_mask = DPU_DBG_MASK_CDM;
> +
> +       /* Assign ops */
> +       c->idx = cfg->id;
> +       c->caps = cfg;
> +       _setup_cdm_ops(&c->ops, c->caps->features);
> +
> +       return c;
> +}
> +
> +void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm)
> +{
> +       kfree(cdm);

I'd prefer not to introduce another manual kzalloc/kfree pair, see
https://patchwork.freedesktop.org/series/120366/

> +}
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
> new file mode 100644
> index 000000000000..da60893a5c02
> --- /dev/null
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
> @@ -0,0 +1,135 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2023, The Linux Foundation. All rights reserved.
> + */
> +
> +#ifndef _DPU_HW_CDM_H
> +#define _DPU_HW_CDM_H
> +
> +#include "dpu_hw_mdss.h"
> +#include "dpu_hw_top.h"
> +
> +struct dpu_hw_cdm;
> +
> +struct dpu_hw_cdm_cfg {
> +       u32 output_width;
> +       u32 output_height;
> +       u32 output_bit_depth;
> +       u32 h_cdwn_type;
> +       u32 v_cdwn_type;
> +       const struct dpu_format *output_fmt;
> +       u32 output_type;
> +       int pp_id;
> +};
> +
> +enum dpu_hw_cdwn_type {
> +       CDM_CDWN_DISABLE,
> +       CDM_CDWN_PIXEL_DROP,
> +       CDM_CDWN_AVG,
> +       CDM_CDWN_COSITE,
> +       CDM_CDWN_OFFSITE,
> +};
> +
> +enum dpu_hw_cdwn_output_type {
> +       CDM_CDWN_OUTPUT_HDMI,
> +       CDM_CDWN_OUTPUT_WB,
> +};
> +
> +enum dpu_hw_cdwn_output_bit_depth {
> +       CDM_CDWN_OUTPUT_8BIT,
> +       CDM_CDWN_OUTPUT_10BIT,
> +};
> +
> +/**
> + * struct dpu_hw_cdm_ops : Interface to the chroma down Hw driver functions
> + *                         Assumption is these functions will be called after
> + *                         clocks are enabled
> + *  @setup_csc:            Programs the csc matrix
> + *  @setup_cdwn:           Sets up the chroma down sub module
> + *  @enable:               Enables the output to interface and programs the
> + *                         output packer
> + *  @disable:              Puts the cdm in bypass mode
> + *  @bind_pingpong_blk:    enable/disable the connection with pingpong which
> + *                         will feed pixels to this cdm
> + */
> +struct dpu_hw_cdm_ops {
> +       /**
> +        * Programs the CSC matrix for conversion from RGB space to YUV space,
> +        * it is optional to call this function as this matrix is automatically
> +        * set during initialization, user should call this if it wants
> +        * to program a different matrix than default matrix.
> +        * @cdm:          Pointer to the chroma down context structure
> +        * @data          Pointer to CSC configuration data
> +        * return:        0 if success; error code otherwise
> +        */
> +       int (*setup_csc_data)(struct dpu_hw_cdm *cdm, struct dpu_csc_cfg *data);
> +
> +       /**
> +        * Programs the Chroma downsample part.
> +        * @cdm         Pointer to chroma down context
> +        * @cfg         Pointer to the cdm configuration data
> +        */
> +       int (*setup_cdwn)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
> +
> +       /**
> +        * Enable the CDM module
> +        * @cdm         Pointer to chroma down context
> +        */
> +       int (*enable)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
> +
> +       /**
> +        * Disable the CDM module
> +        * @cdm         Pointer to chroma down context
> +        */
> +       void (*disable)(struct dpu_hw_cdm *cdm);
> +
> +       /**
> +        * Enable/disable the connection with pingpong
> +        * @cdm         Pointer to chroma down context
> +        * @enable      Enable/disable control
> +        * @pp          pingpong block id.
> +        */
> +       void (*bind_pingpong_blk)(struct dpu_hw_cdm *cdm, bool enable,
> +                                 const enum dpu_pingpong pp);
> +};
> +
> +/**
> + * struct dpu_hw_cdm - cdm description
> + * @base: Hardware block base structure
> + * @hw: Block hardware details
> + * @idx: CDM index
> + * @caps: Pointer to cdm_cfg
> + * @ops: handle to operations possible for this CDM
> + */
> +struct dpu_hw_cdm {
> +       struct dpu_hw_blk base;
> +       struct dpu_hw_blk_reg_map hw;
> +
> +       /* chroma down */
> +       const struct dpu_cdm_cfg *caps;
> +       enum  dpu_cdm  idx;
> +
> +       /* ops */
> +       struct dpu_hw_cdm_ops ops;
> +};
> +
> +/**
> + * dpu_hw_cdm_init - initializes the cdm hw driver object.
> + * should be called once before accessing every cdm.
> + * @cdm: CDM catalog entry for which driver object is required
> + * @addr :   mapped register io address of MDSS
> + */
> +struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cdm, void __iomem *addr);
> +
> +/**
> + * dpu_hw_cdm_destroy - destroys cdm driver context
> + * @cdm:   Pointer to cdm driver context returned by dpu_hw_cdm_init
> + */
> +void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm);
> +
> +static inline struct dpu_hw_cdm *to_dpu_hw_cdm(struct dpu_hw_blk *hw)
> +{
> +       return container_of(hw, struct dpu_hw_cdm, base);
> +}
> +
> +#endif /*_DPU_HW_CDM_H */
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> index 4d6dba18caf0..34f943102499 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> @@ -463,6 +463,7 @@ struct dpu_mdss_color {
>  #define DPU_DBG_MASK_ROT      (1 << 9)
>  #define DPU_DBG_MASK_DSPP     (1 << 10)
>  #define DPU_DBG_MASK_DSC      (1 << 11)
> +#define DPU_DBG_MASK_CDM      (1 << 12)
>
>  /**
>   * struct dpu_hw_tear_check - Struct contains parameters to configure
> --
> 2.40.1
>


--
With best wishes
Dmitry

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

* Re: [PATCH 08/16] drm/msm/dpu: add support to allocate CDM from RM
  2023-08-30 22:49   ` Abhinav Kumar
@ 2023-08-31  0:06     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-31  0:06 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> Even though there is usually only one CDM block, it can be
> used by either HDMI, DisplayPort OR Writeback interfaces.
>
> Hence its allocation needs to be tracked properly by the
> resource manager to ensure appropriate availability of the
> block.

It almost feels like an overkill, as up to now there is at most one CDM block.

>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  2 +-
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h |  1 +
>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h     |  1 +
>  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c      | 45 +++++++++++++++++++--
>  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h      |  4 +-
>  5 files changed, 48 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 6cf6597148fd..582680804016 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -663,7 +663,7 @@ static int dpu_encoder_virt_atomic_check(
>
>                 if (!crtc_state->active_changed || crtc_state->enable)
>                         ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
> -                                       drm_enc, crtc_state, topology);
> +                                       drm_enc, crtc_state, topology, false);
>         }
>
>         trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> index 34f943102499..07f75f295844 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> @@ -98,6 +98,7 @@ enum dpu_hw_blk_type {
>         DPU_HW_BLK_DSPP,
>         DPU_HW_BLK_MERGE_3D,
>         DPU_HW_BLK_DSC,
> +       DPU_HW_BLK_CDM,
>         DPU_HW_BLK_MAX,
>  };
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> index b6f53ca6e962..61aa58643fda 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> @@ -136,6 +136,7 @@ struct dpu_global_state {
>         uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
>         uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
>         uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
> +       uint32_t cdm_to_enc_id;
>  };
>
>  struct dpu_global_state
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> index 7b6444a3fcb1..e7d4beb4661e 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> @@ -29,10 +29,12 @@ static inline bool reserved_by_other(uint32_t *res_map, int idx,
>  /**
>   * struct dpu_rm_requirements - Reservation requirements parameter bundle
>   * @topology:  selected topology for the display
> + * @needs_cdm: whether the display needs a CDM block for the current mode
>   * @hw_res:       Hardware resources required as reported by the encoders
>   */
>  struct dpu_rm_requirements {
>         struct msm_display_topology topology;
> +       bool needs_cdm;
>  };
>
>  int dpu_rm_destroy(struct dpu_rm *rm)
> @@ -505,6 +507,26 @@ static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
>         return 0;
>  }
>
> +static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
> +                              struct dpu_global_state *global_state,
> +                              struct drm_encoder *enc)
> +{
> +       /* try allocating only one CDM block */
> +       if (!rm->cdm_blk) {
> +               DPU_ERROR("CDM block does not exist\n");
> +               return -EIO;
> +       }
> +
> +       if (global_state->cdm_to_enc_id) {
> +               DPU_ERROR("CDM_0 is already allocated\n");
> +               return -EIO;
> +       }
> +
> +       global_state->cdm_to_enc_id = enc->base.id;
> +
> +       return 0;
> +}
> +
>  static int _dpu_rm_make_reservation(
>                 struct dpu_rm *rm,
>                 struct dpu_global_state *global_state,
> @@ -530,15 +552,25 @@ static int _dpu_rm_make_reservation(
>         if (ret)
>                 return ret;
>
> +       if (reqs->needs_cdm) {
> +               ret = _dpu_rm_reserve_cdm(rm, global_state, enc);
> +               if (ret) {
> +                       DPU_ERROR("unable to find CDM blk\n");
> +                       return ret;
> +               }
> +       }
> +
>         return ret;
>  }
>
>  static int _dpu_rm_populate_requirements(
>                 struct drm_encoder *enc,
>                 struct dpu_rm_requirements *reqs,
> -               struct msm_display_topology req_topology)
> +               struct msm_display_topology req_topology,
> +               bool needs_cdm)

Push it to the topology, please. It is a part of the topology at some
point of view.

>  {
>         reqs->topology = req_topology;
> +       reqs->needs_cdm = needs_cdm;
>
>         DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
>                       reqs->topology.num_lm, reqs->topology.num_dsc,
> @@ -571,6 +603,7 @@ void dpu_rm_release(struct dpu_global_state *global_state,
>                 ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
>         _dpu_rm_clear_mapping(global_state->dspp_to_enc_id,
>                 ARRAY_SIZE(global_state->dspp_to_enc_id), enc->base.id);
> +       _dpu_rm_clear_mapping(&global_state->cdm_to_enc_id, 1, enc->base.id);
>  }
>
>  int dpu_rm_reserve(
> @@ -578,7 +611,8 @@ int dpu_rm_reserve(
>                 struct dpu_global_state *global_state,
>                 struct drm_encoder *enc,
>                 struct drm_crtc_state *crtc_state,
> -               struct msm_display_topology topology)
> +               struct msm_display_topology topology,
> +               bool needs_cdm)
>  {
>         struct dpu_rm_requirements reqs;
>         int ret;
> @@ -595,7 +629,7 @@ int dpu_rm_reserve(
>         DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
>                       enc->base.id, crtc_state->crtc->base.id);
>
> -       ret = _dpu_rm_populate_requirements(enc, &reqs, topology);
> +       ret = _dpu_rm_populate_requirements(enc, &reqs, topology, needs_cdm);
>         if (ret) {
>                 DPU_ERROR("failed to populate hw requirements\n");
>                 return ret;
> @@ -644,6 +678,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>                 hw_to_enc_id = global_state->dsc_to_enc_id;
>                 max_blks = ARRAY_SIZE(rm->dsc_blks);
>                 break;
> +       case DPU_HW_BLK_CDM:
> +               hw_blks = &rm->cdm_blk;
> +               hw_to_enc_id = &global_state->cdm_to_enc_id;
> +               max_blks = 1;
> +               break;
>         default:
>                 DPU_ERROR("blk type %d not managed by rm\n", type);
>                 return 0;
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> index 29b221491926..74262d3cb6c3 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> @@ -69,13 +69,15 @@ int dpu_rm_destroy(struct dpu_rm *rm);
>   * @drm_enc: DRM Encoder handle
>   * @crtc_state: Proposed Atomic DRM CRTC State handle
>   * @topology: Pointer to topology info for the display
> + * @needs_cdm: bool to indicate whether current encoder needs CDM
>   * @Return: 0 on Success otherwise -ERROR
>   */
>  int dpu_rm_reserve(struct dpu_rm *rm,
>                 struct dpu_global_state *global_state,
>                 struct drm_encoder *drm_enc,
>                 struct drm_crtc_state *crtc_state,
> -               struct msm_display_topology topology);
> +               struct msm_display_topology topology,
> +               bool needs_cdm);
>
>  /**
>   * dpu_rm_reserve - Given the encoder for the display chain, release any
> --
> 2.40.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH 08/16] drm/msm/dpu: add support to allocate CDM from RM
@ 2023-08-31  0:06     ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-31  0:06 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> Even though there is usually only one CDM block, it can be
> used by either HDMI, DisplayPort OR Writeback interfaces.
>
> Hence its allocation needs to be tracked properly by the
> resource manager to ensure appropriate availability of the
> block.

It almost feels like an overkill, as up to now there is at most one CDM block.

>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  2 +-
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h |  1 +
>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h     |  1 +
>  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c      | 45 +++++++++++++++++++--
>  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h      |  4 +-
>  5 files changed, 48 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 6cf6597148fd..582680804016 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -663,7 +663,7 @@ static int dpu_encoder_virt_atomic_check(
>
>                 if (!crtc_state->active_changed || crtc_state->enable)
>                         ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
> -                                       drm_enc, crtc_state, topology);
> +                                       drm_enc, crtc_state, topology, false);
>         }
>
>         trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> index 34f943102499..07f75f295844 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> @@ -98,6 +98,7 @@ enum dpu_hw_blk_type {
>         DPU_HW_BLK_DSPP,
>         DPU_HW_BLK_MERGE_3D,
>         DPU_HW_BLK_DSC,
> +       DPU_HW_BLK_CDM,
>         DPU_HW_BLK_MAX,
>  };
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> index b6f53ca6e962..61aa58643fda 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> @@ -136,6 +136,7 @@ struct dpu_global_state {
>         uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
>         uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
>         uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
> +       uint32_t cdm_to_enc_id;
>  };
>
>  struct dpu_global_state
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> index 7b6444a3fcb1..e7d4beb4661e 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> @@ -29,10 +29,12 @@ static inline bool reserved_by_other(uint32_t *res_map, int idx,
>  /**
>   * struct dpu_rm_requirements - Reservation requirements parameter bundle
>   * @topology:  selected topology for the display
> + * @needs_cdm: whether the display needs a CDM block for the current mode
>   * @hw_res:       Hardware resources required as reported by the encoders
>   */
>  struct dpu_rm_requirements {
>         struct msm_display_topology topology;
> +       bool needs_cdm;
>  };
>
>  int dpu_rm_destroy(struct dpu_rm *rm)
> @@ -505,6 +507,26 @@ static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
>         return 0;
>  }
>
> +static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
> +                              struct dpu_global_state *global_state,
> +                              struct drm_encoder *enc)
> +{
> +       /* try allocating only one CDM block */
> +       if (!rm->cdm_blk) {
> +               DPU_ERROR("CDM block does not exist\n");
> +               return -EIO;
> +       }
> +
> +       if (global_state->cdm_to_enc_id) {
> +               DPU_ERROR("CDM_0 is already allocated\n");
> +               return -EIO;
> +       }
> +
> +       global_state->cdm_to_enc_id = enc->base.id;
> +
> +       return 0;
> +}
> +
>  static int _dpu_rm_make_reservation(
>                 struct dpu_rm *rm,
>                 struct dpu_global_state *global_state,
> @@ -530,15 +552,25 @@ static int _dpu_rm_make_reservation(
>         if (ret)
>                 return ret;
>
> +       if (reqs->needs_cdm) {
> +               ret = _dpu_rm_reserve_cdm(rm, global_state, enc);
> +               if (ret) {
> +                       DPU_ERROR("unable to find CDM blk\n");
> +                       return ret;
> +               }
> +       }
> +
>         return ret;
>  }
>
>  static int _dpu_rm_populate_requirements(
>                 struct drm_encoder *enc,
>                 struct dpu_rm_requirements *reqs,
> -               struct msm_display_topology req_topology)
> +               struct msm_display_topology req_topology,
> +               bool needs_cdm)

Push it to the topology, please. It is a part of the topology at some
point of view.

>  {
>         reqs->topology = req_topology;
> +       reqs->needs_cdm = needs_cdm;
>
>         DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
>                       reqs->topology.num_lm, reqs->topology.num_dsc,
> @@ -571,6 +603,7 @@ void dpu_rm_release(struct dpu_global_state *global_state,
>                 ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
>         _dpu_rm_clear_mapping(global_state->dspp_to_enc_id,
>                 ARRAY_SIZE(global_state->dspp_to_enc_id), enc->base.id);
> +       _dpu_rm_clear_mapping(&global_state->cdm_to_enc_id, 1, enc->base.id);
>  }
>
>  int dpu_rm_reserve(
> @@ -578,7 +611,8 @@ int dpu_rm_reserve(
>                 struct dpu_global_state *global_state,
>                 struct drm_encoder *enc,
>                 struct drm_crtc_state *crtc_state,
> -               struct msm_display_topology topology)
> +               struct msm_display_topology topology,
> +               bool needs_cdm)
>  {
>         struct dpu_rm_requirements reqs;
>         int ret;
> @@ -595,7 +629,7 @@ int dpu_rm_reserve(
>         DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
>                       enc->base.id, crtc_state->crtc->base.id);
>
> -       ret = _dpu_rm_populate_requirements(enc, &reqs, topology);
> +       ret = _dpu_rm_populate_requirements(enc, &reqs, topology, needs_cdm);
>         if (ret) {
>                 DPU_ERROR("failed to populate hw requirements\n");
>                 return ret;
> @@ -644,6 +678,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>                 hw_to_enc_id = global_state->dsc_to_enc_id;
>                 max_blks = ARRAY_SIZE(rm->dsc_blks);
>                 break;
> +       case DPU_HW_BLK_CDM:
> +               hw_blks = &rm->cdm_blk;
> +               hw_to_enc_id = &global_state->cdm_to_enc_id;
> +               max_blks = 1;
> +               break;
>         default:
>                 DPU_ERROR("blk type %d not managed by rm\n", type);
>                 return 0;
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> index 29b221491926..74262d3cb6c3 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> @@ -69,13 +69,15 @@ int dpu_rm_destroy(struct dpu_rm *rm);
>   * @drm_enc: DRM Encoder handle
>   * @crtc_state: Proposed Atomic DRM CRTC State handle
>   * @topology: Pointer to topology info for the display
> + * @needs_cdm: bool to indicate whether current encoder needs CDM
>   * @Return: 0 on Success otherwise -ERROR
>   */
>  int dpu_rm_reserve(struct dpu_rm *rm,
>                 struct dpu_global_state *global_state,
>                 struct drm_encoder *drm_enc,
>                 struct drm_crtc_state *crtc_state,
> -               struct msm_display_topology topology);
> +               struct msm_display_topology topology,
> +               bool needs_cdm);
>
>  /**
>   * dpu_rm_reserve - Given the encoder for the display chain, release any
> --
> 2.40.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH 11/16] drm/msm/dpu: add an API to setup the CDM block for writeback
  2023-08-30 22:49   ` Abhinav Kumar
@ 2023-08-31  0:11     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-31  0:11 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> Add an API dpu_encoder_helper_phys_setup_cdm() which can be used by
> the writeback encoder to setup the CDM block.
>
> Currently, this is defined and used within the writeback's physical
> encoder layer however, the function can be modified to be used to setup
> the CDM block even for non-writeback interfaces.
>
> Until those modifications are planned and made, keep it local to
> writeback.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   3 +
>  .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 123 +++++++++++++++++-
>  2 files changed, 125 insertions(+), 1 deletion(-)
>
> 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 510c1c41ddbc..93a8ae67beff 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> @@ -16,6 +16,7 @@
>  #include "dpu_hw_pingpong.h"
>  #include "dpu_hw_ctl.h"
>  #include "dpu_hw_top.h"
> +#include "dpu_hw_cdm.h"
>  #include "dpu_encoder.h"
>  #include "dpu_crtc.h"
>
> @@ -209,6 +210,7 @@ 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
> @@ -218,6 +220,7 @@ 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 4c2736c3ee6d..11935aac9fd5 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
> @@ -24,6 +24,20 @@
>  #define to_dpu_encoder_phys_wb(x) \
>         container_of(x, struct dpu_encoder_phys_wb, base)
>
> +#define TO_S15D16(_x_)((_x_) << 7)
> +
> +static struct dpu_csc_cfg dpu_encoder_phys_wb_rgb2yuv_601l = {
> +       {
> +               TO_S15D16(0x0083), TO_S15D16(0x0102), TO_S15D16(0x0032),
> +               TO_S15D16(0x1fb5), TO_S15D16(0x1f6c), TO_S15D16(0x00e1),
> +               TO_S15D16(0x00e1), TO_S15D16(0x1f45), TO_S15D16(0x1fdc)
> +       },
> +       { 0x00, 0x00, 0x00 },
> +       { 0x0040, 0x0200, 0x0200 },
> +       { 0x000, 0x3ff, 0x000, 0x3ff, 0x000, 0x3ff },
> +       { 0x040, 0x3ac, 0x040, 0x3c0, 0x040, 0x3c0 },
> +};

Nit: we probably need to have a single place with all dpu_csc_cfg entries.

> +
>  /**
>   * dpu_encoder_phys_wb_is_master - report wb always as master encoder
>   * @phys_enc:  Pointer to physical encoder
> @@ -225,6 +239,112 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
>         }
>  }
>
> +/**
> + * dpu_encoder_phys_wb_setup_cdp - setup chroma down sampling block
> + * @phys_enc:Pointer to physical encoder
> + */
> +static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
> +{
> +       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;
> +       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;
> +
> +       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.disable)
> +                       hw_cdm->ops.disable(hw_cdm);
> +
> +               return;
> +       }
> +
> +       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_fmt = dpu_fmt;
> +       cdm_cfg->output_type = CDM_CDWN_OUTPUT_WB;
> +       cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
> +                       CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
> +
> +       /* 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 && hw_cdm->ops.setup_csc_data) {
> +               ret = hw_cdm->ops.setup_csc_data(hw_cdm, &dpu_encoder_phys_wb_rgb2yuv_601l);
> +               if (ret < 0) {
> +                       DPU_ERROR("[enc:%d] failed to setup CSC; ret:%d\n",
> +                                 DRMID(phys_enc->parent), ret);
> +                       return;
> +               }
> +       }
> +
> +       if (hw_cdm && hw_cdm->ops.setup_cdwn) {

You have checked for (!hw_cdm) several lines above. We can drop this
condition here.

> +               ret = hw_cdm->ops.setup_cdwn(hw_cdm, cdm_cfg);
> +               if (ret < 0) {
> +                       DPU_ERROR("[enc:%d] failed to setup CDWN; ret:%d\n",
> +                                 DRMID(phys_enc->parent), ret);
> +                       return;
> +               }
> +       }
> +
> +       if (hw_cdm && hw_pp && hw_cdm->ops.enable) {

And what if !hw_pp ? Can it happen here? No, if I understand correctly.

> +               cdm_cfg->pp_id = hw_pp->idx;
> +               ret = hw_cdm->ops.enable(hw_cdm, cdm_cfg);

As we are calling these three ops in a row, can we merge them together
into a single callback to be called from dpu_encoder.c?

> +               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
> @@ -348,8 +468,9 @@ static void dpu_encoder_phys_wb_setup(
>
>         dpu_encoder_phys_wb_setup_fb(phys_enc, fb);
>
> -       dpu_encoder_phys_wb_setup_ctl(phys_enc);
> +       dpu_encoder_helper_phys_setup_cdm(phys_enc);
>
> +       dpu_encoder_phys_wb_setup_ctl(phys_enc);
>  }
>
>  static void _dpu_encoder_phys_wb_frame_done_helper(void *arg)
> --
> 2.40.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH 11/16] drm/msm/dpu: add an API to setup the CDM block for writeback
@ 2023-08-31  0:11     ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-31  0:11 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> Add an API dpu_encoder_helper_phys_setup_cdm() which can be used by
> the writeback encoder to setup the CDM block.
>
> Currently, this is defined and used within the writeback's physical
> encoder layer however, the function can be modified to be used to setup
> the CDM block even for non-writeback interfaces.
>
> Until those modifications are planned and made, keep it local to
> writeback.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   3 +
>  .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 123 +++++++++++++++++-
>  2 files changed, 125 insertions(+), 1 deletion(-)
>
> 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 510c1c41ddbc..93a8ae67beff 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> @@ -16,6 +16,7 @@
>  #include "dpu_hw_pingpong.h"
>  #include "dpu_hw_ctl.h"
>  #include "dpu_hw_top.h"
> +#include "dpu_hw_cdm.h"
>  #include "dpu_encoder.h"
>  #include "dpu_crtc.h"
>
> @@ -209,6 +210,7 @@ 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
> @@ -218,6 +220,7 @@ 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 4c2736c3ee6d..11935aac9fd5 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
> @@ -24,6 +24,20 @@
>  #define to_dpu_encoder_phys_wb(x) \
>         container_of(x, struct dpu_encoder_phys_wb, base)
>
> +#define TO_S15D16(_x_)((_x_) << 7)
> +
> +static struct dpu_csc_cfg dpu_encoder_phys_wb_rgb2yuv_601l = {
> +       {
> +               TO_S15D16(0x0083), TO_S15D16(0x0102), TO_S15D16(0x0032),
> +               TO_S15D16(0x1fb5), TO_S15D16(0x1f6c), TO_S15D16(0x00e1),
> +               TO_S15D16(0x00e1), TO_S15D16(0x1f45), TO_S15D16(0x1fdc)
> +       },
> +       { 0x00, 0x00, 0x00 },
> +       { 0x0040, 0x0200, 0x0200 },
> +       { 0x000, 0x3ff, 0x000, 0x3ff, 0x000, 0x3ff },
> +       { 0x040, 0x3ac, 0x040, 0x3c0, 0x040, 0x3c0 },
> +};

Nit: we probably need to have a single place with all dpu_csc_cfg entries.

> +
>  /**
>   * dpu_encoder_phys_wb_is_master - report wb always as master encoder
>   * @phys_enc:  Pointer to physical encoder
> @@ -225,6 +239,112 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
>         }
>  }
>
> +/**
> + * dpu_encoder_phys_wb_setup_cdp - setup chroma down sampling block
> + * @phys_enc:Pointer to physical encoder
> + */
> +static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
> +{
> +       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;
> +       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;
> +
> +       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.disable)
> +                       hw_cdm->ops.disable(hw_cdm);
> +
> +               return;
> +       }
> +
> +       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_fmt = dpu_fmt;
> +       cdm_cfg->output_type = CDM_CDWN_OUTPUT_WB;
> +       cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
> +                       CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
> +
> +       /* 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 && hw_cdm->ops.setup_csc_data) {
> +               ret = hw_cdm->ops.setup_csc_data(hw_cdm, &dpu_encoder_phys_wb_rgb2yuv_601l);
> +               if (ret < 0) {
> +                       DPU_ERROR("[enc:%d] failed to setup CSC; ret:%d\n",
> +                                 DRMID(phys_enc->parent), ret);
> +                       return;
> +               }
> +       }
> +
> +       if (hw_cdm && hw_cdm->ops.setup_cdwn) {

You have checked for (!hw_cdm) several lines above. We can drop this
condition here.

> +               ret = hw_cdm->ops.setup_cdwn(hw_cdm, cdm_cfg);
> +               if (ret < 0) {
> +                       DPU_ERROR("[enc:%d] failed to setup CDWN; ret:%d\n",
> +                                 DRMID(phys_enc->parent), ret);
> +                       return;
> +               }
> +       }
> +
> +       if (hw_cdm && hw_pp && hw_cdm->ops.enable) {

And what if !hw_pp ? Can it happen here? No, if I understand correctly.

> +               cdm_cfg->pp_id = hw_pp->idx;
> +               ret = hw_cdm->ops.enable(hw_cdm, cdm_cfg);

As we are calling these three ops in a row, can we merge them together
into a single callback to be called from dpu_encoder.c?

> +               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
> @@ -348,8 +468,9 @@ static void dpu_encoder_phys_wb_setup(
>
>         dpu_encoder_phys_wb_setup_fb(phys_enc, fb);
>
> -       dpu_encoder_phys_wb_setup_ctl(phys_enc);
> +       dpu_encoder_helper_phys_setup_cdm(phys_enc);
>
> +       dpu_encoder_phys_wb_setup_ctl(phys_enc);
>  }
>
>  static void _dpu_encoder_phys_wb_frame_done_helper(void *arg)
> --
> 2.40.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH 09/16] drm/msm/dpu: add CDM related logic to dpu_hw_ctl layer
  2023-08-30 22:49   ` Abhinav Kumar
@ 2023-08-31  0:12     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-31  0:12 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> CDM block will need its own logic to program the flush and active
> bits in the dpu_hw_ctl layer.
>
> Make necessary changes in dpu_hw_ctl to support CDM programming.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 34 ++++++++++++++++++++++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 11 +++++++
>  2 files changed, 45 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 c278fb9d2b5b..beced9f19740 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> @@ -29,11 +29,13 @@
>  #define   CTL_DSC_ACTIVE                0x0E8
>  #define   CTL_WB_ACTIVE                 0x0EC
>  #define   CTL_INTF_ACTIVE               0x0F4
> +#define   CTL_CDM_ACTIVE                0x0F8
>  #define   CTL_FETCH_PIPE_ACTIVE         0x0FC
>  #define   CTL_MERGE_3D_FLUSH            0x100
>  #define   CTL_DSC_FLUSH                0x104
>  #define   CTL_WB_FLUSH                  0x108
>  #define   CTL_INTF_FLUSH                0x110
> +#define   CTL_CDM_FLUSH                0x114
>  #define   CTL_INTF_MASTER               0x134
>  #define   CTL_DSPP_n_FLUSH(n)           ((0x13C) + ((n) * 4))
>
> @@ -43,6 +45,7 @@
>  #define DPU_REG_RESET_TIMEOUT_US        2000
>  #define  MERGE_3D_IDX   23
>  #define  DSC_IDX        22
> +#define CDM_IDX         26
>  #define  INTF_IDX       31
>  #define WB_IDX          16
>  #define  DSPP_IDX       29  /* From DPU hw rev 7.x.x */
> @@ -104,6 +107,7 @@ static inline void dpu_hw_ctl_clear_pending_flush(struct dpu_hw_ctl *ctx)
>         ctx->pending_wb_flush_mask = 0;
>         ctx->pending_merge_3d_flush_mask = 0;
>         ctx->pending_dsc_flush_mask = 0;
> +       ctx->pending_cdm_flush_mask = 0;
>
>         memset(ctx->pending_dspp_flush_mask, 0,
>                 sizeof(ctx->pending_dspp_flush_mask));
> @@ -148,6 +152,10 @@ static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
>                 DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH,
>                               ctx->pending_dsc_flush_mask);
>
> +       if (ctx->pending_flush_mask & BIT(CDM_IDX))
> +               DPU_REG_WRITE(&ctx->hw, CTL_CDM_FLUSH,
> +                             ctx->pending_cdm_flush_mask);
> +
>         DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask);
>  }
>
> @@ -273,6 +281,12 @@ static void dpu_hw_ctl_update_pending_flush_wb(struct dpu_hw_ctl *ctx,
>         }
>  }
>
> +static void dpu_hw_ctl_update_pending_flush_cdm(struct dpu_hw_ctl *ctx)
> +{
> +       ctx->pending_flush_mask |= BIT(CDM_IDX);
> +

unused empty line.

> +}
> +
>  static void dpu_hw_ctl_update_pending_flush_wb_v1(struct dpu_hw_ctl *ctx,
>                 enum dpu_wb wb)
>  {
> @@ -301,6 +315,12 @@ static void dpu_hw_ctl_update_pending_flush_dsc_v1(struct dpu_hw_ctl *ctx,
>         ctx->pending_flush_mask |= BIT(DSC_IDX);
>  }
>
> +static void dpu_hw_ctl_update_pending_flush_cdm_v1(struct dpu_hw_ctl *ctx)
> +{
> +       ctx->pending_cdm_flush_mask |= BIT(0);

I'd assume this is because there is just CDM_0? Then it still might be
better to write BIT(cdm->idx - CDM_0).

> +       ctx->pending_flush_mask |= BIT(CDM_IDX);
> +}
> +
>  static void dpu_hw_ctl_update_pending_flush_dspp(struct dpu_hw_ctl *ctx,
>         enum dpu_dspp dspp, u32 dspp_sub_blk)
>  {
> @@ -504,6 +524,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
>         u32 intf_active = 0;
>         u32 wb_active = 0;
>         u32 mode_sel = 0;
> +       u32 cdm_active = 0;
>
>         /* CTL_TOP[31:28] carries group_id to collate CTL paths
>          * per VM. Explicitly disable it until VM support is
> @@ -517,6 +538,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
>
>         intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE);
>         wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE);
> +       cdm_active = DPU_REG_READ(c, CTL_CDM_ACTIVE);
>
>         if (cfg->intf)
>                 intf_active |= BIT(cfg->intf - INTF_0);
> @@ -534,6 +556,9 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
>
>         if (cfg->dsc)
>                 DPU_REG_WRITE(c, CTL_DSC_ACTIVE, cfg->dsc);
> +
> +       if (cfg->cdm)
> +               DPU_REG_WRITE(c, CTL_CDM_ACTIVE, cfg->cdm);
>  }
>
>  static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
> @@ -577,6 +602,7 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx,
>         u32 wb_active = 0;
>         u32 merge3d_active = 0;
>         u32 dsc_active;
> +       u32 cdm_active;
>
>         /*
>          * This API resets each portion of the CTL path namely,
> @@ -612,6 +638,12 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx,
>                 dsc_active &= ~cfg->dsc;
>                 DPU_REG_WRITE(c, CTL_DSC_ACTIVE, dsc_active);
>         }
> +
> +       if (cfg->cdm) {
> +               cdm_active = DPU_REG_READ(c, CTL_CDM_ACTIVE);
> +               cdm_active &= ~cfg->cdm;
> +               DPU_REG_WRITE(c, CTL_CDM_ACTIVE, cdm_active);
> +       }
>  }
>
>  static void dpu_hw_ctl_set_fetch_pipe_active(struct dpu_hw_ctl *ctx,
> @@ -645,12 +677,14 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
>                 ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb_v1;
>                 ops->update_pending_flush_dsc =
>                         dpu_hw_ctl_update_pending_flush_dsc_v1;
> +               ops->update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm_v1;
>         } else {
>                 ops->trigger_flush = dpu_hw_ctl_trigger_flush;
>                 ops->setup_intf_cfg = dpu_hw_ctl_intf_cfg;
>                 ops->update_pending_flush_intf =
>                         dpu_hw_ctl_update_pending_flush_intf;
>                 ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb;
> +               ops->update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm;
>         }
>         ops->clear_pending_flush = dpu_hw_ctl_clear_pending_flush;
>         ops->update_pending_flush = dpu_hw_ctl_update_pending_flush;
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> index 1c242298ff2e..6dd44dfdfb61 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> @@ -39,6 +39,7 @@ struct dpu_hw_stage_cfg {
>   * @mode_3d:               3d mux configuration
>   * @merge_3d:              3d merge block used
>   * @intf_mode_sel:         Interface mode, cmd / vid
> + * @cdm:                   CDM block used
>   * @stream_sel:            Stream selection for multi-stream interfaces
>   * @dsc:                   DSC BIT masks used
>   */
> @@ -48,6 +49,7 @@ struct dpu_hw_intf_cfg {
>         enum dpu_3d_blend_mode mode_3d;
>         enum dpu_merge_3d merge_3d;
>         enum dpu_ctl_mode_sel intf_mode_sel;
> +       enum dpu_cdm cdm;
>         int stream_sel;
>         unsigned int dsc;
>  };
> @@ -166,6 +168,13 @@ struct dpu_hw_ctl_ops {
>         void (*update_pending_flush_dsc)(struct dpu_hw_ctl *ctx,
>                                          enum dpu_dsc blk);
>
> +       /**
> +        * OR in the given flushbits to the cached pending_(cdm_)flush_mask
> +        * No effect on hardware
> +        * @ctx: ctl path ctx pointer
> +        */
> +       void (*update_pending_flush_cdm)(struct dpu_hw_ctl *ctx);
> +
>         /**
>          * Write the value of the pending_flush_mask to hardware
>          * @ctx       : ctl path ctx pointer
> @@ -239,6 +248,7 @@ struct dpu_hw_ctl_ops {
>   * @pending_intf_flush_mask: pending INTF flush
>   * @pending_wb_flush_mask: pending WB flush
>   * @pending_dsc_flush_mask: pending DSC flush
> + * @pending_cdm_flush_mask: pending CDM flush
>   * @ops: operation list
>   */
>  struct dpu_hw_ctl {
> @@ -256,6 +266,7 @@ struct dpu_hw_ctl {
>         u32 pending_merge_3d_flush_mask;
>         u32 pending_dspp_flush_mask[DSPP_MAX - DSPP_0];
>         u32 pending_dsc_flush_mask;
> +       u32 pending_cdm_flush_mask;
>
>         /* ops */
>         struct dpu_hw_ctl_ops ops;
> --
> 2.40.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH 09/16] drm/msm/dpu: add CDM related logic to dpu_hw_ctl layer
@ 2023-08-31  0:12     ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-31  0:12 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> CDM block will need its own logic to program the flush and active
> bits in the dpu_hw_ctl layer.
>
> Make necessary changes in dpu_hw_ctl to support CDM programming.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 34 ++++++++++++++++++++++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 11 +++++++
>  2 files changed, 45 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 c278fb9d2b5b..beced9f19740 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> @@ -29,11 +29,13 @@
>  #define   CTL_DSC_ACTIVE                0x0E8
>  #define   CTL_WB_ACTIVE                 0x0EC
>  #define   CTL_INTF_ACTIVE               0x0F4
> +#define   CTL_CDM_ACTIVE                0x0F8
>  #define   CTL_FETCH_PIPE_ACTIVE         0x0FC
>  #define   CTL_MERGE_3D_FLUSH            0x100
>  #define   CTL_DSC_FLUSH                0x104
>  #define   CTL_WB_FLUSH                  0x108
>  #define   CTL_INTF_FLUSH                0x110
> +#define   CTL_CDM_FLUSH                0x114
>  #define   CTL_INTF_MASTER               0x134
>  #define   CTL_DSPP_n_FLUSH(n)           ((0x13C) + ((n) * 4))
>
> @@ -43,6 +45,7 @@
>  #define DPU_REG_RESET_TIMEOUT_US        2000
>  #define  MERGE_3D_IDX   23
>  #define  DSC_IDX        22
> +#define CDM_IDX         26
>  #define  INTF_IDX       31
>  #define WB_IDX          16
>  #define  DSPP_IDX       29  /* From DPU hw rev 7.x.x */
> @@ -104,6 +107,7 @@ static inline void dpu_hw_ctl_clear_pending_flush(struct dpu_hw_ctl *ctx)
>         ctx->pending_wb_flush_mask = 0;
>         ctx->pending_merge_3d_flush_mask = 0;
>         ctx->pending_dsc_flush_mask = 0;
> +       ctx->pending_cdm_flush_mask = 0;
>
>         memset(ctx->pending_dspp_flush_mask, 0,
>                 sizeof(ctx->pending_dspp_flush_mask));
> @@ -148,6 +152,10 @@ static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
>                 DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH,
>                               ctx->pending_dsc_flush_mask);
>
> +       if (ctx->pending_flush_mask & BIT(CDM_IDX))
> +               DPU_REG_WRITE(&ctx->hw, CTL_CDM_FLUSH,
> +                             ctx->pending_cdm_flush_mask);
> +
>         DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask);
>  }
>
> @@ -273,6 +281,12 @@ static void dpu_hw_ctl_update_pending_flush_wb(struct dpu_hw_ctl *ctx,
>         }
>  }
>
> +static void dpu_hw_ctl_update_pending_flush_cdm(struct dpu_hw_ctl *ctx)
> +{
> +       ctx->pending_flush_mask |= BIT(CDM_IDX);
> +

unused empty line.

> +}
> +
>  static void dpu_hw_ctl_update_pending_flush_wb_v1(struct dpu_hw_ctl *ctx,
>                 enum dpu_wb wb)
>  {
> @@ -301,6 +315,12 @@ static void dpu_hw_ctl_update_pending_flush_dsc_v1(struct dpu_hw_ctl *ctx,
>         ctx->pending_flush_mask |= BIT(DSC_IDX);
>  }
>
> +static void dpu_hw_ctl_update_pending_flush_cdm_v1(struct dpu_hw_ctl *ctx)
> +{
> +       ctx->pending_cdm_flush_mask |= BIT(0);

I'd assume this is because there is just CDM_0? Then it still might be
better to write BIT(cdm->idx - CDM_0).

> +       ctx->pending_flush_mask |= BIT(CDM_IDX);
> +}
> +
>  static void dpu_hw_ctl_update_pending_flush_dspp(struct dpu_hw_ctl *ctx,
>         enum dpu_dspp dspp, u32 dspp_sub_blk)
>  {
> @@ -504,6 +524,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
>         u32 intf_active = 0;
>         u32 wb_active = 0;
>         u32 mode_sel = 0;
> +       u32 cdm_active = 0;
>
>         /* CTL_TOP[31:28] carries group_id to collate CTL paths
>          * per VM. Explicitly disable it until VM support is
> @@ -517,6 +538,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
>
>         intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE);
>         wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE);
> +       cdm_active = DPU_REG_READ(c, CTL_CDM_ACTIVE);
>
>         if (cfg->intf)
>                 intf_active |= BIT(cfg->intf - INTF_0);
> @@ -534,6 +556,9 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
>
>         if (cfg->dsc)
>                 DPU_REG_WRITE(c, CTL_DSC_ACTIVE, cfg->dsc);
> +
> +       if (cfg->cdm)
> +               DPU_REG_WRITE(c, CTL_CDM_ACTIVE, cfg->cdm);
>  }
>
>  static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
> @@ -577,6 +602,7 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx,
>         u32 wb_active = 0;
>         u32 merge3d_active = 0;
>         u32 dsc_active;
> +       u32 cdm_active;
>
>         /*
>          * This API resets each portion of the CTL path namely,
> @@ -612,6 +638,12 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx,
>                 dsc_active &= ~cfg->dsc;
>                 DPU_REG_WRITE(c, CTL_DSC_ACTIVE, dsc_active);
>         }
> +
> +       if (cfg->cdm) {
> +               cdm_active = DPU_REG_READ(c, CTL_CDM_ACTIVE);
> +               cdm_active &= ~cfg->cdm;
> +               DPU_REG_WRITE(c, CTL_CDM_ACTIVE, cdm_active);
> +       }
>  }
>
>  static void dpu_hw_ctl_set_fetch_pipe_active(struct dpu_hw_ctl *ctx,
> @@ -645,12 +677,14 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
>                 ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb_v1;
>                 ops->update_pending_flush_dsc =
>                         dpu_hw_ctl_update_pending_flush_dsc_v1;
> +               ops->update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm_v1;
>         } else {
>                 ops->trigger_flush = dpu_hw_ctl_trigger_flush;
>                 ops->setup_intf_cfg = dpu_hw_ctl_intf_cfg;
>                 ops->update_pending_flush_intf =
>                         dpu_hw_ctl_update_pending_flush_intf;
>                 ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb;
> +               ops->update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm;
>         }
>         ops->clear_pending_flush = dpu_hw_ctl_clear_pending_flush;
>         ops->update_pending_flush = dpu_hw_ctl_update_pending_flush;
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> index 1c242298ff2e..6dd44dfdfb61 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
> @@ -39,6 +39,7 @@ struct dpu_hw_stage_cfg {
>   * @mode_3d:               3d mux configuration
>   * @merge_3d:              3d merge block used
>   * @intf_mode_sel:         Interface mode, cmd / vid
> + * @cdm:                   CDM block used
>   * @stream_sel:            Stream selection for multi-stream interfaces
>   * @dsc:                   DSC BIT masks used
>   */
> @@ -48,6 +49,7 @@ struct dpu_hw_intf_cfg {
>         enum dpu_3d_blend_mode mode_3d;
>         enum dpu_merge_3d merge_3d;
>         enum dpu_ctl_mode_sel intf_mode_sel;
> +       enum dpu_cdm cdm;
>         int stream_sel;
>         unsigned int dsc;
>  };
> @@ -166,6 +168,13 @@ struct dpu_hw_ctl_ops {
>         void (*update_pending_flush_dsc)(struct dpu_hw_ctl *ctx,
>                                          enum dpu_dsc blk);
>
> +       /**
> +        * OR in the given flushbits to the cached pending_(cdm_)flush_mask
> +        * No effect on hardware
> +        * @ctx: ctl path ctx pointer
> +        */
> +       void (*update_pending_flush_cdm)(struct dpu_hw_ctl *ctx);
> +
>         /**
>          * Write the value of the pending_flush_mask to hardware
>          * @ctx       : ctl path ctx pointer
> @@ -239,6 +248,7 @@ struct dpu_hw_ctl_ops {
>   * @pending_intf_flush_mask: pending INTF flush
>   * @pending_wb_flush_mask: pending WB flush
>   * @pending_dsc_flush_mask: pending DSC flush
> + * @pending_cdm_flush_mask: pending CDM flush
>   * @ops: operation list
>   */
>  struct dpu_hw_ctl {
> @@ -256,6 +266,7 @@ struct dpu_hw_ctl {
>         u32 pending_merge_3d_flush_mask;
>         u32 pending_dspp_flush_mask[DSPP_MAX - DSPP_0];
>         u32 pending_dsc_flush_mask;
> +       u32 pending_cdm_flush_mask;
>
>         /* ops */
>         struct dpu_hw_ctl_ops ops;
> --
> 2.40.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH 10/16] drm/msm/dpu: add support to disable CDM block during encoder cleanup
  2023-08-30 22:49   ` Abhinav Kumar
@ 2023-08-31  0:14     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-31  0:14 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> In preparation of setting up CDM block, add the logic to disable it
> properly during encoder cleanup.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c      | 8 ++++++++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 2 ++
>  2 files changed, 10 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 582680804016..1b1e07292a9e 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -26,6 +26,7 @@
>  #include "dpu_hw_dspp.h"
>  #include "dpu_hw_dsc.h"
>  #include "dpu_hw_merge3d.h"
> +#include "dpu_hw_cdm.h"
>  #include "dpu_formats.h"
>  #include "dpu_encoder_phys.h"
>  #include "dpu_crtc.h"
> @@ -2097,6 +2098,13 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
>                                         phys_enc->hw_pp->merge_3d->idx);
>         }
>
> +       if (phys_enc->hw_cdm && phys_enc->hw_cdm->ops.bind_pingpong_blk && phys_enc->hw_pp) {
> +               phys_enc->hw_cdm->ops.bind_pingpong_blk(phys_enc->hw_cdm,
> +                                                       false, phys_enc->hw_pp->idx);

But it was already bound in the cdm->enable, wasn't it?

Also the update_pending_flush_cdm should be called even for DPU < 5.0,
where there should be no bind_pingpong_blk callback.

> +               if (phys_enc->hw_ctl->ops.update_pending_flush_cdm)
> +                       phys_enc->hw_ctl->ops.update_pending_flush_cdm(phys_enc->hw_ctl);
> +       }
> +
>         if (dpu_enc->dsc) {
>                 dpu_encoder_unprep_dsc(dpu_enc);
>                 dpu_enc->dsc = NULL;
> 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 24dbc28be4f8..510c1c41ddbc 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> @@ -150,6 +150,7 @@ enum dpu_intr_idx {
>   * @hw_pp:             Hardware interface to the ping pong registers
>   * @hw_intf:           Hardware interface to the intf registers
>   * @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
>   * @cached_mode:       DRM mode cached at mode_set time, acted on in enable
>   * @enabled:           Whether the encoder has enabled and running a mode
> @@ -178,6 +179,7 @@ struct dpu_encoder_phys {
>         struct dpu_hw_pingpong *hw_pp;
>         struct dpu_hw_intf *hw_intf;
>         struct dpu_hw_wb *hw_wb;
> +       struct dpu_hw_cdm *hw_cdm;
>         struct dpu_kms *dpu_kms;
>         struct drm_display_mode cached_mode;
>         enum dpu_enc_split_role split_role;
> --
> 2.40.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH 10/16] drm/msm/dpu: add support to disable CDM block during encoder cleanup
@ 2023-08-31  0:14     ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-31  0:14 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> In preparation of setting up CDM block, add the logic to disable it
> properly during encoder cleanup.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c      | 8 ++++++++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 2 ++
>  2 files changed, 10 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 582680804016..1b1e07292a9e 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -26,6 +26,7 @@
>  #include "dpu_hw_dspp.h"
>  #include "dpu_hw_dsc.h"
>  #include "dpu_hw_merge3d.h"
> +#include "dpu_hw_cdm.h"
>  #include "dpu_formats.h"
>  #include "dpu_encoder_phys.h"
>  #include "dpu_crtc.h"
> @@ -2097,6 +2098,13 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
>                                         phys_enc->hw_pp->merge_3d->idx);
>         }
>
> +       if (phys_enc->hw_cdm && phys_enc->hw_cdm->ops.bind_pingpong_blk && phys_enc->hw_pp) {
> +               phys_enc->hw_cdm->ops.bind_pingpong_blk(phys_enc->hw_cdm,
> +                                                       false, phys_enc->hw_pp->idx);

But it was already bound in the cdm->enable, wasn't it?

Also the update_pending_flush_cdm should be called even for DPU < 5.0,
where there should be no bind_pingpong_blk callback.

> +               if (phys_enc->hw_ctl->ops.update_pending_flush_cdm)
> +                       phys_enc->hw_ctl->ops.update_pending_flush_cdm(phys_enc->hw_ctl);
> +       }
> +
>         if (dpu_enc->dsc) {
>                 dpu_encoder_unprep_dsc(dpu_enc);
>                 dpu_enc->dsc = NULL;
> 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 24dbc28be4f8..510c1c41ddbc 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> @@ -150,6 +150,7 @@ enum dpu_intr_idx {
>   * @hw_pp:             Hardware interface to the ping pong registers
>   * @hw_intf:           Hardware interface to the intf registers
>   * @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
>   * @cached_mode:       DRM mode cached at mode_set time, acted on in enable
>   * @enabled:           Whether the encoder has enabled and running a mode
> @@ -178,6 +179,7 @@ struct dpu_encoder_phys {
>         struct dpu_hw_pingpong *hw_pp;
>         struct dpu_hw_intf *hw_intf;
>         struct dpu_hw_wb *hw_wb;
> +       struct dpu_hw_cdm *hw_cdm;
>         struct dpu_kms *dpu_kms;
>         struct drm_display_mode cached_mode;
>         enum dpu_enc_split_role split_role;
> --
> 2.40.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH 12/16] drm/msm/dpu: plug-in the cdm related bits to writeback setup
  2023-08-30 22:49   ` Abhinav Kumar
@ 2023-08-31  0:15     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-31  0:15 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> To setup and enable CDM block for the writeback pipeline, lets
> add the pieces together to set the active bits and the flush
> bits for the CDM block.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>

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

> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)


-- 
With best wishes
Dmitry

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

* Re: [PATCH 12/16] drm/msm/dpu: plug-in the cdm related bits to writeback setup
@ 2023-08-31  0:15     ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-31  0:15 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> To setup and enable CDM block for the writeback pipeline, lets
> add the pieces together to set the active bits and the flush
> bits for the CDM block.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>

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

> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)


-- 
With best wishes
Dmitry

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

* Re: [PATCH 13/16] drm/msm/dpu: reserve cdm blocks for writeback in case of YUV output
  2023-08-30 22:49   ` Abhinav Kumar
@ 2023-08-31  0:23     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-31  0:23 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> Reserve CDM blocks for writeback if the format of the output fb
> is YUV. At the moment, the reservation is done only for writeback
> but can easily be extended by relaxing the checks once other
> interfaces are ready to output YUV.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 35 ++++++++++++++++++++-
>  1 file changed, 34 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 1b1e07292a9e..7a3d179bdfba 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -16,6 +16,7 @@
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_file.h>
>  #include <drm/drm_probe_helper.h>
> +#include <drm/drm_framebuffer.h>
>
>  #include "msm_drv.h"
>  #include "dpu_kms.h"
> @@ -615,9 +616,11 @@ static int dpu_encoder_virt_atomic_check(
>         struct drm_display_mode *adj_mode;
>         struct msm_display_topology topology;
>         struct dpu_global_state *global_state;
> +       struct drm_framebuffer *fb;
>         struct drm_dsc_config *dsc;
>         int i = 0;
>         int ret = 0;
> +       bool needs_cdm = false;
>
>         if (!drm_enc || !crtc_state || !conn_state) {
>                 DPU_ERROR("invalid arg(s), drm_enc %d, crtc/conn state %d/%d\n",
> @@ -655,6 +658,22 @@ 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()
> +        * earlier.
> +        */
> +       if (dpu_enc->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))))
> +                       needs_cdm = true;
> +               if (needs_cdm && !dpu_enc->cur_master->hw_cdm)
> +                       crtc_state->mode_changed = true;
> +               else if (!needs_cdm && dpu_enc->cur_master->hw_cdm)
> +                       crtc_state->mode_changed = true;
> +       }

What would be the (estimated) check for DP?

> +
>         /*
>          * Release and Allocate resources on every modeset
>          * Dont allocate when active is false.
> @@ -664,7 +683,7 @@ static int dpu_encoder_virt_atomic_check(
>
>                 if (!crtc_state->active_changed || crtc_state->enable)
>                         ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
> -                                       drm_enc, crtc_state, topology, false);
> +                                       drm_enc, crtc_state, topology, needs_cdm);
>         }
>
>         trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
> @@ -1126,6 +1145,20 @@ 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) {
> +               struct dpu_hw_blk *hw_cdm = NULL;
> +               struct drm_framebuffer *fb;
> +
> +               fb = conn_state->writeback_job->fb;
> +
> +               if (fb && DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(fb)))) {

You can drop all fb-related conditions here. If we have CDM, we know
that we asked for it. If we do not, it's because we do not need it.

> +                       dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> +                                                     drm_enc->base.id, DPU_HW_BLK_CDM,
> +                                                     &hw_cdm, 1);
> +               }
> +               dpu_enc->cur_master->hw_cdm = hw_cdm ? to_dpu_hw_cdm(hw_cdm) : NULL;
> +       }
> +
>         cstate = to_dpu_crtc_state(crtc_state);
>
>         for (i = 0; i < num_lm; i++) {
> --
> 2.40.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH 13/16] drm/msm/dpu: reserve cdm blocks for writeback in case of YUV output
@ 2023-08-31  0:23     ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-31  0:23 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> Reserve CDM blocks for writeback if the format of the output fb
> is YUV. At the moment, the reservation is done only for writeback
> but can easily be extended by relaxing the checks once other
> interfaces are ready to output YUV.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 35 ++++++++++++++++++++-
>  1 file changed, 34 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 1b1e07292a9e..7a3d179bdfba 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -16,6 +16,7 @@
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_file.h>
>  #include <drm/drm_probe_helper.h>
> +#include <drm/drm_framebuffer.h>
>
>  #include "msm_drv.h"
>  #include "dpu_kms.h"
> @@ -615,9 +616,11 @@ static int dpu_encoder_virt_atomic_check(
>         struct drm_display_mode *adj_mode;
>         struct msm_display_topology topology;
>         struct dpu_global_state *global_state;
> +       struct drm_framebuffer *fb;
>         struct drm_dsc_config *dsc;
>         int i = 0;
>         int ret = 0;
> +       bool needs_cdm = false;
>
>         if (!drm_enc || !crtc_state || !conn_state) {
>                 DPU_ERROR("invalid arg(s), drm_enc %d, crtc/conn state %d/%d\n",
> @@ -655,6 +658,22 @@ 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()
> +        * earlier.
> +        */
> +       if (dpu_enc->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))))
> +                       needs_cdm = true;
> +               if (needs_cdm && !dpu_enc->cur_master->hw_cdm)
> +                       crtc_state->mode_changed = true;
> +               else if (!needs_cdm && dpu_enc->cur_master->hw_cdm)
> +                       crtc_state->mode_changed = true;
> +       }

What would be the (estimated) check for DP?

> +
>         /*
>          * Release and Allocate resources on every modeset
>          * Dont allocate when active is false.
> @@ -664,7 +683,7 @@ static int dpu_encoder_virt_atomic_check(
>
>                 if (!crtc_state->active_changed || crtc_state->enable)
>                         ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
> -                                       drm_enc, crtc_state, topology, false);
> +                                       drm_enc, crtc_state, topology, needs_cdm);
>         }
>
>         trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
> @@ -1126,6 +1145,20 @@ 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) {
> +               struct dpu_hw_blk *hw_cdm = NULL;
> +               struct drm_framebuffer *fb;
> +
> +               fb = conn_state->writeback_job->fb;
> +
> +               if (fb && DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(fb)))) {

You can drop all fb-related conditions here. If we have CDM, we know
that we asked for it. If we do not, it's because we do not need it.

> +                       dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> +                                                     drm_enc->base.id, DPU_HW_BLK_CDM,
> +                                                     &hw_cdm, 1);
> +               }
> +               dpu_enc->cur_master->hw_cdm = hw_cdm ? to_dpu_hw_cdm(hw_cdm) : NULL;
> +       }
> +
>         cstate = to_dpu_crtc_state(crtc_state);
>
>         for (i = 0; i < num_lm; i++) {
> --
> 2.40.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH 14/16] drm/msm/dpu: do not allow YUV formats if no CDM block is present
  2023-08-30 22:49   ` Abhinav Kumar
@ 2023-08-31  0:24     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-31  0:24 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> On chipsets where CDM block is not available OR where support has
> not been added yet do not allow YUV formats for writeback block.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> 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 7fc174b33ae2..d8edca9bc964 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
> @@ -406,6 +406,12 @@ static int dpu_encoder_phys_wb_atomic_check(
>                 return ret;
>         }
>
> +       if (DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(fb))) &&
> +           !phys_enc->dpu_kms->catalog->cdm) {
> +               DPU_ERROR("cannot support YUV formats without CDM block\n");
> +               return -EINVAL;
> +       }

Can we have YUV formats in wb_formats if we do not support CDM? That
would be an error.

> +
>         return 0;
>  }
>
> --
> 2.40.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH 14/16] drm/msm/dpu: do not allow YUV formats if no CDM block is present
@ 2023-08-31  0:24     ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-31  0:24 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> On chipsets where CDM block is not available OR where support has
> not been added yet do not allow YUV formats for writeback block.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> 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 7fc174b33ae2..d8edca9bc964 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
> @@ -406,6 +406,12 @@ static int dpu_encoder_phys_wb_atomic_check(
>                 return ret;
>         }
>
> +       if (DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(fb))) &&
> +           !phys_enc->dpu_kms->catalog->cdm) {
> +               DPU_ERROR("cannot support YUV formats without CDM block\n");
> +               return -EINVAL;
> +       }

Can we have YUV formats in wb_formats if we do not support CDM? That
would be an error.

> +
>         return 0;
>  }
>
> --
> 2.40.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH 15/16] drm/msm/dpu: add NV12 in the list of supported WB formats
  2023-08-30 22:49   ` Abhinav Kumar
@ 2023-08-31  0:26     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-31  0:26 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> Since CDM block support has now been added for writeback blocks
> add NV12 in the list of supported WB formats.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
> index 713dfc079718..978330c6678e 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
> @@ -244,6 +244,7 @@ static const uint32_t wb2_formats[] = {
>         DRM_FORMAT_BGRA4444,
>         DRM_FORMAT_BGRX4444,
>         DRM_FORMAT_XBGR4444,
> +       DRM_FORMAT_NV12,
>  };

No. This way the driver would announce availability of NV12 even on
chipsets where NV12 is not supported for the writeback. Please define
separate formats array.

BTW: does HW only support NV12 for the writeback? What about YV12 or e.g. NV21?

>
>  /*************************************************************
> --
> 2.40.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH 15/16] drm/msm/dpu: add NV12 in the list of supported WB formats
@ 2023-08-31  0:26     ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-31  0:26 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> Since CDM block support has now been added for writeback blocks
> add NV12 in the list of supported WB formats.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
> index 713dfc079718..978330c6678e 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
> @@ -244,6 +244,7 @@ static const uint32_t wb2_formats[] = {
>         DRM_FORMAT_BGRA4444,
>         DRM_FORMAT_BGRX4444,
>         DRM_FORMAT_XBGR4444,
> +       DRM_FORMAT_NV12,
>  };

No. This way the driver would announce availability of NV12 even on
chipsets where NV12 is not supported for the writeback. Please define
separate formats array.

BTW: does HW only support NV12 for the writeback? What about YV12 or e.g. NV21?

>
>  /*************************************************************
> --
> 2.40.1
>


-- 
With best wishes
Dmitry

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

* Re: [PATCH 16/16] drm/msm/dpu: add cdm blocks to dpu snapshot
  2023-08-30 22:49   ` Abhinav Kumar
@ 2023-08-31  0:27     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-31  0:27 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> Now that CDM block support has been added to DPU lets also add its
> entry to the DPU snapshot to help debugging.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>

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

> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 4 ++++
>  1 file changed, 4 insertions(+)


-- 
With best wishes
Dmitry

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

* Re: [PATCH 16/16] drm/msm/dpu: add cdm blocks to dpu snapshot
@ 2023-08-31  0:27     ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-08-31  0:27 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
> Now that CDM block support has been added to DPU lets also add its
> entry to the DPU snapshot to help debugging.
>
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>

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

> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 4 ++++
>  1 file changed, 4 insertions(+)


-- 
With best wishes
Dmitry

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

* Re: [PATCH 04/16] drm/msm/dpu: add cdm blocks to sc7280 dpu_hw_catalog
  2023-08-30 22:57     ` Dmitry Baryshkov
@ 2023-11-30 22:41       ` Abhinav Kumar
  -1 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-11-30 22:41 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul



On 8/30/2023 3:57 PM, Dmitry Baryshkov wrote:
> On Thu, 31 Aug 2023 at 01:49, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> Add CDM blocks to the sc7280 dpu_hw_catalog to support
>> YUV format output from writeback block.
>>
>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>> ---
>>   .../gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h  |  9 +++++++++
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h      | 13 +++++++++++++
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h         |  5 +++++
>>   3 files changed, 27 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
>> index 3b5061c4402a..5252170f216d 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
>> @@ -251,10 +251,19 @@ static const struct dpu_mdss_version sc7280_mdss_ver = {
>>          .core_minor_ver = 2,
>>   };
>>
>> +static const struct dpu_cdm_cfg sc7280_cdm = {
>> +       .name = "cdm_0",
>> +       .id = CDM_0,
>> +       .len = 0x228,
>> +       .base = 0x79200,
>> +       .features = 0,
> 
> No need to.
> Also, as the CDM block seems to be common to all existing platforms,
> what about moving this definition to dpu_hw_catalog.c next to VBIF
> settings?
> 

Thanks for the feedback and sorry for the delay in getting back to this 
feature.

Ack. Yes lets move it to dpu_hw_catalog.c and remove explicit 0 
assignment for features.

>> +};
>> +
>>   const struct dpu_mdss_cfg dpu_sc7280_cfg = {
>>          .mdss_ver = &sc7280_mdss_ver,
>>          .caps = &sc7280_dpu_caps,
>>          .mdp = &sc7280_mdp,
>> +       .cdm = &sc7280_cdm,
>>          .ctl_count = ARRAY_SIZE(sc7280_ctl),
>>          .ctl = sc7280_ctl,
>>          .sspp_count = ARRAY_SIZE(sc7280_sspp),
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>> index 6c9634209e9f..4ea7c3f85a95 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>> @@ -693,6 +693,17 @@ struct dpu_vbif_cfg {
>>          u32 memtype[MAX_XIN_COUNT];
>>   };
>>
>> +/**
>> + * struct dpu_cdm_cfg - information of chroma down blocks
>> + * @name               string name for debug purposes
>> + * @id                 enum identifying this block
>> + * @base               register offset of this block
>> + * @features           bit mask identifying sub-blocks/features
>> + */
>> +struct dpu_cdm_cfg {
>> +       DPU_HW_BLK_INFO;
>> +};
>> +
>>   /**
>>    * Define CDP use cases
>>    * @DPU_PERF_CDP_UDAGE_RT: real-time use cases
>> @@ -816,6 +827,8 @@ struct dpu_mdss_cfg {
>>          u32 wb_count;
>>          const struct dpu_wb_cfg *wb;
>>
>> +       const struct dpu_cdm_cfg *cdm;
>> +
>>          u32 ad_count;
>>
>>          u32 dspp_count;
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> index d85157acfbf8..4d6dba18caf0 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> @@ -185,6 +185,11 @@ enum dpu_dsc {
>>          DSC_MAX
>>   };
>>
>> +enum dpu_cdm {
>> +       CDM_0 = 1,
>> +       CDM_MAX
>> +};
>> +
>>   enum dpu_pingpong {
>>          PINGPONG_NONE,
>>          PINGPONG_0,
>> --
>> 2.40.1
>>
> 
> 

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

* Re: [PATCH 04/16] drm/msm/dpu: add cdm blocks to sc7280 dpu_hw_catalog
@ 2023-11-30 22:41       ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-11-30 22:41 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Sean Paul, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, Marijn Suijten, quic_jesszhan, freedreno



On 8/30/2023 3:57 PM, Dmitry Baryshkov wrote:
> On Thu, 31 Aug 2023 at 01:49, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> Add CDM blocks to the sc7280 dpu_hw_catalog to support
>> YUV format output from writeback block.
>>
>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>> ---
>>   .../gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h  |  9 +++++++++
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h      | 13 +++++++++++++
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h         |  5 +++++
>>   3 files changed, 27 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
>> index 3b5061c4402a..5252170f216d 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
>> @@ -251,10 +251,19 @@ static const struct dpu_mdss_version sc7280_mdss_ver = {
>>          .core_minor_ver = 2,
>>   };
>>
>> +static const struct dpu_cdm_cfg sc7280_cdm = {
>> +       .name = "cdm_0",
>> +       .id = CDM_0,
>> +       .len = 0x228,
>> +       .base = 0x79200,
>> +       .features = 0,
> 
> No need to.
> Also, as the CDM block seems to be common to all existing platforms,
> what about moving this definition to dpu_hw_catalog.c next to VBIF
> settings?
> 

Thanks for the feedback and sorry for the delay in getting back to this 
feature.

Ack. Yes lets move it to dpu_hw_catalog.c and remove explicit 0 
assignment for features.

>> +};
>> +
>>   const struct dpu_mdss_cfg dpu_sc7280_cfg = {
>>          .mdss_ver = &sc7280_mdss_ver,
>>          .caps = &sc7280_dpu_caps,
>>          .mdp = &sc7280_mdp,
>> +       .cdm = &sc7280_cdm,
>>          .ctl_count = ARRAY_SIZE(sc7280_ctl),
>>          .ctl = sc7280_ctl,
>>          .sspp_count = ARRAY_SIZE(sc7280_sspp),
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>> index 6c9634209e9f..4ea7c3f85a95 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
>> @@ -693,6 +693,17 @@ struct dpu_vbif_cfg {
>>          u32 memtype[MAX_XIN_COUNT];
>>   };
>>
>> +/**
>> + * struct dpu_cdm_cfg - information of chroma down blocks
>> + * @name               string name for debug purposes
>> + * @id                 enum identifying this block
>> + * @base               register offset of this block
>> + * @features           bit mask identifying sub-blocks/features
>> + */
>> +struct dpu_cdm_cfg {
>> +       DPU_HW_BLK_INFO;
>> +};
>> +
>>   /**
>>    * Define CDP use cases
>>    * @DPU_PERF_CDP_UDAGE_RT: real-time use cases
>> @@ -816,6 +827,8 @@ struct dpu_mdss_cfg {
>>          u32 wb_count;
>>          const struct dpu_wb_cfg *wb;
>>
>> +       const struct dpu_cdm_cfg *cdm;
>> +
>>          u32 ad_count;
>>
>>          u32 dspp_count;
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> index d85157acfbf8..4d6dba18caf0 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> @@ -185,6 +185,11 @@ enum dpu_dsc {
>>          DSC_MAX
>>   };
>>
>> +enum dpu_cdm {
>> +       CDM_0 = 1,
>> +       CDM_MAX
>> +};
>> +
>>   enum dpu_pingpong {
>>          PINGPONG_NONE,
>>          PINGPONG_0,
>> --
>> 2.40.1
>>
> 
> 

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

* Re: [PATCH 06/16] drm/msm/dpu: add dpu_hw_cdm abstraction for CDM block
  2023-08-31  0:00     ` Dmitry Baryshkov
@ 2023-11-30 23:36       ` Abhinav Kumar
  -1 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-11-30 23:36 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-kernel, linux-arm-msm



On 8/30/2023 5:00 PM, Dmitry Baryshkov wrote:
> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> CDM block comes with its own set of registers and operations
>> which can be done. In-line with other hardware sub-blocks, this
>> change adds the dpu_hw_cdm abstraction for the CDM block.
>>
>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/Makefile                |   1 +
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c  | 272 ++++++++++++++++++++
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h  | 135 ++++++++++
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h |   1 +
>>   4 files changed, 409 insertions(+)
>>   create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
>>   create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
>>
>> diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
>> index 8d02d8c33069..2010cb1ca995 100644
>> --- a/drivers/gpu/drm/msm/Makefile
>> +++ b/drivers/gpu/drm/msm/Makefile
>> @@ -63,6 +63,7 @@ msm-$(CONFIG_DRM_MSM_DPU) += \
>>          disp/dpu1/dpu_encoder_phys_wb.o \
>>          disp/dpu1/dpu_formats.o \
>>          disp/dpu1/dpu_hw_catalog.o \
>> +       disp/dpu1/dpu_hw_cdm.o \
>>          disp/dpu1/dpu_hw_ctl.o \
>>          disp/dpu1/dpu_hw_dsc.o \
>>          disp/dpu1/dpu_hw_dsc_1_2.o \
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
>> new file mode 100644
>> index 000000000000..a2f7ee8f54e4
>> --- /dev/null
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
>> @@ -0,0 +1,272 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (c) 2023, The Linux Foundation. All rights reserved.
>> + */
>> +
>> +#include <drm/drm_managed.h>
>> +
>> +#include "dpu_hw_mdss.h"
>> +#include "dpu_hw_util.h"
>> +#include "dpu_hw_catalog.h"
>> +#include "dpu_hw_cdm.h"
>> +#include "dpu_kms.h"
>> +
>> +#define CDM_CSC_10_OPMODE                  0x000
>> +#define CDM_CSC_10_BASE                    0x004
>> +
>> +#define CDM_CDWN2_OP_MODE                  0x100
>> +#define CDM_CDWN2_CLAMP_OUT                0x104
>> +#define CDM_CDWN2_PARAMS_3D_0              0x108
>> +#define CDM_CDWN2_PARAMS_3D_1              0x10C
>> +#define CDM_CDWN2_COEFF_COSITE_H_0         0x110
>> +#define CDM_CDWN2_COEFF_COSITE_H_1         0x114
>> +#define CDM_CDWN2_COEFF_COSITE_H_2         0x118
>> +#define CDM_CDWN2_COEFF_OFFSITE_H_0        0x11C
>> +#define CDM_CDWN2_COEFF_OFFSITE_H_1        0x120
>> +#define CDM_CDWN2_COEFF_OFFSITE_H_2        0x124
>> +#define CDM_CDWN2_COEFF_COSITE_V           0x128
>> +#define CDM_CDWN2_COEFF_OFFSITE_V          0x12C
>> +#define CDM_CDWN2_OUT_SIZE                 0x130
>> +
>> +#define CDM_HDMI_PACK_OP_MODE              0x200
>> +#define CDM_CSC_10_MATRIX_COEFF_0          0x004
>> +
>> +#define CDM_MUX                            0x224
>> +
>> +/**
>> + * Horizontal coefficients for cosite chroma downscale
>> + * s13 representation of coefficients
>> + */
>> +static u32 cosite_h_coeff[] = {0x00000016, 0x000001cc, 0x0100009e};
>> +
>> +/**
>> + * Horizontal coefficients for offsite chroma downscale
>> + */
>> +static u32 offsite_h_coeff[] = {0x000b0005, 0x01db01eb, 0x00e40046};
>> +
>> +/**
>> + * Vertical coefficients for cosite chroma downscale
>> + */
>> +static u32 cosite_v_coeff[] = {0x00080004};
>> +/**
>> + * Vertical coefficients for offsite chroma downscale
>> + */
>> +static u32 offsite_v_coeff[] = {0x00060002};
>> +
>> +static int dpu_hw_cdm_setup_csc_10bit(struct dpu_hw_cdm *ctx, struct dpu_csc_cfg *data)
>> +{
>> +       dpu_hw_csc_setup(&ctx->hw, CDM_CSC_10_MATRIX_COEFF_0, data, true);
> 
> Where was this defined?
> 

Its in this file itself

+#define CDM_CSC_10_MATRIX_COEFF_0          0x004

>> +
>> +       return 0;
>> +}
>> +
>> +static int dpu_hw_cdm_setup_cdwn(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cfg)
>> +{
>> +       struct dpu_hw_blk_reg_map *c = &ctx->hw;
>> +       u32 opmode = 0;
>> +       u32 out_size = 0;
>> +
>> +       if (cfg->output_bit_depth == CDM_CDWN_OUTPUT_10BIT)
>> +               opmode &= ~BIT(7);
>> +       else
>> +               opmode |= BIT(7);
>> +
>> +       /* ENABLE DWNS_H bit */
>> +       opmode |= BIT(1);
>> +
>> +       switch (cfg->h_cdwn_type) {
>> +       case CDM_CDWN_DISABLE:
>> +               /* CLEAR METHOD_H field */
>> +               opmode &= ~(0x18);
>> +               /* CLEAR DWNS_H bit */
>> +               opmode &= ~BIT(1);
>> +               break;
>> +       case CDM_CDWN_PIXEL_DROP:
>> +               /* Clear METHOD_H field (pixel drop is 0) */
>> +               opmode &= ~(0x18);
>> +               break;
>> +       case CDM_CDWN_AVG:
>> +               /* Clear METHOD_H field (Average is 0x1) */
>> +               opmode &= ~(0x18);
>> +               opmode |= (0x1 << 0x3);
>> +               break;
>> +       case CDM_CDWN_COSITE:
>> +               /* Clear METHOD_H field (Average is 0x2) */
>> +               opmode &= ~(0x18);
>> +               opmode |= (0x2 << 0x3);
>> +               /* Co-site horizontal coefficients */
>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_0,
>> +                               cosite_h_coeff[0]);
>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_1,
>> +                               cosite_h_coeff[1]);
>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_2,
>> +                               cosite_h_coeff[2]);
>> +               break;
>> +       case CDM_CDWN_OFFSITE:
>> +               /* Clear METHOD_H field (Average is 0x3) */
>> +               opmode &= ~(0x18);
>> +               opmode |= (0x3 << 0x3);
>> +
>> +               /* Off-site horizontal coefficients */
>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_0,
>> +                               offsite_h_coeff[0]);
>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_1,
>> +                               offsite_h_coeff[1]);
>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_2,
>> +                               offsite_h_coeff[2]);
>> +               break;
>> +       default:
>> +               pr_err("%s invalid horz down sampling type\n", __func__);
>> +               return -EINVAL;
>> +       }
>> +
>> +       /* ENABLE DWNS_V bit */
>> +       opmode |= BIT(2);
>> +
>> +       switch (cfg->v_cdwn_type) {
>> +       case CDM_CDWN_DISABLE:
>> +               /* CLEAR METHOD_V field */
>> +               opmode &= ~(0x60);
> 
> #define, GENMASK
> 
>> +               /* CLEAR DWNS_V bit */
>> +               opmode &= ~BIT(2);
>> +               break;
>> +       case CDM_CDWN_PIXEL_DROP:
>> +               /* Clear METHOD_V field (pixel drop is 0) */
>> +               opmode &= ~(0x60);
>> +               break;
>> +       case CDM_CDWN_AVG:
>> +               /* Clear METHOD_V field (Average is 0x1) */
>> +               opmode &= ~(0x60);
>> +               opmode |= (0x1 << 0x5);
> 
> #define
> 
>> +               break;
>> +       case CDM_CDWN_COSITE:
>> +               /* Clear METHOD_V field (Average is 0x2) */
>> +               opmode &= ~(0x60);
>> +               opmode |= (0x2 << 0x5);
>> +               /* Co-site vertical coefficients */
>> +               DPU_REG_WRITE(c,
>> +                               CDM_CDWN2_COEFF_COSITE_V,
>> +                               cosite_v_coeff[0]);
> 
> align to opening bracket
> 
>> +               break;
>> +       case CDM_CDWN_OFFSITE:
>> +               /* Clear METHOD_V field (Average is 0x3) */
>> +               opmode &= ~(0x60);
>> +               opmode |= (0x3 << 0x5);
>> +
>> +               /* Off-site vertical coefficients */
>> +               DPU_REG_WRITE(c,
>> +                               CDM_CDWN2_COEFF_OFFSITE_V,
>> +                               offsite_v_coeff[0]);
> 
> align to opening bracket
> 
>> +               break;
>> +       default:
>> +               return -EINVAL;
>> +       }
>> +
>> +       if (cfg->v_cdwn_type || cfg->h_cdwn_type)
>> +               opmode |= BIT(0); /* EN CDWN module */
> 
> #define
> 

Ack to all comments about GENMASK and #define

>> +       else
>> +               opmode &= ~BIT(0);
>> +
>> +       out_size = (cfg->output_width & 0xFFFF) |
>> +               ((cfg->output_height & 0xFFFF) << 16);
>> +       DPU_REG_WRITE(c, CDM_CDWN2_OUT_SIZE, out_size);
>> +       DPU_REG_WRITE(c, CDM_CDWN2_OP_MODE, opmode);
>> +       DPU_REG_WRITE(c, CDM_CDWN2_CLAMP_OUT,
>> +                       ((0x3FF << 16) | 0x0));
>> +
>> +       return 0;
>> +}
>> +
>> +int dpu_hw_cdm_enable(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cdm)
>> +{
>> +       struct dpu_hw_blk_reg_map *c = &ctx->hw;
>> +       const struct dpu_format *fmt;
>> +       u32 opmode = 0;
>> +       u32 csc = 0;
>> +
>> +       if (!ctx || !cdm)
>> +               return -EINVAL;
>> +
>> +       fmt = cdm->output_fmt;
>> +
>> +       if (!DPU_FORMAT_IS_YUV(fmt))
>> +               return -EINVAL;
>> +
>> +       if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
>> +               if (fmt->chroma_sample != DPU_CHROMA_H1V2)
>> +                       return -EINVAL; /*unsupported format */
>> +               opmode = BIT(0);
>> +               opmode |= (fmt->chroma_sample << 1);
>> +       }
>> +
>> +       csc |= BIT(2);
>> +       csc &= ~BIT(1);
>> +       csc |= BIT(0);
> 
> Can we get some sensible #defines for all this magic, please?
> 

Ack, will do.

>> +
>> +       if (ctx && ctx->ops.bind_pingpong_blk)
>> +               ctx->ops.bind_pingpong_blk(ctx, true,
>> +                               cdm->pp_id);
>> +
>> +       DPU_REG_WRITE(c, CDM_CSC_10_OPMODE, csc);
>> +       DPU_REG_WRITE(c, CDM_HDMI_PACK_OP_MODE, opmode);
>> +       return 0;
>> +}
>> +
>> +void dpu_hw_cdm_disable(struct dpu_hw_cdm *ctx)
>> +{
>> +       if (!ctx)
>> +               return;
>> +
>> +       if (ctx && ctx->ops.bind_pingpong_blk)
>> +               ctx->ops.bind_pingpong_blk(ctx, false, 0);
> 
> PINGPONG_NONE.
> 
>> +}
>> +
>> +static void dpu_hw_cdm_bind_pingpong_blk(struct dpu_hw_cdm *ctx, bool enable,
>> +                                        const enum dpu_pingpong pp)
>> +{
>> +       struct dpu_hw_blk_reg_map *c;
>> +       int mux_cfg = 0xF;
>> +
>> +       if (!ctx || (enable && (pp < PINGPONG_0 || pp >= PINGPONG_MAX)))
>> +               return;
> 
> I'd say, this is useless. We don't have such checks in other
> bind_pingpong_blk() callbacks.
> 
> Also there should be a guarding check for DPU >= 5.0 either here or at
> the ops init.
> 

Will add it at ops init

>> +
>> +       c = &ctx->hw;
>> +
>> +       if (enable)
>> +               mux_cfg = (pp - PINGPONG_0) & 0x7;
>> +
>> +       DPU_REG_WRITE(c, CDM_MUX, mux_cfg);
>> +}
>> +
>> +static void _setup_cdm_ops(struct dpu_hw_cdm_ops *ops, unsigned long features)
> 
> Please inline
> 

OK

>> +{
>> +       ops->setup_csc_data = dpu_hw_cdm_setup_csc_10bit;
>> +       ops->setup_cdwn = dpu_hw_cdm_setup_cdwn;
>> +       ops->enable = dpu_hw_cdm_enable;
>> +       ops->disable = dpu_hw_cdm_disable;
>> +       ops->bind_pingpong_blk = dpu_hw_cdm_bind_pingpong_blk;
> 
> As you seem to call this function directly, we might as well drop the
> callback from the ops.
> 

There are two paths for the bind_pingpong_blk(). One is absorbed within 
cdm_enable and cdm_disable calls to bind and unbind the pingpong resp. 
And yes, for that we dont need a separate ops as its within the same file.

This will handle cases where we transition from YUV to non-YUV cases and 
vice-versa without an encoder disable in between which I believe happens 
in the IGT cases.

But the dpu_encoder_helper_phys_cleanup() path is only in the encoder 
disable() path without a non-YUV frame in the middle so lets say we were 
in YUV mode but then just disabled the encoder we do need the cleanup 
there and since thats outside of the dpu_hw_cdm, we do need this op.

I agree we need to protect this with the DPU revision check.

>> +}
>> +
>> +struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cfg, void __iomem *addr)
>> +{
>> +       struct dpu_hw_cdm *c;
>> +
>> +       c = kzalloc(sizeof(*c), GFP_KERNEL);
>> +       if (!c)
>> +               return ERR_PTR(-ENOMEM);
>> +
>> +       c->hw.blk_addr = addr + cfg->base;
>> +       c->hw.log_mask = DPU_DBG_MASK_CDM;
>> +
>> +       /* Assign ops */
>> +       c->idx = cfg->id;
>> +       c->caps = cfg;
>> +       _setup_cdm_ops(&c->ops, c->caps->features);
>> +
>> +       return c;
>> +}
>> +
>> +void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm)
>> +{
>> +       kfree(cdm);
> 
> I'd prefer not to introduce another manual kzalloc/kfree pair, see
> https://patchwork.freedesktop.org/series/120366/
> 

I recall I did not want to have a manual kzalloc/kfree pair. But the 
issue was I think this series was not merged that time (and is isnt 
merged now either) and this is the one which passes drm_dev to 
dpu_rm_init. I thought maybe it was easier for you to absorb this change 
into that series instead of me pulling that whole series to make this 
one compile as we will not be adding new HW blocks after this for the 
next 2 cycles. It will only be using existing ones.

If its too much trouble for you, I will rebase on top of that series but 
I am pretty sure you will have to rebase and post that again anyway on 
top of the current msm-next.

I am also going to do the same thing now with this series.

So we can just decide that in whose rebase we will handle it.

>> +}
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
>> new file mode 100644
>> index 000000000000..da60893a5c02
>> --- /dev/null
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
>> @@ -0,0 +1,135 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/*
>> + * Copyright (c) 2023, The Linux Foundation. All rights reserved.
>> + */
>> +
>> +#ifndef _DPU_HW_CDM_H
>> +#define _DPU_HW_CDM_H
>> +
>> +#include "dpu_hw_mdss.h"
>> +#include "dpu_hw_top.h"
>> +
>> +struct dpu_hw_cdm;
>> +
>> +struct dpu_hw_cdm_cfg {
>> +       u32 output_width;
>> +       u32 output_height;
>> +       u32 output_bit_depth;
>> +       u32 h_cdwn_type;
>> +       u32 v_cdwn_type;
>> +       const struct dpu_format *output_fmt;
>> +       u32 output_type;
>> +       int pp_id;
>> +};
>> +
>> +enum dpu_hw_cdwn_type {
>> +       CDM_CDWN_DISABLE,
>> +       CDM_CDWN_PIXEL_DROP,
>> +       CDM_CDWN_AVG,
>> +       CDM_CDWN_COSITE,
>> +       CDM_CDWN_OFFSITE,
>> +};
>> +
>> +enum dpu_hw_cdwn_output_type {
>> +       CDM_CDWN_OUTPUT_HDMI,
>> +       CDM_CDWN_OUTPUT_WB,
>> +};
>> +
>> +enum dpu_hw_cdwn_output_bit_depth {
>> +       CDM_CDWN_OUTPUT_8BIT,
>> +       CDM_CDWN_OUTPUT_10BIT,
>> +};
>> +
>> +/**
>> + * struct dpu_hw_cdm_ops : Interface to the chroma down Hw driver functions
>> + *                         Assumption is these functions will be called after
>> + *                         clocks are enabled
>> + *  @setup_csc:            Programs the csc matrix
>> + *  @setup_cdwn:           Sets up the chroma down sub module
>> + *  @enable:               Enables the output to interface and programs the
>> + *                         output packer
>> + *  @disable:              Puts the cdm in bypass mode
>> + *  @bind_pingpong_blk:    enable/disable the connection with pingpong which
>> + *                         will feed pixels to this cdm
>> + */
>> +struct dpu_hw_cdm_ops {
>> +       /**
>> +        * Programs the CSC matrix for conversion from RGB space to YUV space,
>> +        * it is optional to call this function as this matrix is automatically
>> +        * set during initialization, user should call this if it wants
>> +        * to program a different matrix than default matrix.
>> +        * @cdm:          Pointer to the chroma down context structure
>> +        * @data          Pointer to CSC configuration data
>> +        * return:        0 if success; error code otherwise
>> +        */
>> +       int (*setup_csc_data)(struct dpu_hw_cdm *cdm, struct dpu_csc_cfg *data);
>> +
>> +       /**
>> +        * Programs the Chroma downsample part.
>> +        * @cdm         Pointer to chroma down context
>> +        * @cfg         Pointer to the cdm configuration data
>> +        */
>> +       int (*setup_cdwn)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
>> +
>> +       /**
>> +        * Enable the CDM module
>> +        * @cdm         Pointer to chroma down context
>> +        */
>> +       int (*enable)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
>> +
>> +       /**
>> +        * Disable the CDM module
>> +        * @cdm         Pointer to chroma down context
>> +        */
>> +       void (*disable)(struct dpu_hw_cdm *cdm);
>> +
>> +       /**
>> +        * Enable/disable the connection with pingpong
>> +        * @cdm         Pointer to chroma down context
>> +        * @enable      Enable/disable control
>> +        * @pp          pingpong block id.
>> +        */
>> +       void (*bind_pingpong_blk)(struct dpu_hw_cdm *cdm, bool enable,
>> +                                 const enum dpu_pingpong pp);
>> +};
>> +
>> +/**
>> + * struct dpu_hw_cdm - cdm description
>> + * @base: Hardware block base structure
>> + * @hw: Block hardware details
>> + * @idx: CDM index
>> + * @caps: Pointer to cdm_cfg
>> + * @ops: handle to operations possible for this CDM
>> + */
>> +struct dpu_hw_cdm {
>> +       struct dpu_hw_blk base;
>> +       struct dpu_hw_blk_reg_map hw;
>> +
>> +       /* chroma down */
>> +       const struct dpu_cdm_cfg *caps;
>> +       enum  dpu_cdm  idx;
>> +
>> +       /* ops */
>> +       struct dpu_hw_cdm_ops ops;
>> +};
>> +
>> +/**
>> + * dpu_hw_cdm_init - initializes the cdm hw driver object.
>> + * should be called once before accessing every cdm.
>> + * @cdm: CDM catalog entry for which driver object is required
>> + * @addr :   mapped register io address of MDSS
>> + */
>> +struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cdm, void __iomem *addr);
>> +
>> +/**
>> + * dpu_hw_cdm_destroy - destroys cdm driver context
>> + * @cdm:   Pointer to cdm driver context returned by dpu_hw_cdm_init
>> + */
>> +void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm);
>> +
>> +static inline struct dpu_hw_cdm *to_dpu_hw_cdm(struct dpu_hw_blk *hw)
>> +{
>> +       return container_of(hw, struct dpu_hw_cdm, base);
>> +}
>> +
>> +#endif /*_DPU_HW_CDM_H */
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> index 4d6dba18caf0..34f943102499 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> @@ -463,6 +463,7 @@ struct dpu_mdss_color {
>>   #define DPU_DBG_MASK_ROT      (1 << 9)
>>   #define DPU_DBG_MASK_DSPP     (1 << 10)
>>   #define DPU_DBG_MASK_DSC      (1 << 11)
>> +#define DPU_DBG_MASK_CDM      (1 << 12)
>>
>>   /**
>>    * struct dpu_hw_tear_check - Struct contains parameters to configure
>> --
>> 2.40.1
>>
> 
> 
> --
> With best wishes
> Dmitry

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

* Re: [PATCH 06/16] drm/msm/dpu: add dpu_hw_cdm abstraction for CDM block
@ 2023-11-30 23:36       ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-11-30 23:36 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul



On 8/30/2023 5:00 PM, Dmitry Baryshkov wrote:
> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> CDM block comes with its own set of registers and operations
>> which can be done. In-line with other hardware sub-blocks, this
>> change adds the dpu_hw_cdm abstraction for the CDM block.
>>
>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/Makefile                |   1 +
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c  | 272 ++++++++++++++++++++
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h  | 135 ++++++++++
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h |   1 +
>>   4 files changed, 409 insertions(+)
>>   create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
>>   create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
>>
>> diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
>> index 8d02d8c33069..2010cb1ca995 100644
>> --- a/drivers/gpu/drm/msm/Makefile
>> +++ b/drivers/gpu/drm/msm/Makefile
>> @@ -63,6 +63,7 @@ msm-$(CONFIG_DRM_MSM_DPU) += \
>>          disp/dpu1/dpu_encoder_phys_wb.o \
>>          disp/dpu1/dpu_formats.o \
>>          disp/dpu1/dpu_hw_catalog.o \
>> +       disp/dpu1/dpu_hw_cdm.o \
>>          disp/dpu1/dpu_hw_ctl.o \
>>          disp/dpu1/dpu_hw_dsc.o \
>>          disp/dpu1/dpu_hw_dsc_1_2.o \
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
>> new file mode 100644
>> index 000000000000..a2f7ee8f54e4
>> --- /dev/null
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
>> @@ -0,0 +1,272 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (c) 2023, The Linux Foundation. All rights reserved.
>> + */
>> +
>> +#include <drm/drm_managed.h>
>> +
>> +#include "dpu_hw_mdss.h"
>> +#include "dpu_hw_util.h"
>> +#include "dpu_hw_catalog.h"
>> +#include "dpu_hw_cdm.h"
>> +#include "dpu_kms.h"
>> +
>> +#define CDM_CSC_10_OPMODE                  0x000
>> +#define CDM_CSC_10_BASE                    0x004
>> +
>> +#define CDM_CDWN2_OP_MODE                  0x100
>> +#define CDM_CDWN2_CLAMP_OUT                0x104
>> +#define CDM_CDWN2_PARAMS_3D_0              0x108
>> +#define CDM_CDWN2_PARAMS_3D_1              0x10C
>> +#define CDM_CDWN2_COEFF_COSITE_H_0         0x110
>> +#define CDM_CDWN2_COEFF_COSITE_H_1         0x114
>> +#define CDM_CDWN2_COEFF_COSITE_H_2         0x118
>> +#define CDM_CDWN2_COEFF_OFFSITE_H_0        0x11C
>> +#define CDM_CDWN2_COEFF_OFFSITE_H_1        0x120
>> +#define CDM_CDWN2_COEFF_OFFSITE_H_2        0x124
>> +#define CDM_CDWN2_COEFF_COSITE_V           0x128
>> +#define CDM_CDWN2_COEFF_OFFSITE_V          0x12C
>> +#define CDM_CDWN2_OUT_SIZE                 0x130
>> +
>> +#define CDM_HDMI_PACK_OP_MODE              0x200
>> +#define CDM_CSC_10_MATRIX_COEFF_0          0x004
>> +
>> +#define CDM_MUX                            0x224
>> +
>> +/**
>> + * Horizontal coefficients for cosite chroma downscale
>> + * s13 representation of coefficients
>> + */
>> +static u32 cosite_h_coeff[] = {0x00000016, 0x000001cc, 0x0100009e};
>> +
>> +/**
>> + * Horizontal coefficients for offsite chroma downscale
>> + */
>> +static u32 offsite_h_coeff[] = {0x000b0005, 0x01db01eb, 0x00e40046};
>> +
>> +/**
>> + * Vertical coefficients for cosite chroma downscale
>> + */
>> +static u32 cosite_v_coeff[] = {0x00080004};
>> +/**
>> + * Vertical coefficients for offsite chroma downscale
>> + */
>> +static u32 offsite_v_coeff[] = {0x00060002};
>> +
>> +static int dpu_hw_cdm_setup_csc_10bit(struct dpu_hw_cdm *ctx, struct dpu_csc_cfg *data)
>> +{
>> +       dpu_hw_csc_setup(&ctx->hw, CDM_CSC_10_MATRIX_COEFF_0, data, true);
> 
> Where was this defined?
> 

Its in this file itself

+#define CDM_CSC_10_MATRIX_COEFF_0          0x004

>> +
>> +       return 0;
>> +}
>> +
>> +static int dpu_hw_cdm_setup_cdwn(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cfg)
>> +{
>> +       struct dpu_hw_blk_reg_map *c = &ctx->hw;
>> +       u32 opmode = 0;
>> +       u32 out_size = 0;
>> +
>> +       if (cfg->output_bit_depth == CDM_CDWN_OUTPUT_10BIT)
>> +               opmode &= ~BIT(7);
>> +       else
>> +               opmode |= BIT(7);
>> +
>> +       /* ENABLE DWNS_H bit */
>> +       opmode |= BIT(1);
>> +
>> +       switch (cfg->h_cdwn_type) {
>> +       case CDM_CDWN_DISABLE:
>> +               /* CLEAR METHOD_H field */
>> +               opmode &= ~(0x18);
>> +               /* CLEAR DWNS_H bit */
>> +               opmode &= ~BIT(1);
>> +               break;
>> +       case CDM_CDWN_PIXEL_DROP:
>> +               /* Clear METHOD_H field (pixel drop is 0) */
>> +               opmode &= ~(0x18);
>> +               break;
>> +       case CDM_CDWN_AVG:
>> +               /* Clear METHOD_H field (Average is 0x1) */
>> +               opmode &= ~(0x18);
>> +               opmode |= (0x1 << 0x3);
>> +               break;
>> +       case CDM_CDWN_COSITE:
>> +               /* Clear METHOD_H field (Average is 0x2) */
>> +               opmode &= ~(0x18);
>> +               opmode |= (0x2 << 0x3);
>> +               /* Co-site horizontal coefficients */
>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_0,
>> +                               cosite_h_coeff[0]);
>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_1,
>> +                               cosite_h_coeff[1]);
>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_2,
>> +                               cosite_h_coeff[2]);
>> +               break;
>> +       case CDM_CDWN_OFFSITE:
>> +               /* Clear METHOD_H field (Average is 0x3) */
>> +               opmode &= ~(0x18);
>> +               opmode |= (0x3 << 0x3);
>> +
>> +               /* Off-site horizontal coefficients */
>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_0,
>> +                               offsite_h_coeff[0]);
>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_1,
>> +                               offsite_h_coeff[1]);
>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_2,
>> +                               offsite_h_coeff[2]);
>> +               break;
>> +       default:
>> +               pr_err("%s invalid horz down sampling type\n", __func__);
>> +               return -EINVAL;
>> +       }
>> +
>> +       /* ENABLE DWNS_V bit */
>> +       opmode |= BIT(2);
>> +
>> +       switch (cfg->v_cdwn_type) {
>> +       case CDM_CDWN_DISABLE:
>> +               /* CLEAR METHOD_V field */
>> +               opmode &= ~(0x60);
> 
> #define, GENMASK
> 
>> +               /* CLEAR DWNS_V bit */
>> +               opmode &= ~BIT(2);
>> +               break;
>> +       case CDM_CDWN_PIXEL_DROP:
>> +               /* Clear METHOD_V field (pixel drop is 0) */
>> +               opmode &= ~(0x60);
>> +               break;
>> +       case CDM_CDWN_AVG:
>> +               /* Clear METHOD_V field (Average is 0x1) */
>> +               opmode &= ~(0x60);
>> +               opmode |= (0x1 << 0x5);
> 
> #define
> 
>> +               break;
>> +       case CDM_CDWN_COSITE:
>> +               /* Clear METHOD_V field (Average is 0x2) */
>> +               opmode &= ~(0x60);
>> +               opmode |= (0x2 << 0x5);
>> +               /* Co-site vertical coefficients */
>> +               DPU_REG_WRITE(c,
>> +                               CDM_CDWN2_COEFF_COSITE_V,
>> +                               cosite_v_coeff[0]);
> 
> align to opening bracket
> 
>> +               break;
>> +       case CDM_CDWN_OFFSITE:
>> +               /* Clear METHOD_V field (Average is 0x3) */
>> +               opmode &= ~(0x60);
>> +               opmode |= (0x3 << 0x5);
>> +
>> +               /* Off-site vertical coefficients */
>> +               DPU_REG_WRITE(c,
>> +                               CDM_CDWN2_COEFF_OFFSITE_V,
>> +                               offsite_v_coeff[0]);
> 
> align to opening bracket
> 
>> +               break;
>> +       default:
>> +               return -EINVAL;
>> +       }
>> +
>> +       if (cfg->v_cdwn_type || cfg->h_cdwn_type)
>> +               opmode |= BIT(0); /* EN CDWN module */
> 
> #define
> 

Ack to all comments about GENMASK and #define

>> +       else
>> +               opmode &= ~BIT(0);
>> +
>> +       out_size = (cfg->output_width & 0xFFFF) |
>> +               ((cfg->output_height & 0xFFFF) << 16);
>> +       DPU_REG_WRITE(c, CDM_CDWN2_OUT_SIZE, out_size);
>> +       DPU_REG_WRITE(c, CDM_CDWN2_OP_MODE, opmode);
>> +       DPU_REG_WRITE(c, CDM_CDWN2_CLAMP_OUT,
>> +                       ((0x3FF << 16) | 0x0));
>> +
>> +       return 0;
>> +}
>> +
>> +int dpu_hw_cdm_enable(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cdm)
>> +{
>> +       struct dpu_hw_blk_reg_map *c = &ctx->hw;
>> +       const struct dpu_format *fmt;
>> +       u32 opmode = 0;
>> +       u32 csc = 0;
>> +
>> +       if (!ctx || !cdm)
>> +               return -EINVAL;
>> +
>> +       fmt = cdm->output_fmt;
>> +
>> +       if (!DPU_FORMAT_IS_YUV(fmt))
>> +               return -EINVAL;
>> +
>> +       if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
>> +               if (fmt->chroma_sample != DPU_CHROMA_H1V2)
>> +                       return -EINVAL; /*unsupported format */
>> +               opmode = BIT(0);
>> +               opmode |= (fmt->chroma_sample << 1);
>> +       }
>> +
>> +       csc |= BIT(2);
>> +       csc &= ~BIT(1);
>> +       csc |= BIT(0);
> 
> Can we get some sensible #defines for all this magic, please?
> 

Ack, will do.

>> +
>> +       if (ctx && ctx->ops.bind_pingpong_blk)
>> +               ctx->ops.bind_pingpong_blk(ctx, true,
>> +                               cdm->pp_id);
>> +
>> +       DPU_REG_WRITE(c, CDM_CSC_10_OPMODE, csc);
>> +       DPU_REG_WRITE(c, CDM_HDMI_PACK_OP_MODE, opmode);
>> +       return 0;
>> +}
>> +
>> +void dpu_hw_cdm_disable(struct dpu_hw_cdm *ctx)
>> +{
>> +       if (!ctx)
>> +               return;
>> +
>> +       if (ctx && ctx->ops.bind_pingpong_blk)
>> +               ctx->ops.bind_pingpong_blk(ctx, false, 0);
> 
> PINGPONG_NONE.
> 
>> +}
>> +
>> +static void dpu_hw_cdm_bind_pingpong_blk(struct dpu_hw_cdm *ctx, bool enable,
>> +                                        const enum dpu_pingpong pp)
>> +{
>> +       struct dpu_hw_blk_reg_map *c;
>> +       int mux_cfg = 0xF;
>> +
>> +       if (!ctx || (enable && (pp < PINGPONG_0 || pp >= PINGPONG_MAX)))
>> +               return;
> 
> I'd say, this is useless. We don't have such checks in other
> bind_pingpong_blk() callbacks.
> 
> Also there should be a guarding check for DPU >= 5.0 either here or at
> the ops init.
> 

Will add it at ops init

>> +
>> +       c = &ctx->hw;
>> +
>> +       if (enable)
>> +               mux_cfg = (pp - PINGPONG_0) & 0x7;
>> +
>> +       DPU_REG_WRITE(c, CDM_MUX, mux_cfg);
>> +}
>> +
>> +static void _setup_cdm_ops(struct dpu_hw_cdm_ops *ops, unsigned long features)
> 
> Please inline
> 

OK

>> +{
>> +       ops->setup_csc_data = dpu_hw_cdm_setup_csc_10bit;
>> +       ops->setup_cdwn = dpu_hw_cdm_setup_cdwn;
>> +       ops->enable = dpu_hw_cdm_enable;
>> +       ops->disable = dpu_hw_cdm_disable;
>> +       ops->bind_pingpong_blk = dpu_hw_cdm_bind_pingpong_blk;
> 
> As you seem to call this function directly, we might as well drop the
> callback from the ops.
> 

There are two paths for the bind_pingpong_blk(). One is absorbed within 
cdm_enable and cdm_disable calls to bind and unbind the pingpong resp. 
And yes, for that we dont need a separate ops as its within the same file.

This will handle cases where we transition from YUV to non-YUV cases and 
vice-versa without an encoder disable in between which I believe happens 
in the IGT cases.

But the dpu_encoder_helper_phys_cleanup() path is only in the encoder 
disable() path without a non-YUV frame in the middle so lets say we were 
in YUV mode but then just disabled the encoder we do need the cleanup 
there and since thats outside of the dpu_hw_cdm, we do need this op.

I agree we need to protect this with the DPU revision check.

>> +}
>> +
>> +struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cfg, void __iomem *addr)
>> +{
>> +       struct dpu_hw_cdm *c;
>> +
>> +       c = kzalloc(sizeof(*c), GFP_KERNEL);
>> +       if (!c)
>> +               return ERR_PTR(-ENOMEM);
>> +
>> +       c->hw.blk_addr = addr + cfg->base;
>> +       c->hw.log_mask = DPU_DBG_MASK_CDM;
>> +
>> +       /* Assign ops */
>> +       c->idx = cfg->id;
>> +       c->caps = cfg;
>> +       _setup_cdm_ops(&c->ops, c->caps->features);
>> +
>> +       return c;
>> +}
>> +
>> +void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm)
>> +{
>> +       kfree(cdm);
> 
> I'd prefer not to introduce another manual kzalloc/kfree pair, see
> https://patchwork.freedesktop.org/series/120366/
> 

I recall I did not want to have a manual kzalloc/kfree pair. But the 
issue was I think this series was not merged that time (and is isnt 
merged now either) and this is the one which passes drm_dev to 
dpu_rm_init. I thought maybe it was easier for you to absorb this change 
into that series instead of me pulling that whole series to make this 
one compile as we will not be adding new HW blocks after this for the 
next 2 cycles. It will only be using existing ones.

If its too much trouble for you, I will rebase on top of that series but 
I am pretty sure you will have to rebase and post that again anyway on 
top of the current msm-next.

I am also going to do the same thing now with this series.

So we can just decide that in whose rebase we will handle it.

>> +}
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
>> new file mode 100644
>> index 000000000000..da60893a5c02
>> --- /dev/null
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
>> @@ -0,0 +1,135 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/*
>> + * Copyright (c) 2023, The Linux Foundation. All rights reserved.
>> + */
>> +
>> +#ifndef _DPU_HW_CDM_H
>> +#define _DPU_HW_CDM_H
>> +
>> +#include "dpu_hw_mdss.h"
>> +#include "dpu_hw_top.h"
>> +
>> +struct dpu_hw_cdm;
>> +
>> +struct dpu_hw_cdm_cfg {
>> +       u32 output_width;
>> +       u32 output_height;
>> +       u32 output_bit_depth;
>> +       u32 h_cdwn_type;
>> +       u32 v_cdwn_type;
>> +       const struct dpu_format *output_fmt;
>> +       u32 output_type;
>> +       int pp_id;
>> +};
>> +
>> +enum dpu_hw_cdwn_type {
>> +       CDM_CDWN_DISABLE,
>> +       CDM_CDWN_PIXEL_DROP,
>> +       CDM_CDWN_AVG,
>> +       CDM_CDWN_COSITE,
>> +       CDM_CDWN_OFFSITE,
>> +};
>> +
>> +enum dpu_hw_cdwn_output_type {
>> +       CDM_CDWN_OUTPUT_HDMI,
>> +       CDM_CDWN_OUTPUT_WB,
>> +};
>> +
>> +enum dpu_hw_cdwn_output_bit_depth {
>> +       CDM_CDWN_OUTPUT_8BIT,
>> +       CDM_CDWN_OUTPUT_10BIT,
>> +};
>> +
>> +/**
>> + * struct dpu_hw_cdm_ops : Interface to the chroma down Hw driver functions
>> + *                         Assumption is these functions will be called after
>> + *                         clocks are enabled
>> + *  @setup_csc:            Programs the csc matrix
>> + *  @setup_cdwn:           Sets up the chroma down sub module
>> + *  @enable:               Enables the output to interface and programs the
>> + *                         output packer
>> + *  @disable:              Puts the cdm in bypass mode
>> + *  @bind_pingpong_blk:    enable/disable the connection with pingpong which
>> + *                         will feed pixels to this cdm
>> + */
>> +struct dpu_hw_cdm_ops {
>> +       /**
>> +        * Programs the CSC matrix for conversion from RGB space to YUV space,
>> +        * it is optional to call this function as this matrix is automatically
>> +        * set during initialization, user should call this if it wants
>> +        * to program a different matrix than default matrix.
>> +        * @cdm:          Pointer to the chroma down context structure
>> +        * @data          Pointer to CSC configuration data
>> +        * return:        0 if success; error code otherwise
>> +        */
>> +       int (*setup_csc_data)(struct dpu_hw_cdm *cdm, struct dpu_csc_cfg *data);
>> +
>> +       /**
>> +        * Programs the Chroma downsample part.
>> +        * @cdm         Pointer to chroma down context
>> +        * @cfg         Pointer to the cdm configuration data
>> +        */
>> +       int (*setup_cdwn)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
>> +
>> +       /**
>> +        * Enable the CDM module
>> +        * @cdm         Pointer to chroma down context
>> +        */
>> +       int (*enable)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
>> +
>> +       /**
>> +        * Disable the CDM module
>> +        * @cdm         Pointer to chroma down context
>> +        */
>> +       void (*disable)(struct dpu_hw_cdm *cdm);
>> +
>> +       /**
>> +        * Enable/disable the connection with pingpong
>> +        * @cdm         Pointer to chroma down context
>> +        * @enable      Enable/disable control
>> +        * @pp          pingpong block id.
>> +        */
>> +       void (*bind_pingpong_blk)(struct dpu_hw_cdm *cdm, bool enable,
>> +                                 const enum dpu_pingpong pp);
>> +};
>> +
>> +/**
>> + * struct dpu_hw_cdm - cdm description
>> + * @base: Hardware block base structure
>> + * @hw: Block hardware details
>> + * @idx: CDM index
>> + * @caps: Pointer to cdm_cfg
>> + * @ops: handle to operations possible for this CDM
>> + */
>> +struct dpu_hw_cdm {
>> +       struct dpu_hw_blk base;
>> +       struct dpu_hw_blk_reg_map hw;
>> +
>> +       /* chroma down */
>> +       const struct dpu_cdm_cfg *caps;
>> +       enum  dpu_cdm  idx;
>> +
>> +       /* ops */
>> +       struct dpu_hw_cdm_ops ops;
>> +};
>> +
>> +/**
>> + * dpu_hw_cdm_init - initializes the cdm hw driver object.
>> + * should be called once before accessing every cdm.
>> + * @cdm: CDM catalog entry for which driver object is required
>> + * @addr :   mapped register io address of MDSS
>> + */
>> +struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cdm, void __iomem *addr);
>> +
>> +/**
>> + * dpu_hw_cdm_destroy - destroys cdm driver context
>> + * @cdm:   Pointer to cdm driver context returned by dpu_hw_cdm_init
>> + */
>> +void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm);
>> +
>> +static inline struct dpu_hw_cdm *to_dpu_hw_cdm(struct dpu_hw_blk *hw)
>> +{
>> +       return container_of(hw, struct dpu_hw_cdm, base);
>> +}
>> +
>> +#endif /*_DPU_HW_CDM_H */
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> index 4d6dba18caf0..34f943102499 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> @@ -463,6 +463,7 @@ struct dpu_mdss_color {
>>   #define DPU_DBG_MASK_ROT      (1 << 9)
>>   #define DPU_DBG_MASK_DSPP     (1 << 10)
>>   #define DPU_DBG_MASK_DSC      (1 << 11)
>> +#define DPU_DBG_MASK_CDM      (1 << 12)
>>
>>   /**
>>    * struct dpu_hw_tear_check - Struct contains parameters to configure
>> --
>> 2.40.1
>>
> 
> 
> --
> With best wishes
> Dmitry

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

* Re: [PATCH 07/16] drm/msm/dpu: add cdm blocks to RM
  2023-08-30 23:48     ` Dmitry Baryshkov
@ 2023-11-30 23:47       ` Abhinav Kumar
  -1 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-11-30 23:47 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel



On 8/30/2023 4:48 PM, Dmitry Baryshkov wrote:
> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> Add the RM APIs necessary to initialize and allocate CDM
>> blocks by the rest of the DPU pipeline.
> 
> ... to be used by the rest?
> 

Yes, thanks.


>>
>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 17 +++++++++++++++++
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h |  2 ++
>>   2 files changed, 19 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> index f9215643c71a..7b6444a3fcb1 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> @@ -8,6 +8,7 @@
>>   #include "dpu_kms.h"
>>   #include "dpu_hw_lm.h"
>>   #include "dpu_hw_ctl.h"
>> +#include "dpu_hw_cdm.h"
>>   #include "dpu_hw_pingpong.h"
>>   #include "dpu_hw_sspp.h"
>>   #include "dpu_hw_intf.h"
>> @@ -90,6 +91,9 @@ int dpu_rm_destroy(struct dpu_rm *rm)
>>                  }
>>          }
>>
>> +       if (rm->cdm_blk)
>> +               dpu_hw_cdm_destroy(to_dpu_hw_cdm(rm->cdm_blk));
>> +
>>          for (i = 0; i < ARRAY_SIZE(rm->hw_wb); i++)
>>                  dpu_hw_wb_destroy(rm->hw_wb[i]);
>>
>> @@ -240,6 +244,19 @@ int dpu_rm_init(struct dpu_rm *rm,
>>                  rm->hw_sspp[sspp->id - SSPP_NONE] = hw;
>>          }
>>
>> +       if (cat->cdm) {
>> +               struct dpu_hw_cdm *hw;
>> +
>> +               hw = dpu_hw_cdm_init(cat->cdm, mmio);
>> +               /* CDM is optional so no need to bail out */
>> +               if (IS_ERR(hw)) {
>> +                       rc = PTR_ERR(hw);
>> +                       DPU_DEBUG("failed cdm object creation: err %d\n", rc);
> 
> No. If it is a part of the catalog, we should fail here as we do in other cases.
> 

I guess, the only reason for not failing here was other hw blocks are 
needed even for basic display to come up but cdm is only for YUV formats.

Thats the only reason to mark this a failure which is "OK" to ignore.

But I see your point that if someone is listing this in the catalog but 
still RM fails thats an error.

Hence, ack.

> 
>> +               } else {
>> +                       rm->cdm_blk = &hw->base;
>> +               }
>> +       }
>> +
>>          return 0;
>>
>>   fail:
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>> index 2b551566cbf4..29b221491926 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>> @@ -22,6 +22,7 @@ struct dpu_global_state;
>>    * @hw_wb: array of wb hardware resources
>>    * @dspp_blks: array of dspp hardware resources
>>    * @hw_sspp: array of sspp hardware resources
>> + * @cdm_blk: cdm hardware resource
>>    */
>>   struct dpu_rm {
>>          struct dpu_hw_blk *pingpong_blks[PINGPONG_MAX - PINGPONG_0];
>> @@ -33,6 +34,7 @@ struct dpu_rm {
>>          struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0];
>>          struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0];
>>          struct dpu_hw_sspp *hw_sspp[SSPP_MAX - SSPP_NONE];
>> +       struct dpu_hw_blk *cdm_blk;
> 
> struct dpu_hw_cdm *cdm (or cdm_blk), please.

Ack.

> 
>>   };
>>
>>   /**
>> --
>> 2.40.1
>>
> 
> 
> --
> With best wishes
> Dmitry

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

* Re: [PATCH 07/16] drm/msm/dpu: add cdm blocks to RM
@ 2023-11-30 23:47       ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-11-30 23:47 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul



On 8/30/2023 4:48 PM, Dmitry Baryshkov wrote:
> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> Add the RM APIs necessary to initialize and allocate CDM
>> blocks by the rest of the DPU pipeline.
> 
> ... to be used by the rest?
> 

Yes, thanks.


>>
>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 17 +++++++++++++++++
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h |  2 ++
>>   2 files changed, 19 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> index f9215643c71a..7b6444a3fcb1 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> @@ -8,6 +8,7 @@
>>   #include "dpu_kms.h"
>>   #include "dpu_hw_lm.h"
>>   #include "dpu_hw_ctl.h"
>> +#include "dpu_hw_cdm.h"
>>   #include "dpu_hw_pingpong.h"
>>   #include "dpu_hw_sspp.h"
>>   #include "dpu_hw_intf.h"
>> @@ -90,6 +91,9 @@ int dpu_rm_destroy(struct dpu_rm *rm)
>>                  }
>>          }
>>
>> +       if (rm->cdm_blk)
>> +               dpu_hw_cdm_destroy(to_dpu_hw_cdm(rm->cdm_blk));
>> +
>>          for (i = 0; i < ARRAY_SIZE(rm->hw_wb); i++)
>>                  dpu_hw_wb_destroy(rm->hw_wb[i]);
>>
>> @@ -240,6 +244,19 @@ int dpu_rm_init(struct dpu_rm *rm,
>>                  rm->hw_sspp[sspp->id - SSPP_NONE] = hw;
>>          }
>>
>> +       if (cat->cdm) {
>> +               struct dpu_hw_cdm *hw;
>> +
>> +               hw = dpu_hw_cdm_init(cat->cdm, mmio);
>> +               /* CDM is optional so no need to bail out */
>> +               if (IS_ERR(hw)) {
>> +                       rc = PTR_ERR(hw);
>> +                       DPU_DEBUG("failed cdm object creation: err %d\n", rc);
> 
> No. If it is a part of the catalog, we should fail here as we do in other cases.
> 

I guess, the only reason for not failing here was other hw blocks are 
needed even for basic display to come up but cdm is only for YUV formats.

Thats the only reason to mark this a failure which is "OK" to ignore.

But I see your point that if someone is listing this in the catalog but 
still RM fails thats an error.

Hence, ack.

> 
>> +               } else {
>> +                       rm->cdm_blk = &hw->base;
>> +               }
>> +       }
>> +
>>          return 0;
>>
>>   fail:
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>> index 2b551566cbf4..29b221491926 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>> @@ -22,6 +22,7 @@ struct dpu_global_state;
>>    * @hw_wb: array of wb hardware resources
>>    * @dspp_blks: array of dspp hardware resources
>>    * @hw_sspp: array of sspp hardware resources
>> + * @cdm_blk: cdm hardware resource
>>    */
>>   struct dpu_rm {
>>          struct dpu_hw_blk *pingpong_blks[PINGPONG_MAX - PINGPONG_0];
>> @@ -33,6 +34,7 @@ struct dpu_rm {
>>          struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0];
>>          struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0];
>>          struct dpu_hw_sspp *hw_sspp[SSPP_MAX - SSPP_NONE];
>> +       struct dpu_hw_blk *cdm_blk;
> 
> struct dpu_hw_cdm *cdm (or cdm_blk), please.

Ack.

> 
>>   };
>>
>>   /**
>> --
>> 2.40.1
>>
> 
> 
> --
> With best wishes
> Dmitry

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

* Re: [PATCH 08/16] drm/msm/dpu: add support to allocate CDM from RM
  2023-08-31  0:06     ` Dmitry Baryshkov
@ 2023-11-30 23:50       ` Abhinav Kumar
  -1 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-11-30 23:50 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel



On 8/30/2023 5:06 PM, Dmitry Baryshkov wrote:
> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> Even though there is usually only one CDM block, it can be
>> used by either HDMI, DisplayPort OR Writeback interfaces.
>>
>> Hence its allocation needs to be tracked properly by the
>> resource manager to ensure appropriate availability of the
>> block.
> 
> It almost feels like an overkill, as up to now there is at most one CDM block.
> 

Yes but even that one CDM block can be used by any connector. So as we 
discussed on IRC, this just implements the FCFS and we need RM to be the 
manager of that one block.

>>
>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  2 +-
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h |  1 +
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h     |  1 +
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c      | 45 +++++++++++++++++++--
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h      |  4 +-
>>   5 files changed, 48 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> index 6cf6597148fd..582680804016 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> @@ -663,7 +663,7 @@ static int dpu_encoder_virt_atomic_check(
>>
>>                  if (!crtc_state->active_changed || crtc_state->enable)
>>                          ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
>> -                                       drm_enc, crtc_state, topology);
>> +                                       drm_enc, crtc_state, topology, false);
>>          }
>>
>>          trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> index 34f943102499..07f75f295844 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> @@ -98,6 +98,7 @@ enum dpu_hw_blk_type {
>>          DPU_HW_BLK_DSPP,
>>          DPU_HW_BLK_MERGE_3D,
>>          DPU_HW_BLK_DSC,
>> +       DPU_HW_BLK_CDM,
>>          DPU_HW_BLK_MAX,
>>   };
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>> index b6f53ca6e962..61aa58643fda 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>> @@ -136,6 +136,7 @@ struct dpu_global_state {
>>          uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
>>          uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
>>          uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
>> +       uint32_t cdm_to_enc_id;
>>   };
>>
>>   struct dpu_global_state
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> index 7b6444a3fcb1..e7d4beb4661e 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> @@ -29,10 +29,12 @@ static inline bool reserved_by_other(uint32_t *res_map, int idx,
>>   /**
>>    * struct dpu_rm_requirements - Reservation requirements parameter bundle
>>    * @topology:  selected topology for the display
>> + * @needs_cdm: whether the display needs a CDM block for the current mode
>>    * @hw_res:       Hardware resources required as reported by the encoders
>>    */
>>   struct dpu_rm_requirements {
>>          struct msm_display_topology topology;
>> +       bool needs_cdm;
>>   };
>>
>>   int dpu_rm_destroy(struct dpu_rm *rm)
>> @@ -505,6 +507,26 @@ static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
>>          return 0;
>>   }
>>
>> +static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
>> +                              struct dpu_global_state *global_state,
>> +                              struct drm_encoder *enc)
>> +{
>> +       /* try allocating only one CDM block */
>> +       if (!rm->cdm_blk) {
>> +               DPU_ERROR("CDM block does not exist\n");
>> +               return -EIO;
>> +       }
>> +
>> +       if (global_state->cdm_to_enc_id) {
>> +               DPU_ERROR("CDM_0 is already allocated\n");
>> +               return -EIO;
>> +       }
>> +
>> +       global_state->cdm_to_enc_id = enc->base.id;
>> +
>> +       return 0;
>> +}
>> +
>>   static int _dpu_rm_make_reservation(
>>                  struct dpu_rm *rm,
>>                  struct dpu_global_state *global_state,
>> @@ -530,15 +552,25 @@ static int _dpu_rm_make_reservation(
>>          if (ret)
>>                  return ret;
>>
>> +       if (reqs->needs_cdm) {
>> +               ret = _dpu_rm_reserve_cdm(rm, global_state, enc);
>> +               if (ret) {
>> +                       DPU_ERROR("unable to find CDM blk\n");
>> +                       return ret;
>> +               }
>> +       }
>> +
>>          return ret;
>>   }
>>
>>   static int _dpu_rm_populate_requirements(
>>                  struct drm_encoder *enc,
>>                  struct dpu_rm_requirements *reqs,
>> -               struct msm_display_topology req_topology)
>> +               struct msm_display_topology req_topology,
>> +               bool needs_cdm)
> 
> Push it to the topology, please. It is a part of the topology at some
> point of view.
> 

hmmm ... ok with a pinch of salt as we somewhat deviate from the true 
topology definition that topology is just how lm, dsc and intf blocks 
are used. it was not intended to hold cdm.

>>   {
>>          reqs->topology = req_topology;
>> +       reqs->needs_cdm = needs_cdm;
>>
>>          DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
>>                        reqs->topology.num_lm, reqs->topology.num_dsc,
>> @@ -571,6 +603,7 @@ void dpu_rm_release(struct dpu_global_state *global_state,
>>                  ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
>>          _dpu_rm_clear_mapping(global_state->dspp_to_enc_id,
>>                  ARRAY_SIZE(global_state->dspp_to_enc_id), enc->base.id);
>> +       _dpu_rm_clear_mapping(&global_state->cdm_to_enc_id, 1, enc->base.id);
>>   }
>>
>>   int dpu_rm_reserve(
>> @@ -578,7 +611,8 @@ int dpu_rm_reserve(
>>                  struct dpu_global_state *global_state,
>>                  struct drm_encoder *enc,
>>                  struct drm_crtc_state *crtc_state,
>> -               struct msm_display_topology topology)
>> +               struct msm_display_topology topology,
>> +               bool needs_cdm)
>>   {
>>          struct dpu_rm_requirements reqs;
>>          int ret;
>> @@ -595,7 +629,7 @@ int dpu_rm_reserve(
>>          DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
>>                        enc->base.id, crtc_state->crtc->base.id);
>>
>> -       ret = _dpu_rm_populate_requirements(enc, &reqs, topology);
>> +       ret = _dpu_rm_populate_requirements(enc, &reqs, topology, needs_cdm);
>>          if (ret) {
>>                  DPU_ERROR("failed to populate hw requirements\n");
>>                  return ret;
>> @@ -644,6 +678,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>>                  hw_to_enc_id = global_state->dsc_to_enc_id;
>>                  max_blks = ARRAY_SIZE(rm->dsc_blks);
>>                  break;
>> +       case DPU_HW_BLK_CDM:
>> +               hw_blks = &rm->cdm_blk;
>> +               hw_to_enc_id = &global_state->cdm_to_enc_id;
>> +               max_blks = 1;
>> +               break;
>>          default:
>>                  DPU_ERROR("blk type %d not managed by rm\n", type);
>>                  return 0;
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>> index 29b221491926..74262d3cb6c3 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>> @@ -69,13 +69,15 @@ int dpu_rm_destroy(struct dpu_rm *rm);
>>    * @drm_enc: DRM Encoder handle
>>    * @crtc_state: Proposed Atomic DRM CRTC State handle
>>    * @topology: Pointer to topology info for the display
>> + * @needs_cdm: bool to indicate whether current encoder needs CDM
>>    * @Return: 0 on Success otherwise -ERROR
>>    */
>>   int dpu_rm_reserve(struct dpu_rm *rm,
>>                  struct dpu_global_state *global_state,
>>                  struct drm_encoder *drm_enc,
>>                  struct drm_crtc_state *crtc_state,
>> -               struct msm_display_topology topology);
>> +               struct msm_display_topology topology,
>> +               bool needs_cdm);
>>
>>   /**
>>    * dpu_rm_reserve - Given the encoder for the display chain, release any
>> --
>> 2.40.1
>>
> 
> 

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

* Re: [PATCH 08/16] drm/msm/dpu: add support to allocate CDM from RM
@ 2023-11-30 23:50       ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-11-30 23:50 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul



On 8/30/2023 5:06 PM, Dmitry Baryshkov wrote:
> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> Even though there is usually only one CDM block, it can be
>> used by either HDMI, DisplayPort OR Writeback interfaces.
>>
>> Hence its allocation needs to be tracked properly by the
>> resource manager to ensure appropriate availability of the
>> block.
> 
> It almost feels like an overkill, as up to now there is at most one CDM block.
> 

Yes but even that one CDM block can be used by any connector. So as we 
discussed on IRC, this just implements the FCFS and we need RM to be the 
manager of that one block.

>>
>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  2 +-
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h |  1 +
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h     |  1 +
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c      | 45 +++++++++++++++++++--
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h      |  4 +-
>>   5 files changed, 48 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> index 6cf6597148fd..582680804016 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> @@ -663,7 +663,7 @@ static int dpu_encoder_virt_atomic_check(
>>
>>                  if (!crtc_state->active_changed || crtc_state->enable)
>>                          ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
>> -                                       drm_enc, crtc_state, topology);
>> +                                       drm_enc, crtc_state, topology, false);
>>          }
>>
>>          trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> index 34f943102499..07f75f295844 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> @@ -98,6 +98,7 @@ enum dpu_hw_blk_type {
>>          DPU_HW_BLK_DSPP,
>>          DPU_HW_BLK_MERGE_3D,
>>          DPU_HW_BLK_DSC,
>> +       DPU_HW_BLK_CDM,
>>          DPU_HW_BLK_MAX,
>>   };
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>> index b6f53ca6e962..61aa58643fda 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>> @@ -136,6 +136,7 @@ struct dpu_global_state {
>>          uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
>>          uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
>>          uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
>> +       uint32_t cdm_to_enc_id;
>>   };
>>
>>   struct dpu_global_state
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> index 7b6444a3fcb1..e7d4beb4661e 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> @@ -29,10 +29,12 @@ static inline bool reserved_by_other(uint32_t *res_map, int idx,
>>   /**
>>    * struct dpu_rm_requirements - Reservation requirements parameter bundle
>>    * @topology:  selected topology for the display
>> + * @needs_cdm: whether the display needs a CDM block for the current mode
>>    * @hw_res:       Hardware resources required as reported by the encoders
>>    */
>>   struct dpu_rm_requirements {
>>          struct msm_display_topology topology;
>> +       bool needs_cdm;
>>   };
>>
>>   int dpu_rm_destroy(struct dpu_rm *rm)
>> @@ -505,6 +507,26 @@ static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
>>          return 0;
>>   }
>>
>> +static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
>> +                              struct dpu_global_state *global_state,
>> +                              struct drm_encoder *enc)
>> +{
>> +       /* try allocating only one CDM block */
>> +       if (!rm->cdm_blk) {
>> +               DPU_ERROR("CDM block does not exist\n");
>> +               return -EIO;
>> +       }
>> +
>> +       if (global_state->cdm_to_enc_id) {
>> +               DPU_ERROR("CDM_0 is already allocated\n");
>> +               return -EIO;
>> +       }
>> +
>> +       global_state->cdm_to_enc_id = enc->base.id;
>> +
>> +       return 0;
>> +}
>> +
>>   static int _dpu_rm_make_reservation(
>>                  struct dpu_rm *rm,
>>                  struct dpu_global_state *global_state,
>> @@ -530,15 +552,25 @@ static int _dpu_rm_make_reservation(
>>          if (ret)
>>                  return ret;
>>
>> +       if (reqs->needs_cdm) {
>> +               ret = _dpu_rm_reserve_cdm(rm, global_state, enc);
>> +               if (ret) {
>> +                       DPU_ERROR("unable to find CDM blk\n");
>> +                       return ret;
>> +               }
>> +       }
>> +
>>          return ret;
>>   }
>>
>>   static int _dpu_rm_populate_requirements(
>>                  struct drm_encoder *enc,
>>                  struct dpu_rm_requirements *reqs,
>> -               struct msm_display_topology req_topology)
>> +               struct msm_display_topology req_topology,
>> +               bool needs_cdm)
> 
> Push it to the topology, please. It is a part of the topology at some
> point of view.
> 

hmmm ... ok with a pinch of salt as we somewhat deviate from the true 
topology definition that topology is just how lm, dsc and intf blocks 
are used. it was not intended to hold cdm.

>>   {
>>          reqs->topology = req_topology;
>> +       reqs->needs_cdm = needs_cdm;
>>
>>          DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
>>                        reqs->topology.num_lm, reqs->topology.num_dsc,
>> @@ -571,6 +603,7 @@ void dpu_rm_release(struct dpu_global_state *global_state,
>>                  ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
>>          _dpu_rm_clear_mapping(global_state->dspp_to_enc_id,
>>                  ARRAY_SIZE(global_state->dspp_to_enc_id), enc->base.id);
>> +       _dpu_rm_clear_mapping(&global_state->cdm_to_enc_id, 1, enc->base.id);
>>   }
>>
>>   int dpu_rm_reserve(
>> @@ -578,7 +611,8 @@ int dpu_rm_reserve(
>>                  struct dpu_global_state *global_state,
>>                  struct drm_encoder *enc,
>>                  struct drm_crtc_state *crtc_state,
>> -               struct msm_display_topology topology)
>> +               struct msm_display_topology topology,
>> +               bool needs_cdm)
>>   {
>>          struct dpu_rm_requirements reqs;
>>          int ret;
>> @@ -595,7 +629,7 @@ int dpu_rm_reserve(
>>          DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
>>                        enc->base.id, crtc_state->crtc->base.id);
>>
>> -       ret = _dpu_rm_populate_requirements(enc, &reqs, topology);
>> +       ret = _dpu_rm_populate_requirements(enc, &reqs, topology, needs_cdm);
>>          if (ret) {
>>                  DPU_ERROR("failed to populate hw requirements\n");
>>                  return ret;
>> @@ -644,6 +678,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>>                  hw_to_enc_id = global_state->dsc_to_enc_id;
>>                  max_blks = ARRAY_SIZE(rm->dsc_blks);
>>                  break;
>> +       case DPU_HW_BLK_CDM:
>> +               hw_blks = &rm->cdm_blk;
>> +               hw_to_enc_id = &global_state->cdm_to_enc_id;
>> +               max_blks = 1;
>> +               break;
>>          default:
>>                  DPU_ERROR("blk type %d not managed by rm\n", type);
>>                  return 0;
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>> index 29b221491926..74262d3cb6c3 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>> @@ -69,13 +69,15 @@ int dpu_rm_destroy(struct dpu_rm *rm);
>>    * @drm_enc: DRM Encoder handle
>>    * @crtc_state: Proposed Atomic DRM CRTC State handle
>>    * @topology: Pointer to topology info for the display
>> + * @needs_cdm: bool to indicate whether current encoder needs CDM
>>    * @Return: 0 on Success otherwise -ERROR
>>    */
>>   int dpu_rm_reserve(struct dpu_rm *rm,
>>                  struct dpu_global_state *global_state,
>>                  struct drm_encoder *drm_enc,
>>                  struct drm_crtc_state *crtc_state,
>> -               struct msm_display_topology topology);
>> +               struct msm_display_topology topology,
>> +               bool needs_cdm);
>>
>>   /**
>>    * dpu_rm_reserve - Given the encoder for the display chain, release any
>> --
>> 2.40.1
>>
> 
> 

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

* Re: [PATCH 09/16] drm/msm/dpu: add CDM related logic to dpu_hw_ctl layer
  2023-08-31  0:12     ` Dmitry Baryshkov
@ 2023-11-30 23:54       ` Abhinav Kumar
  -1 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-11-30 23:54 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul



On 8/30/2023 5:12 PM, Dmitry Baryshkov wrote:
> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> CDM block will need its own logic to program the flush and active
>> bits in the dpu_hw_ctl layer.
>>
>> Make necessary changes in dpu_hw_ctl to support CDM programming.
>>
>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 34 ++++++++++++++++++++++
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 11 +++++++
>>   2 files changed, 45 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 c278fb9d2b5b..beced9f19740 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
>> @@ -29,11 +29,13 @@
>>   #define   CTL_DSC_ACTIVE                0x0E8
>>   #define   CTL_WB_ACTIVE                 0x0EC
>>   #define   CTL_INTF_ACTIVE               0x0F4
>> +#define   CTL_CDM_ACTIVE                0x0F8
>>   #define   CTL_FETCH_PIPE_ACTIVE         0x0FC
>>   #define   CTL_MERGE_3D_FLUSH            0x100
>>   #define   CTL_DSC_FLUSH                0x104
>>   #define   CTL_WB_FLUSH                  0x108
>>   #define   CTL_INTF_FLUSH                0x110
>> +#define   CTL_CDM_FLUSH                0x114
>>   #define   CTL_INTF_MASTER               0x134
>>   #define   CTL_DSPP_n_FLUSH(n)           ((0x13C) + ((n) * 4))
>>
>> @@ -43,6 +45,7 @@
>>   #define DPU_REG_RESET_TIMEOUT_US        2000
>>   #define  MERGE_3D_IDX   23
>>   #define  DSC_IDX        22
>> +#define CDM_IDX         26
>>   #define  INTF_IDX       31
>>   #define WB_IDX          16
>>   #define  DSPP_IDX       29  /* From DPU hw rev 7.x.x */
>> @@ -104,6 +107,7 @@ static inline void dpu_hw_ctl_clear_pending_flush(struct dpu_hw_ctl *ctx)
>>          ctx->pending_wb_flush_mask = 0;
>>          ctx->pending_merge_3d_flush_mask = 0;
>>          ctx->pending_dsc_flush_mask = 0;
>> +       ctx->pending_cdm_flush_mask = 0;
>>
>>          memset(ctx->pending_dspp_flush_mask, 0,
>>                  sizeof(ctx->pending_dspp_flush_mask));
>> @@ -148,6 +152,10 @@ static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
>>                  DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH,
>>                                ctx->pending_dsc_flush_mask);
>>
>> +       if (ctx->pending_flush_mask & BIT(CDM_IDX))
>> +               DPU_REG_WRITE(&ctx->hw, CTL_CDM_FLUSH,
>> +                             ctx->pending_cdm_flush_mask);
>> +
>>          DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask);
>>   }
>>
>> @@ -273,6 +281,12 @@ static void dpu_hw_ctl_update_pending_flush_wb(struct dpu_hw_ctl *ctx,
>>          }
>>   }
>>
>> +static void dpu_hw_ctl_update_pending_flush_cdm(struct dpu_hw_ctl *ctx)
>> +{
>> +       ctx->pending_flush_mask |= BIT(CDM_IDX);
>> +
> 
> unused empty line.
>

Yes indeed.

>> +}
>> +
>>   static void dpu_hw_ctl_update_pending_flush_wb_v1(struct dpu_hw_ctl *ctx,
>>                  enum dpu_wb wb)
>>   {
>> @@ -301,6 +315,12 @@ static void dpu_hw_ctl_update_pending_flush_dsc_v1(struct dpu_hw_ctl *ctx,
>>          ctx->pending_flush_mask |= BIT(DSC_IDX);
>>   }
>>
>> +static void dpu_hw_ctl_update_pending_flush_cdm_v1(struct dpu_hw_ctl *ctx)
>> +{
>> +       ctx->pending_cdm_flush_mask |= BIT(0);
> 
> I'd assume this is because there is just CDM_0? Then it still might be
> better to write BIT(cdm->idx - CDM_0).
> 

Ack.

>> +       ctx->pending_flush_mask |= BIT(CDM_IDX);
>> +}
>> +
>>   static void dpu_hw_ctl_update_pending_flush_dspp(struct dpu_hw_ctl *ctx,
>>          enum dpu_dspp dspp, u32 dspp_sub_blk)
>>   {
>> @@ -504,6 +524,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
>>          u32 intf_active = 0;
>>          u32 wb_active = 0;
>>          u32 mode_sel = 0;
>> +       u32 cdm_active = 0;
>>
>>          /* CTL_TOP[31:28] carries group_id to collate CTL paths
>>           * per VM. Explicitly disable it until VM support is
>> @@ -517,6 +538,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
>>
>>          intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE);
>>          wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE);
>> +       cdm_active = DPU_REG_READ(c, CTL_CDM_ACTIVE);
>>
>>          if (cfg->intf)
>>                  intf_active |= BIT(cfg->intf - INTF_0);
>> @@ -534,6 +556,9 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
>>
>>          if (cfg->dsc)
>>                  DPU_REG_WRITE(c, CTL_DSC_ACTIVE, cfg->dsc);
>> +
>> +       if (cfg->cdm)
>> +               DPU_REG_WRITE(c, CTL_CDM_ACTIVE, cfg->cdm);
>>   }
>>
>>   static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
>> @@ -577,6 +602,7 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx,
>>          u32 wb_active = 0;
>>          u32 merge3d_active = 0;
>>          u32 dsc_active;
>> +       u32 cdm_active;
>>
>>          /*
>>           * This API resets each portion of the CTL path namely,
>> @@ -612,6 +638,12 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx,
>>                  dsc_active &= ~cfg->dsc;
>>                  DPU_REG_WRITE(c, CTL_DSC_ACTIVE, dsc_active);
>>          }
>> +
>> +       if (cfg->cdm) {
>> +               cdm_active = DPU_REG_READ(c, CTL_CDM_ACTIVE);
>> +               cdm_active &= ~cfg->cdm;
>> +               DPU_REG_WRITE(c, CTL_CDM_ACTIVE, cdm_active);
>> +       }
>>   }
>>
>>   static void dpu_hw_ctl_set_fetch_pipe_active(struct dpu_hw_ctl *ctx,
>> @@ -645,12 +677,14 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
>>                  ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb_v1;
>>                  ops->update_pending_flush_dsc =
>>                          dpu_hw_ctl_update_pending_flush_dsc_v1;
>> +               ops->update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm_v1;
>>          } else {
>>                  ops->trigger_flush = dpu_hw_ctl_trigger_flush;
>>                  ops->setup_intf_cfg = dpu_hw_ctl_intf_cfg;
>>                  ops->update_pending_flush_intf =
>>                          dpu_hw_ctl_update_pending_flush_intf;
>>                  ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb;
>> +               ops->update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm;
>>          }
>>          ops->clear_pending_flush = dpu_hw_ctl_clear_pending_flush;
>>          ops->update_pending_flush = dpu_hw_ctl_update_pending_flush;
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
>> index 1c242298ff2e..6dd44dfdfb61 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
>> @@ -39,6 +39,7 @@ struct dpu_hw_stage_cfg {
>>    * @mode_3d:               3d mux configuration
>>    * @merge_3d:              3d merge block used
>>    * @intf_mode_sel:         Interface mode, cmd / vid
>> + * @cdm:                   CDM block used
>>    * @stream_sel:            Stream selection for multi-stream interfaces
>>    * @dsc:                   DSC BIT masks used
>>    */
>> @@ -48,6 +49,7 @@ struct dpu_hw_intf_cfg {
>>          enum dpu_3d_blend_mode mode_3d;
>>          enum dpu_merge_3d merge_3d;
>>          enum dpu_ctl_mode_sel intf_mode_sel;
>> +       enum dpu_cdm cdm;
>>          int stream_sel;
>>          unsigned int dsc;
>>   };
>> @@ -166,6 +168,13 @@ struct dpu_hw_ctl_ops {
>>          void (*update_pending_flush_dsc)(struct dpu_hw_ctl *ctx,
>>                                           enum dpu_dsc blk);
>>
>> +       /**
>> +        * OR in the given flushbits to the cached pending_(cdm_)flush_mask
>> +        * No effect on hardware
>> +        * @ctx: ctl path ctx pointer
>> +        */
>> +       void (*update_pending_flush_cdm)(struct dpu_hw_ctl *ctx);
>> +
>>          /**
>>           * Write the value of the pending_flush_mask to hardware
>>           * @ctx       : ctl path ctx pointer
>> @@ -239,6 +248,7 @@ struct dpu_hw_ctl_ops {
>>    * @pending_intf_flush_mask: pending INTF flush
>>    * @pending_wb_flush_mask: pending WB flush
>>    * @pending_dsc_flush_mask: pending DSC flush
>> + * @pending_cdm_flush_mask: pending CDM flush
>>    * @ops: operation list
>>    */
>>   struct dpu_hw_ctl {
>> @@ -256,6 +266,7 @@ struct dpu_hw_ctl {
>>          u32 pending_merge_3d_flush_mask;
>>          u32 pending_dspp_flush_mask[DSPP_MAX - DSPP_0];
>>          u32 pending_dsc_flush_mask;
>> +       u32 pending_cdm_flush_mask;
>>
>>          /* ops */
>>          struct dpu_hw_ctl_ops ops;
>> --
>> 2.40.1
>>
> 
> 

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

* Re: [PATCH 09/16] drm/msm/dpu: add CDM related logic to dpu_hw_ctl layer
@ 2023-11-30 23:54       ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-11-30 23:54 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel



On 8/30/2023 5:12 PM, Dmitry Baryshkov wrote:
> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> CDM block will need its own logic to program the flush and active
>> bits in the dpu_hw_ctl layer.
>>
>> Make necessary changes in dpu_hw_ctl to support CDM programming.
>>
>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 34 ++++++++++++++++++++++
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 11 +++++++
>>   2 files changed, 45 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 c278fb9d2b5b..beced9f19740 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
>> @@ -29,11 +29,13 @@
>>   #define   CTL_DSC_ACTIVE                0x0E8
>>   #define   CTL_WB_ACTIVE                 0x0EC
>>   #define   CTL_INTF_ACTIVE               0x0F4
>> +#define   CTL_CDM_ACTIVE                0x0F8
>>   #define   CTL_FETCH_PIPE_ACTIVE         0x0FC
>>   #define   CTL_MERGE_3D_FLUSH            0x100
>>   #define   CTL_DSC_FLUSH                0x104
>>   #define   CTL_WB_FLUSH                  0x108
>>   #define   CTL_INTF_FLUSH                0x110
>> +#define   CTL_CDM_FLUSH                0x114
>>   #define   CTL_INTF_MASTER               0x134
>>   #define   CTL_DSPP_n_FLUSH(n)           ((0x13C) + ((n) * 4))
>>
>> @@ -43,6 +45,7 @@
>>   #define DPU_REG_RESET_TIMEOUT_US        2000
>>   #define  MERGE_3D_IDX   23
>>   #define  DSC_IDX        22
>> +#define CDM_IDX         26
>>   #define  INTF_IDX       31
>>   #define WB_IDX          16
>>   #define  DSPP_IDX       29  /* From DPU hw rev 7.x.x */
>> @@ -104,6 +107,7 @@ static inline void dpu_hw_ctl_clear_pending_flush(struct dpu_hw_ctl *ctx)
>>          ctx->pending_wb_flush_mask = 0;
>>          ctx->pending_merge_3d_flush_mask = 0;
>>          ctx->pending_dsc_flush_mask = 0;
>> +       ctx->pending_cdm_flush_mask = 0;
>>
>>          memset(ctx->pending_dspp_flush_mask, 0,
>>                  sizeof(ctx->pending_dspp_flush_mask));
>> @@ -148,6 +152,10 @@ static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
>>                  DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH,
>>                                ctx->pending_dsc_flush_mask);
>>
>> +       if (ctx->pending_flush_mask & BIT(CDM_IDX))
>> +               DPU_REG_WRITE(&ctx->hw, CTL_CDM_FLUSH,
>> +                             ctx->pending_cdm_flush_mask);
>> +
>>          DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask);
>>   }
>>
>> @@ -273,6 +281,12 @@ static void dpu_hw_ctl_update_pending_flush_wb(struct dpu_hw_ctl *ctx,
>>          }
>>   }
>>
>> +static void dpu_hw_ctl_update_pending_flush_cdm(struct dpu_hw_ctl *ctx)
>> +{
>> +       ctx->pending_flush_mask |= BIT(CDM_IDX);
>> +
> 
> unused empty line.
>

Yes indeed.

>> +}
>> +
>>   static void dpu_hw_ctl_update_pending_flush_wb_v1(struct dpu_hw_ctl *ctx,
>>                  enum dpu_wb wb)
>>   {
>> @@ -301,6 +315,12 @@ static void dpu_hw_ctl_update_pending_flush_dsc_v1(struct dpu_hw_ctl *ctx,
>>          ctx->pending_flush_mask |= BIT(DSC_IDX);
>>   }
>>
>> +static void dpu_hw_ctl_update_pending_flush_cdm_v1(struct dpu_hw_ctl *ctx)
>> +{
>> +       ctx->pending_cdm_flush_mask |= BIT(0);
> 
> I'd assume this is because there is just CDM_0? Then it still might be
> better to write BIT(cdm->idx - CDM_0).
> 

Ack.

>> +       ctx->pending_flush_mask |= BIT(CDM_IDX);
>> +}
>> +
>>   static void dpu_hw_ctl_update_pending_flush_dspp(struct dpu_hw_ctl *ctx,
>>          enum dpu_dspp dspp, u32 dspp_sub_blk)
>>   {
>> @@ -504,6 +524,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
>>          u32 intf_active = 0;
>>          u32 wb_active = 0;
>>          u32 mode_sel = 0;
>> +       u32 cdm_active = 0;
>>
>>          /* CTL_TOP[31:28] carries group_id to collate CTL paths
>>           * per VM. Explicitly disable it until VM support is
>> @@ -517,6 +538,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
>>
>>          intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE);
>>          wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE);
>> +       cdm_active = DPU_REG_READ(c, CTL_CDM_ACTIVE);
>>
>>          if (cfg->intf)
>>                  intf_active |= BIT(cfg->intf - INTF_0);
>> @@ -534,6 +556,9 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
>>
>>          if (cfg->dsc)
>>                  DPU_REG_WRITE(c, CTL_DSC_ACTIVE, cfg->dsc);
>> +
>> +       if (cfg->cdm)
>> +               DPU_REG_WRITE(c, CTL_CDM_ACTIVE, cfg->cdm);
>>   }
>>
>>   static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
>> @@ -577,6 +602,7 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx,
>>          u32 wb_active = 0;
>>          u32 merge3d_active = 0;
>>          u32 dsc_active;
>> +       u32 cdm_active;
>>
>>          /*
>>           * This API resets each portion of the CTL path namely,
>> @@ -612,6 +638,12 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx,
>>                  dsc_active &= ~cfg->dsc;
>>                  DPU_REG_WRITE(c, CTL_DSC_ACTIVE, dsc_active);
>>          }
>> +
>> +       if (cfg->cdm) {
>> +               cdm_active = DPU_REG_READ(c, CTL_CDM_ACTIVE);
>> +               cdm_active &= ~cfg->cdm;
>> +               DPU_REG_WRITE(c, CTL_CDM_ACTIVE, cdm_active);
>> +       }
>>   }
>>
>>   static void dpu_hw_ctl_set_fetch_pipe_active(struct dpu_hw_ctl *ctx,
>> @@ -645,12 +677,14 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
>>                  ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb_v1;
>>                  ops->update_pending_flush_dsc =
>>                          dpu_hw_ctl_update_pending_flush_dsc_v1;
>> +               ops->update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm_v1;
>>          } else {
>>                  ops->trigger_flush = dpu_hw_ctl_trigger_flush;
>>                  ops->setup_intf_cfg = dpu_hw_ctl_intf_cfg;
>>                  ops->update_pending_flush_intf =
>>                          dpu_hw_ctl_update_pending_flush_intf;
>>                  ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb;
>> +               ops->update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm;
>>          }
>>          ops->clear_pending_flush = dpu_hw_ctl_clear_pending_flush;
>>          ops->update_pending_flush = dpu_hw_ctl_update_pending_flush;
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
>> index 1c242298ff2e..6dd44dfdfb61 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
>> @@ -39,6 +39,7 @@ struct dpu_hw_stage_cfg {
>>    * @mode_3d:               3d mux configuration
>>    * @merge_3d:              3d merge block used
>>    * @intf_mode_sel:         Interface mode, cmd / vid
>> + * @cdm:                   CDM block used
>>    * @stream_sel:            Stream selection for multi-stream interfaces
>>    * @dsc:                   DSC BIT masks used
>>    */
>> @@ -48,6 +49,7 @@ struct dpu_hw_intf_cfg {
>>          enum dpu_3d_blend_mode mode_3d;
>>          enum dpu_merge_3d merge_3d;
>>          enum dpu_ctl_mode_sel intf_mode_sel;
>> +       enum dpu_cdm cdm;
>>          int stream_sel;
>>          unsigned int dsc;
>>   };
>> @@ -166,6 +168,13 @@ struct dpu_hw_ctl_ops {
>>          void (*update_pending_flush_dsc)(struct dpu_hw_ctl *ctx,
>>                                           enum dpu_dsc blk);
>>
>> +       /**
>> +        * OR in the given flushbits to the cached pending_(cdm_)flush_mask
>> +        * No effect on hardware
>> +        * @ctx: ctl path ctx pointer
>> +        */
>> +       void (*update_pending_flush_cdm)(struct dpu_hw_ctl *ctx);
>> +
>>          /**
>>           * Write the value of the pending_flush_mask to hardware
>>           * @ctx       : ctl path ctx pointer
>> @@ -239,6 +248,7 @@ struct dpu_hw_ctl_ops {
>>    * @pending_intf_flush_mask: pending INTF flush
>>    * @pending_wb_flush_mask: pending WB flush
>>    * @pending_dsc_flush_mask: pending DSC flush
>> + * @pending_cdm_flush_mask: pending CDM flush
>>    * @ops: operation list
>>    */
>>   struct dpu_hw_ctl {
>> @@ -256,6 +266,7 @@ struct dpu_hw_ctl {
>>          u32 pending_merge_3d_flush_mask;
>>          u32 pending_dspp_flush_mask[DSPP_MAX - DSPP_0];
>>          u32 pending_dsc_flush_mask;
>> +       u32 pending_cdm_flush_mask;
>>
>>          /* ops */
>>          struct dpu_hw_ctl_ops ops;
>> --
>> 2.40.1
>>
> 
> 

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

* Re: [PATCH 10/16] drm/msm/dpu: add support to disable CDM block during encoder cleanup
  2023-08-31  0:14     ` Dmitry Baryshkov
@ 2023-11-30 23:58       ` Abhinav Kumar
  -1 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-11-30 23:58 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel



On 8/30/2023 5:14 PM, Dmitry Baryshkov wrote:
> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> In preparation of setting up CDM block, add the logic to disable it
>> properly during encoder cleanup.
>>
>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c      | 8 ++++++++
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 2 ++
>>   2 files changed, 10 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> index 582680804016..1b1e07292a9e 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> @@ -26,6 +26,7 @@
>>   #include "dpu_hw_dspp.h"
>>   #include "dpu_hw_dsc.h"
>>   #include "dpu_hw_merge3d.h"
>> +#include "dpu_hw_cdm.h"
>>   #include "dpu_formats.h"
>>   #include "dpu_encoder_phys.h"
>>   #include "dpu_crtc.h"
>> @@ -2097,6 +2098,13 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
>>                                          phys_enc->hw_pp->merge_3d->idx);
>>          }
>>
>> +       if (phys_enc->hw_cdm && phys_enc->hw_cdm->ops.bind_pingpong_blk && phys_enc->hw_pp) {
>> +               phys_enc->hw_cdm->ops.bind_pingpong_blk(phys_enc->hw_cdm,
>> +                                                       false, phys_enc->hw_pp->idx);
> 
> But it was already bound in the cdm->enable, wasn't it?
> 

This is disable. I think you missed the "false" parameter.

> Also the update_pending_flush_cdm should be called even for DPU < 5.0,
> where there should be no bind_pingpong_blk callback.
> 

Ack. This is a good catch!

>> +               if (phys_enc->hw_ctl->ops.update_pending_flush_cdm)
>> +                       phys_enc->hw_ctl->ops.update_pending_flush_cdm(phys_enc->hw_ctl);
>> +       }
>> +
>>          if (dpu_enc->dsc) {
>>                  dpu_encoder_unprep_dsc(dpu_enc);
>>                  dpu_enc->dsc = NULL;
>> 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 24dbc28be4f8..510c1c41ddbc 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>> @@ -150,6 +150,7 @@ enum dpu_intr_idx {
>>    * @hw_pp:             Hardware interface to the ping pong registers
>>    * @hw_intf:           Hardware interface to the intf registers
>>    * @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
>>    * @cached_mode:       DRM mode cached at mode_set time, acted on in enable
>>    * @enabled:           Whether the encoder has enabled and running a mode
>> @@ -178,6 +179,7 @@ struct dpu_encoder_phys {
>>          struct dpu_hw_pingpong *hw_pp;
>>          struct dpu_hw_intf *hw_intf;
>>          struct dpu_hw_wb *hw_wb;
>> +       struct dpu_hw_cdm *hw_cdm;
>>          struct dpu_kms *dpu_kms;
>>          struct drm_display_mode cached_mode;
>>          enum dpu_enc_split_role split_role;
>> --
>> 2.40.1
>>
> 
> 

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

* Re: [PATCH 10/16] drm/msm/dpu: add support to disable CDM block during encoder cleanup
@ 2023-11-30 23:58       ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-11-30 23:58 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul



On 8/30/2023 5:14 PM, Dmitry Baryshkov wrote:
> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> In preparation of setting up CDM block, add the logic to disable it
>> properly during encoder cleanup.
>>
>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c      | 8 ++++++++
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 2 ++
>>   2 files changed, 10 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> index 582680804016..1b1e07292a9e 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> @@ -26,6 +26,7 @@
>>   #include "dpu_hw_dspp.h"
>>   #include "dpu_hw_dsc.h"
>>   #include "dpu_hw_merge3d.h"
>> +#include "dpu_hw_cdm.h"
>>   #include "dpu_formats.h"
>>   #include "dpu_encoder_phys.h"
>>   #include "dpu_crtc.h"
>> @@ -2097,6 +2098,13 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
>>                                          phys_enc->hw_pp->merge_3d->idx);
>>          }
>>
>> +       if (phys_enc->hw_cdm && phys_enc->hw_cdm->ops.bind_pingpong_blk && phys_enc->hw_pp) {
>> +               phys_enc->hw_cdm->ops.bind_pingpong_blk(phys_enc->hw_cdm,
>> +                                                       false, phys_enc->hw_pp->idx);
> 
> But it was already bound in the cdm->enable, wasn't it?
> 

This is disable. I think you missed the "false" parameter.

> Also the update_pending_flush_cdm should be called even for DPU < 5.0,
> where there should be no bind_pingpong_blk callback.
> 

Ack. This is a good catch!

>> +               if (phys_enc->hw_ctl->ops.update_pending_flush_cdm)
>> +                       phys_enc->hw_ctl->ops.update_pending_flush_cdm(phys_enc->hw_ctl);
>> +       }
>> +
>>          if (dpu_enc->dsc) {
>>                  dpu_encoder_unprep_dsc(dpu_enc);
>>                  dpu_enc->dsc = NULL;
>> 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 24dbc28be4f8..510c1c41ddbc 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>> @@ -150,6 +150,7 @@ enum dpu_intr_idx {
>>    * @hw_pp:             Hardware interface to the ping pong registers
>>    * @hw_intf:           Hardware interface to the intf registers
>>    * @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
>>    * @cached_mode:       DRM mode cached at mode_set time, acted on in enable
>>    * @enabled:           Whether the encoder has enabled and running a mode
>> @@ -178,6 +179,7 @@ struct dpu_encoder_phys {
>>          struct dpu_hw_pingpong *hw_pp;
>>          struct dpu_hw_intf *hw_intf;
>>          struct dpu_hw_wb *hw_wb;
>> +       struct dpu_hw_cdm *hw_cdm;
>>          struct dpu_kms *dpu_kms;
>>          struct drm_display_mode cached_mode;
>>          enum dpu_enc_split_role split_role;
>> --
>> 2.40.1
>>
> 
> 

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

* Re: [PATCH 11/16] drm/msm/dpu: add an API to setup the CDM block for writeback
  2023-08-31  0:11     ` Dmitry Baryshkov
@ 2023-12-01  0:41       ` Abhinav Kumar
  -1 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-12-01  0:41 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel



On 8/30/2023 5:11 PM, Dmitry Baryshkov wrote:
> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> Add an API dpu_encoder_helper_phys_setup_cdm() which can be used by
>> the writeback encoder to setup the CDM block.
>>
>> Currently, this is defined and used within the writeback's physical
>> encoder layer however, the function can be modified to be used to setup
>> the CDM block even for non-writeback interfaces.
>>
>> Until those modifications are planned and made, keep it local to
>> writeback.
>>
>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>> ---
>>   .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   3 +
>>   .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 123 +++++++++++++++++-
>>   2 files changed, 125 insertions(+), 1 deletion(-)
>>
>> 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 510c1c41ddbc..93a8ae67beff 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>> @@ -16,6 +16,7 @@
>>   #include "dpu_hw_pingpong.h"
>>   #include "dpu_hw_ctl.h"
>>   #include "dpu_hw_top.h"
>> +#include "dpu_hw_cdm.h"
>>   #include "dpu_encoder.h"
>>   #include "dpu_crtc.h"
>>
>> @@ -209,6 +210,7 @@ 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
>> @@ -218,6 +220,7 @@ 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 4c2736c3ee6d..11935aac9fd5 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
>> @@ -24,6 +24,20 @@
>>   #define to_dpu_encoder_phys_wb(x) \
>>          container_of(x, struct dpu_encoder_phys_wb, base)
>>
>> +#define TO_S15D16(_x_)((_x_) << 7)
>> +
>> +static struct dpu_csc_cfg dpu_encoder_phys_wb_rgb2yuv_601l = {
>> +       {
>> +               TO_S15D16(0x0083), TO_S15D16(0x0102), TO_S15D16(0x0032),
>> +               TO_S15D16(0x1fb5), TO_S15D16(0x1f6c), TO_S15D16(0x00e1),
>> +               TO_S15D16(0x00e1), TO_S15D16(0x1f45), TO_S15D16(0x1fdc)
>> +       },
>> +       { 0x00, 0x00, 0x00 },
>> +       { 0x0040, 0x0200, 0x0200 },
>> +       { 0x000, 0x3ff, 0x000, 0x3ff, 0x000, 0x3ff },
>> +       { 0x040, 0x3ac, 0x040, 0x3c0, 0x040, 0x3c0 },
>> +};
> 
> Nit: we probably need to have a single place with all dpu_csc_cfg entries.
> 

hmmm ... so we have YUV2RGB matrices for dpu plane and RGB2YUV matrices 
for WB and DP.

We can move all this to dpu_hw_util.c but lets do that in the DP series 
as that completes the consumer list of these matrices.

>> +
>>   /**
>>    * dpu_encoder_phys_wb_is_master - report wb always as master encoder
>>    * @phys_enc:  Pointer to physical encoder
>> @@ -225,6 +239,112 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
>>          }
>>   }
>>
>> +/**
>> + * dpu_encoder_phys_wb_setup_cdp - setup chroma down sampling block
>> + * @phys_enc:Pointer to physical encoder
>> + */
>> +static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
>> +{
>> +       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;
>> +       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;
>> +
>> +       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.disable)
>> +                       hw_cdm->ops.disable(hw_cdm);
>> +
>> +               return;
>> +       }
>> +
>> +       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_fmt = dpu_fmt;
>> +       cdm_cfg->output_type = CDM_CDWN_OUTPUT_WB;
>> +       cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
>> +                       CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
>> +
>> +       /* 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 && hw_cdm->ops.setup_csc_data) {
>> +               ret = hw_cdm->ops.setup_csc_data(hw_cdm, &dpu_encoder_phys_wb_rgb2yuv_601l);
>> +               if (ret < 0) {
>> +                       DPU_ERROR("[enc:%d] failed to setup CSC; ret:%d\n",
>> +                                 DRMID(phys_enc->parent), ret);
>> +                       return;
>> +               }
>> +       }
>> +
>> +       if (hw_cdm && hw_cdm->ops.setup_cdwn) {
> 
> You have checked for (!hw_cdm) several lines above. We can drop this
> condition here.
> 

Ack.

>> +               ret = hw_cdm->ops.setup_cdwn(hw_cdm, cdm_cfg);
>> +               if (ret < 0) {
>> +                       DPU_ERROR("[enc:%d] failed to setup CDWN; ret:%d\n",
>> +                                 DRMID(phys_enc->parent), ret);
>> +                       return;
>> +               }
>> +       }
>> +
>> +       if (hw_cdm && hw_pp && hw_cdm->ops.enable) {
> 
> And what if !hw_pp ? Can it happen here? No, if I understand correctly.
> 

I dont see any other protection for !hw_pp in this flow so would prefer 
to keep it.

>> +               cdm_cfg->pp_id = hw_pp->idx;
>> +               ret = hw_cdm->ops.enable(hw_cdm, cdm_cfg);
> 
> As we are calling these three ops in a row, can we merge them together
> into a single callback to be called from dpu_encoder.c?
> 

Good idea. I can add a csc_cfg entry to cdm_cfg and merge all three into 
the enable() op itself and drop the other two.

>> +               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
>> @@ -348,8 +468,9 @@ static void dpu_encoder_phys_wb_setup(
>>
>>          dpu_encoder_phys_wb_setup_fb(phys_enc, fb);
>>
>> -       dpu_encoder_phys_wb_setup_ctl(phys_enc);
>> +       dpu_encoder_helper_phys_setup_cdm(phys_enc);
>>
>> +       dpu_encoder_phys_wb_setup_ctl(phys_enc);
>>   }
>>
>>   static void _dpu_encoder_phys_wb_frame_done_helper(void *arg)
>> --
>> 2.40.1
>>
> 
> 

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

* Re: [PATCH 11/16] drm/msm/dpu: add an API to setup the CDM block for writeback
@ 2023-12-01  0:41       ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-12-01  0:41 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul



On 8/30/2023 5:11 PM, Dmitry Baryshkov wrote:
> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> Add an API dpu_encoder_helper_phys_setup_cdm() which can be used by
>> the writeback encoder to setup the CDM block.
>>
>> Currently, this is defined and used within the writeback's physical
>> encoder layer however, the function can be modified to be used to setup
>> the CDM block even for non-writeback interfaces.
>>
>> Until those modifications are planned and made, keep it local to
>> writeback.
>>
>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>> ---
>>   .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   3 +
>>   .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 123 +++++++++++++++++-
>>   2 files changed, 125 insertions(+), 1 deletion(-)
>>
>> 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 510c1c41ddbc..93a8ae67beff 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>> @@ -16,6 +16,7 @@
>>   #include "dpu_hw_pingpong.h"
>>   #include "dpu_hw_ctl.h"
>>   #include "dpu_hw_top.h"
>> +#include "dpu_hw_cdm.h"
>>   #include "dpu_encoder.h"
>>   #include "dpu_crtc.h"
>>
>> @@ -209,6 +210,7 @@ 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
>> @@ -218,6 +220,7 @@ 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 4c2736c3ee6d..11935aac9fd5 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
>> @@ -24,6 +24,20 @@
>>   #define to_dpu_encoder_phys_wb(x) \
>>          container_of(x, struct dpu_encoder_phys_wb, base)
>>
>> +#define TO_S15D16(_x_)((_x_) << 7)
>> +
>> +static struct dpu_csc_cfg dpu_encoder_phys_wb_rgb2yuv_601l = {
>> +       {
>> +               TO_S15D16(0x0083), TO_S15D16(0x0102), TO_S15D16(0x0032),
>> +               TO_S15D16(0x1fb5), TO_S15D16(0x1f6c), TO_S15D16(0x00e1),
>> +               TO_S15D16(0x00e1), TO_S15D16(0x1f45), TO_S15D16(0x1fdc)
>> +       },
>> +       { 0x00, 0x00, 0x00 },
>> +       { 0x0040, 0x0200, 0x0200 },
>> +       { 0x000, 0x3ff, 0x000, 0x3ff, 0x000, 0x3ff },
>> +       { 0x040, 0x3ac, 0x040, 0x3c0, 0x040, 0x3c0 },
>> +};
> 
> Nit: we probably need to have a single place with all dpu_csc_cfg entries.
> 

hmmm ... so we have YUV2RGB matrices for dpu plane and RGB2YUV matrices 
for WB and DP.

We can move all this to dpu_hw_util.c but lets do that in the DP series 
as that completes the consumer list of these matrices.

>> +
>>   /**
>>    * dpu_encoder_phys_wb_is_master - report wb always as master encoder
>>    * @phys_enc:  Pointer to physical encoder
>> @@ -225,6 +239,112 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
>>          }
>>   }
>>
>> +/**
>> + * dpu_encoder_phys_wb_setup_cdp - setup chroma down sampling block
>> + * @phys_enc:Pointer to physical encoder
>> + */
>> +static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
>> +{
>> +       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;
>> +       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;
>> +
>> +       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.disable)
>> +                       hw_cdm->ops.disable(hw_cdm);
>> +
>> +               return;
>> +       }
>> +
>> +       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_fmt = dpu_fmt;
>> +       cdm_cfg->output_type = CDM_CDWN_OUTPUT_WB;
>> +       cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
>> +                       CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
>> +
>> +       /* 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 && hw_cdm->ops.setup_csc_data) {
>> +               ret = hw_cdm->ops.setup_csc_data(hw_cdm, &dpu_encoder_phys_wb_rgb2yuv_601l);
>> +               if (ret < 0) {
>> +                       DPU_ERROR("[enc:%d] failed to setup CSC; ret:%d\n",
>> +                                 DRMID(phys_enc->parent), ret);
>> +                       return;
>> +               }
>> +       }
>> +
>> +       if (hw_cdm && hw_cdm->ops.setup_cdwn) {
> 
> You have checked for (!hw_cdm) several lines above. We can drop this
> condition here.
> 

Ack.

>> +               ret = hw_cdm->ops.setup_cdwn(hw_cdm, cdm_cfg);
>> +               if (ret < 0) {
>> +                       DPU_ERROR("[enc:%d] failed to setup CDWN; ret:%d\n",
>> +                                 DRMID(phys_enc->parent), ret);
>> +                       return;
>> +               }
>> +       }
>> +
>> +       if (hw_cdm && hw_pp && hw_cdm->ops.enable) {
> 
> And what if !hw_pp ? Can it happen here? No, if I understand correctly.
> 

I dont see any other protection for !hw_pp in this flow so would prefer 
to keep it.

>> +               cdm_cfg->pp_id = hw_pp->idx;
>> +               ret = hw_cdm->ops.enable(hw_cdm, cdm_cfg);
> 
> As we are calling these three ops in a row, can we merge them together
> into a single callback to be called from dpu_encoder.c?
> 

Good idea. I can add a csc_cfg entry to cdm_cfg and merge all three into 
the enable() op itself and drop the other two.

>> +               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
>> @@ -348,8 +468,9 @@ static void dpu_encoder_phys_wb_setup(
>>
>>          dpu_encoder_phys_wb_setup_fb(phys_enc, fb);
>>
>> -       dpu_encoder_phys_wb_setup_ctl(phys_enc);
>> +       dpu_encoder_helper_phys_setup_cdm(phys_enc);
>>
>> +       dpu_encoder_phys_wb_setup_ctl(phys_enc);
>>   }
>>
>>   static void _dpu_encoder_phys_wb_frame_done_helper(void *arg)
>> --
>> 2.40.1
>>
> 
> 

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

* Re: [PATCH 13/16] drm/msm/dpu: reserve cdm blocks for writeback in case of YUV output
  2023-08-31  0:23     ` Dmitry Baryshkov
@ 2023-12-01  0:45       ` Abhinav Kumar
  -1 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-12-01  0:45 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel



On 8/30/2023 5:23 PM, Dmitry Baryshkov wrote:
> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> Reserve CDM blocks for writeback if the format of the output fb
>> is YUV. At the moment, the reservation is done only for writeback
>> but can easily be extended by relaxing the checks once other
>> interfaces are ready to output YUV.
>>
>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 35 ++++++++++++++++++++-
>>   1 file changed, 34 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 1b1e07292a9e..7a3d179bdfba 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> @@ -16,6 +16,7 @@
>>   #include <drm/drm_crtc.h>
>>   #include <drm/drm_file.h>
>>   #include <drm/drm_probe_helper.h>
>> +#include <drm/drm_framebuffer.h>
>>
>>   #include "msm_drv.h"
>>   #include "dpu_kms.h"
>> @@ -615,9 +616,11 @@ static int dpu_encoder_virt_atomic_check(
>>          struct drm_display_mode *adj_mode;
>>          struct msm_display_topology topology;
>>          struct dpu_global_state *global_state;
>> +       struct drm_framebuffer *fb;
>>          struct drm_dsc_config *dsc;
>>          int i = 0;
>>          int ret = 0;
>> +       bool needs_cdm = false;
>>
>>          if (!drm_enc || !crtc_state || !conn_state) {
>>                  DPU_ERROR("invalid arg(s), drm_enc %d, crtc/conn state %d/%d\n",
>> @@ -655,6 +658,22 @@ 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()
>> +        * earlier.
>> +        */
>> +       if (dpu_enc->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))))
>> +                       needs_cdm = true;
>> +               if (needs_cdm && !dpu_enc->cur_master->hw_cdm)
>> +                       crtc_state->mode_changed = true;
>> +               else if (!needs_cdm && dpu_enc->cur_master->hw_cdm)
>> +                       crtc_state->mode_changed = true;
>> +       }
> 
> What would be the (estimated) check for DP?
> 

Originally we were planning a lot more but now we are going to start 
with the mode being drm_mode_is_420_only and use CDM for that.

>> +
>>          /*
>>           * Release and Allocate resources on every modeset
>>           * Dont allocate when active is false.
>> @@ -664,7 +683,7 @@ static int dpu_encoder_virt_atomic_check(
>>
>>                  if (!crtc_state->active_changed || crtc_state->enable)
>>                          ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
>> -                                       drm_enc, crtc_state, topology, false);
>> +                                       drm_enc, crtc_state, topology, needs_cdm);
>>          }
>>
>>          trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
>> @@ -1126,6 +1145,20 @@ 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) {
>> +               struct dpu_hw_blk *hw_cdm = NULL;
>> +               struct drm_framebuffer *fb;
>> +
>> +               fb = conn_state->writeback_job->fb;
>> +
>> +               if (fb && DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(fb)))) {
> 
> You can drop all fb-related conditions here. If we have CDM, we know
> that we asked for it. If we do not, it's because we do not need it.
> 

hmmm .... let me do some testing with this and if it works I will make 
this change as well. Thanks.

>> +                       dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>> +                                                     drm_enc->base.id, DPU_HW_BLK_CDM,
>> +                                                     &hw_cdm, 1);
>> +               }
>> +               dpu_enc->cur_master->hw_cdm = hw_cdm ? to_dpu_hw_cdm(hw_cdm) : NULL;
>> +       }
>> +
>>          cstate = to_dpu_crtc_state(crtc_state);
>>
>>          for (i = 0; i < num_lm; i++) {
>> --
>> 2.40.1
>>
> 
> 

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

* Re: [PATCH 13/16] drm/msm/dpu: reserve cdm blocks for writeback in case of YUV output
@ 2023-12-01  0:45       ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-12-01  0:45 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul



On 8/30/2023 5:23 PM, Dmitry Baryshkov wrote:
> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> Reserve CDM blocks for writeback if the format of the output fb
>> is YUV. At the moment, the reservation is done only for writeback
>> but can easily be extended by relaxing the checks once other
>> interfaces are ready to output YUV.
>>
>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 35 ++++++++++++++++++++-
>>   1 file changed, 34 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 1b1e07292a9e..7a3d179bdfba 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> @@ -16,6 +16,7 @@
>>   #include <drm/drm_crtc.h>
>>   #include <drm/drm_file.h>
>>   #include <drm/drm_probe_helper.h>
>> +#include <drm/drm_framebuffer.h>
>>
>>   #include "msm_drv.h"
>>   #include "dpu_kms.h"
>> @@ -615,9 +616,11 @@ static int dpu_encoder_virt_atomic_check(
>>          struct drm_display_mode *adj_mode;
>>          struct msm_display_topology topology;
>>          struct dpu_global_state *global_state;
>> +       struct drm_framebuffer *fb;
>>          struct drm_dsc_config *dsc;
>>          int i = 0;
>>          int ret = 0;
>> +       bool needs_cdm = false;
>>
>>          if (!drm_enc || !crtc_state || !conn_state) {
>>                  DPU_ERROR("invalid arg(s), drm_enc %d, crtc/conn state %d/%d\n",
>> @@ -655,6 +658,22 @@ 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()
>> +        * earlier.
>> +        */
>> +       if (dpu_enc->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))))
>> +                       needs_cdm = true;
>> +               if (needs_cdm && !dpu_enc->cur_master->hw_cdm)
>> +                       crtc_state->mode_changed = true;
>> +               else if (!needs_cdm && dpu_enc->cur_master->hw_cdm)
>> +                       crtc_state->mode_changed = true;
>> +       }
> 
> What would be the (estimated) check for DP?
> 

Originally we were planning a lot more but now we are going to start 
with the mode being drm_mode_is_420_only and use CDM for that.

>> +
>>          /*
>>           * Release and Allocate resources on every modeset
>>           * Dont allocate when active is false.
>> @@ -664,7 +683,7 @@ static int dpu_encoder_virt_atomic_check(
>>
>>                  if (!crtc_state->active_changed || crtc_state->enable)
>>                          ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
>> -                                       drm_enc, crtc_state, topology, false);
>> +                                       drm_enc, crtc_state, topology, needs_cdm);
>>          }
>>
>>          trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
>> @@ -1126,6 +1145,20 @@ 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) {
>> +               struct dpu_hw_blk *hw_cdm = NULL;
>> +               struct drm_framebuffer *fb;
>> +
>> +               fb = conn_state->writeback_job->fb;
>> +
>> +               if (fb && DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(fb)))) {
> 
> You can drop all fb-related conditions here. If we have CDM, we know
> that we asked for it. If we do not, it's because we do not need it.
> 

hmmm .... let me do some testing with this and if it works I will make 
this change as well. Thanks.

>> +                       dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>> +                                                     drm_enc->base.id, DPU_HW_BLK_CDM,
>> +                                                     &hw_cdm, 1);
>> +               }
>> +               dpu_enc->cur_master->hw_cdm = hw_cdm ? to_dpu_hw_cdm(hw_cdm) : NULL;
>> +       }
>> +
>>          cstate = to_dpu_crtc_state(crtc_state);
>>
>>          for (i = 0; i < num_lm; i++) {
>> --
>> 2.40.1
>>
> 
> 

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

* Re: [PATCH 14/16] drm/msm/dpu: do not allow YUV formats if no CDM block is present
  2023-08-31  0:24     ` Dmitry Baryshkov
@ 2023-12-01  0:50       ` Abhinav Kumar
  -1 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-12-01  0:50 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel



On 8/30/2023 5:24 PM, Dmitry Baryshkov wrote:
> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> On chipsets where CDM block is not available OR where support has
>> not been added yet do not allow YUV formats for writeback block.
>>
>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 6 ++++++
>>   1 file changed, 6 insertions(+)
>>
>> 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 7fc174b33ae2..d8edca9bc964 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
>> @@ -406,6 +406,12 @@ static int dpu_encoder_phys_wb_atomic_check(
>>                  return ret;
>>          }
>>
>> +       if (DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(fb))) &&
>> +           !phys_enc->dpu_kms->catalog->cdm) {
>> +               DPU_ERROR("cannot support YUV formats without CDM block\n");
>> +               return -EINVAL;
>> +       }
> 
> Can we have YUV formats in wb_formats if we do not support CDM? That
> would be an error.

I can drop this one once i address the comments on the next patch.

Yeah the reason for this change was we had one formats array for wb and 
were using that for all chipsets. We can have two arrays : one only rgb 
and the other rgb+yuv to address this.

> 
>> +
>>          return 0;
>>   }
>>
>> --
>> 2.40.1
>>
> 
> 

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

* Re: [PATCH 14/16] drm/msm/dpu: do not allow YUV formats if no CDM block is present
@ 2023-12-01  0:50       ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-12-01  0:50 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul



On 8/30/2023 5:24 PM, Dmitry Baryshkov wrote:
> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> On chipsets where CDM block is not available OR where support has
>> not been added yet do not allow YUV formats for writeback block.
>>
>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 6 ++++++
>>   1 file changed, 6 insertions(+)
>>
>> 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 7fc174b33ae2..d8edca9bc964 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
>> @@ -406,6 +406,12 @@ static int dpu_encoder_phys_wb_atomic_check(
>>                  return ret;
>>          }
>>
>> +       if (DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(fb))) &&
>> +           !phys_enc->dpu_kms->catalog->cdm) {
>> +               DPU_ERROR("cannot support YUV formats without CDM block\n");
>> +               return -EINVAL;
>> +       }
> 
> Can we have YUV formats in wb_formats if we do not support CDM? That
> would be an error.

I can drop this one once i address the comments on the next patch.

Yeah the reason for this change was we had one formats array for wb and 
were using that for all chipsets. We can have two arrays : one only rgb 
and the other rgb+yuv to address this.

> 
>> +
>>          return 0;
>>   }
>>
>> --
>> 2.40.1
>>
> 
> 

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

* Re: [PATCH 06/16] drm/msm/dpu: add dpu_hw_cdm abstraction for CDM block
  2023-11-30 23:36       ` Abhinav Kumar
@ 2023-12-01  7:05         ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-12-01  7:05 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-kernel, linux-arm-msm

On Fri, 1 Dec 2023 at 01:36, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 8/30/2023 5:00 PM, Dmitry Baryshkov wrote:
> > On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >> CDM block comes with its own set of registers and operations
> >> which can be done. In-line with other hardware sub-blocks, this
> >> change adds the dpu_hw_cdm abstraction for the CDM block.
> >>
> >> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> >> ---
> >>   drivers/gpu/drm/msm/Makefile                |   1 +
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c  | 272 ++++++++++++++++++++
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h  | 135 ++++++++++
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h |   1 +
> >>   4 files changed, 409 insertions(+)
> >>   create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
> >>   create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
> >>
> >> diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
> >> index 8d02d8c33069..2010cb1ca995 100644
> >> --- a/drivers/gpu/drm/msm/Makefile
> >> +++ b/drivers/gpu/drm/msm/Makefile
> >> @@ -63,6 +63,7 @@ msm-$(CONFIG_DRM_MSM_DPU) += \
> >>          disp/dpu1/dpu_encoder_phys_wb.o \
> >>          disp/dpu1/dpu_formats.o \
> >>          disp/dpu1/dpu_hw_catalog.o \
> >> +       disp/dpu1/dpu_hw_cdm.o \
> >>          disp/dpu1/dpu_hw_ctl.o \
> >>          disp/dpu1/dpu_hw_dsc.o \
> >>          disp/dpu1/dpu_hw_dsc_1_2.o \
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
> >> new file mode 100644
> >> index 000000000000..a2f7ee8f54e4
> >> --- /dev/null
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
> >> @@ -0,0 +1,272 @@
> >> +// SPDX-License-Identifier: GPL-2.0-only
> >> +/*
> >> + * Copyright (c) 2023, The Linux Foundation. All rights reserved.
> >> + */
> >> +
> >> +#include <drm/drm_managed.h>
> >> +
> >> +#include "dpu_hw_mdss.h"
> >> +#include "dpu_hw_util.h"
> >> +#include "dpu_hw_catalog.h"
> >> +#include "dpu_hw_cdm.h"
> >> +#include "dpu_kms.h"
> >> +
> >> +#define CDM_CSC_10_OPMODE                  0x000
> >> +#define CDM_CSC_10_BASE                    0x004
> >> +
> >> +#define CDM_CDWN2_OP_MODE                  0x100
> >> +#define CDM_CDWN2_CLAMP_OUT                0x104
> >> +#define CDM_CDWN2_PARAMS_3D_0              0x108
> >> +#define CDM_CDWN2_PARAMS_3D_1              0x10C
> >> +#define CDM_CDWN2_COEFF_COSITE_H_0         0x110
> >> +#define CDM_CDWN2_COEFF_COSITE_H_1         0x114
> >> +#define CDM_CDWN2_COEFF_COSITE_H_2         0x118
> >> +#define CDM_CDWN2_COEFF_OFFSITE_H_0        0x11C
> >> +#define CDM_CDWN2_COEFF_OFFSITE_H_1        0x120
> >> +#define CDM_CDWN2_COEFF_OFFSITE_H_2        0x124
> >> +#define CDM_CDWN2_COEFF_COSITE_V           0x128
> >> +#define CDM_CDWN2_COEFF_OFFSITE_V          0x12C
> >> +#define CDM_CDWN2_OUT_SIZE                 0x130
> >> +
> >> +#define CDM_HDMI_PACK_OP_MODE              0x200
> >> +#define CDM_CSC_10_MATRIX_COEFF_0          0x004
> >> +
> >> +#define CDM_MUX                            0x224
> >> +
> >> +/**
> >> + * Horizontal coefficients for cosite chroma downscale
> >> + * s13 representation of coefficients
> >> + */
> >> +static u32 cosite_h_coeff[] = {0x00000016, 0x000001cc, 0x0100009e};
> >> +
> >> +/**
> >> + * Horizontal coefficients for offsite chroma downscale
> >> + */
> >> +static u32 offsite_h_coeff[] = {0x000b0005, 0x01db01eb, 0x00e40046};
> >> +
> >> +/**
> >> + * Vertical coefficients for cosite chroma downscale
> >> + */
> >> +static u32 cosite_v_coeff[] = {0x00080004};
> >> +/**
> >> + * Vertical coefficients for offsite chroma downscale
> >> + */
> >> +static u32 offsite_v_coeff[] = {0x00060002};
> >> +
> >> +static int dpu_hw_cdm_setup_csc_10bit(struct dpu_hw_cdm *ctx, struct dpu_csc_cfg *data)
> >> +{
> >> +       dpu_hw_csc_setup(&ctx->hw, CDM_CSC_10_MATRIX_COEFF_0, data, true);
> >
> > Where was this defined?
> >
>
> Its in this file itself
>
> +#define CDM_CSC_10_MATRIX_COEFF_0          0x004
>
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static int dpu_hw_cdm_setup_cdwn(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cfg)
> >> +{
> >> +       struct dpu_hw_blk_reg_map *c = &ctx->hw;
> >> +       u32 opmode = 0;
> >> +       u32 out_size = 0;
> >> +
> >> +       if (cfg->output_bit_depth == CDM_CDWN_OUTPUT_10BIT)
> >> +               opmode &= ~BIT(7);
> >> +       else
> >> +               opmode |= BIT(7);
> >> +
> >> +       /* ENABLE DWNS_H bit */
> >> +       opmode |= BIT(1);
> >> +
> >> +       switch (cfg->h_cdwn_type) {
> >> +       case CDM_CDWN_DISABLE:
> >> +               /* CLEAR METHOD_H field */
> >> +               opmode &= ~(0x18);
> >> +               /* CLEAR DWNS_H bit */
> >> +               opmode &= ~BIT(1);
> >> +               break;
> >> +       case CDM_CDWN_PIXEL_DROP:
> >> +               /* Clear METHOD_H field (pixel drop is 0) */
> >> +               opmode &= ~(0x18);
> >> +               break;
> >> +       case CDM_CDWN_AVG:
> >> +               /* Clear METHOD_H field (Average is 0x1) */
> >> +               opmode &= ~(0x18);
> >> +               opmode |= (0x1 << 0x3);
> >> +               break;
> >> +       case CDM_CDWN_COSITE:
> >> +               /* Clear METHOD_H field (Average is 0x2) */
> >> +               opmode &= ~(0x18);
> >> +               opmode |= (0x2 << 0x3);
> >> +               /* Co-site horizontal coefficients */
> >> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_0,
> >> +                               cosite_h_coeff[0]);
> >> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_1,
> >> +                               cosite_h_coeff[1]);
> >> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_2,
> >> +                               cosite_h_coeff[2]);
> >> +               break;
> >> +       case CDM_CDWN_OFFSITE:
> >> +               /* Clear METHOD_H field (Average is 0x3) */
> >> +               opmode &= ~(0x18);
> >> +               opmode |= (0x3 << 0x3);
> >> +
> >> +               /* Off-site horizontal coefficients */
> >> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_0,
> >> +                               offsite_h_coeff[0]);
> >> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_1,
> >> +                               offsite_h_coeff[1]);
> >> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_2,
> >> +                               offsite_h_coeff[2]);
> >> +               break;
> >> +       default:
> >> +               pr_err("%s invalid horz down sampling type\n", __func__);
> >> +               return -EINVAL;
> >> +       }
> >> +
> >> +       /* ENABLE DWNS_V bit */
> >> +       opmode |= BIT(2);
> >> +
> >> +       switch (cfg->v_cdwn_type) {
> >> +       case CDM_CDWN_DISABLE:
> >> +               /* CLEAR METHOD_V field */
> >> +               opmode &= ~(0x60);
> >
> > #define, GENMASK
> >
> >> +               /* CLEAR DWNS_V bit */
> >> +               opmode &= ~BIT(2);
> >> +               break;
> >> +       case CDM_CDWN_PIXEL_DROP:
> >> +               /* Clear METHOD_V field (pixel drop is 0) */
> >> +               opmode &= ~(0x60);
> >> +               break;
> >> +       case CDM_CDWN_AVG:
> >> +               /* Clear METHOD_V field (Average is 0x1) */
> >> +               opmode &= ~(0x60);
> >> +               opmode |= (0x1 << 0x5);
> >
> > #define
> >
> >> +               break;
> >> +       case CDM_CDWN_COSITE:
> >> +               /* Clear METHOD_V field (Average is 0x2) */
> >> +               opmode &= ~(0x60);
> >> +               opmode |= (0x2 << 0x5);
> >> +               /* Co-site vertical coefficients */
> >> +               DPU_REG_WRITE(c,
> >> +                               CDM_CDWN2_COEFF_COSITE_V,
> >> +                               cosite_v_coeff[0]);
> >
> > align to opening bracket
> >
> >> +               break;
> >> +       case CDM_CDWN_OFFSITE:
> >> +               /* Clear METHOD_V field (Average is 0x3) */
> >> +               opmode &= ~(0x60);
> >> +               opmode |= (0x3 << 0x5);
> >> +
> >> +               /* Off-site vertical coefficients */
> >> +               DPU_REG_WRITE(c,
> >> +                               CDM_CDWN2_COEFF_OFFSITE_V,
> >> +                               offsite_v_coeff[0]);
> >
> > align to opening bracket
> >
> >> +               break;
> >> +       default:
> >> +               return -EINVAL;
> >> +       }
> >> +
> >> +       if (cfg->v_cdwn_type || cfg->h_cdwn_type)
> >> +               opmode |= BIT(0); /* EN CDWN module */
> >
> > #define
> >
>
> Ack to all comments about GENMASK and #define
>
> >> +       else
> >> +               opmode &= ~BIT(0);
> >> +
> >> +       out_size = (cfg->output_width & 0xFFFF) |
> >> +               ((cfg->output_height & 0xFFFF) << 16);
> >> +       DPU_REG_WRITE(c, CDM_CDWN2_OUT_SIZE, out_size);
> >> +       DPU_REG_WRITE(c, CDM_CDWN2_OP_MODE, opmode);
> >> +       DPU_REG_WRITE(c, CDM_CDWN2_CLAMP_OUT,
> >> +                       ((0x3FF << 16) | 0x0));
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +int dpu_hw_cdm_enable(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cdm)
> >> +{
> >> +       struct dpu_hw_blk_reg_map *c = &ctx->hw;
> >> +       const struct dpu_format *fmt;
> >> +       u32 opmode = 0;
> >> +       u32 csc = 0;
> >> +
> >> +       if (!ctx || !cdm)
> >> +               return -EINVAL;
> >> +
> >> +       fmt = cdm->output_fmt;
> >> +
> >> +       if (!DPU_FORMAT_IS_YUV(fmt))
> >> +               return -EINVAL;
> >> +
> >> +       if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
> >> +               if (fmt->chroma_sample != DPU_CHROMA_H1V2)
> >> +                       return -EINVAL; /*unsupported format */
> >> +               opmode = BIT(0);
> >> +               opmode |= (fmt->chroma_sample << 1);
> >> +       }
> >> +
> >> +       csc |= BIT(2);
> >> +       csc &= ~BIT(1);
> >> +       csc |= BIT(0);
> >
> > Can we get some sensible #defines for all this magic, please?
> >
>
> Ack, will do.
>
> >> +
> >> +       if (ctx && ctx->ops.bind_pingpong_blk)
> >> +               ctx->ops.bind_pingpong_blk(ctx, true,
> >> +                               cdm->pp_id);
> >> +
> >> +       DPU_REG_WRITE(c, CDM_CSC_10_OPMODE, csc);
> >> +       DPU_REG_WRITE(c, CDM_HDMI_PACK_OP_MODE, opmode);
> >> +       return 0;
> >> +}
> >> +
> >> +void dpu_hw_cdm_disable(struct dpu_hw_cdm *ctx)
> >> +{
> >> +       if (!ctx)
> >> +               return;
> >> +
> >> +       if (ctx && ctx->ops.bind_pingpong_blk)
> >> +               ctx->ops.bind_pingpong_blk(ctx, false, 0);
> >
> > PINGPONG_NONE.
> >
> >> +}
> >> +
> >> +static void dpu_hw_cdm_bind_pingpong_blk(struct dpu_hw_cdm *ctx, bool enable,
> >> +                                        const enum dpu_pingpong pp)
> >> +{
> >> +       struct dpu_hw_blk_reg_map *c;
> >> +       int mux_cfg = 0xF;
> >> +
> >> +       if (!ctx || (enable && (pp < PINGPONG_0 || pp >= PINGPONG_MAX)))
> >> +               return;
> >
> > I'd say, this is useless. We don't have such checks in other
> > bind_pingpong_blk() callbacks.
> >
> > Also there should be a guarding check for DPU >= 5.0 either here or at
> > the ops init.
> >
>
> Will add it at ops init
>
> >> +
> >> +       c = &ctx->hw;
> >> +
> >> +       if (enable)
> >> +               mux_cfg = (pp - PINGPONG_0) & 0x7;
> >> +
> >> +       DPU_REG_WRITE(c, CDM_MUX, mux_cfg);
> >> +}
> >> +
> >> +static void _setup_cdm_ops(struct dpu_hw_cdm_ops *ops, unsigned long features)
> >
> > Please inline
> >
>
> OK
>
> >> +{
> >> +       ops->setup_csc_data = dpu_hw_cdm_setup_csc_10bit;
> >> +       ops->setup_cdwn = dpu_hw_cdm_setup_cdwn;
> >> +       ops->enable = dpu_hw_cdm_enable;
> >> +       ops->disable = dpu_hw_cdm_disable;
> >> +       ops->bind_pingpong_blk = dpu_hw_cdm_bind_pingpong_blk;
> >
> > As you seem to call this function directly, we might as well drop the
> > callback from the ops.
> >
>
> There are two paths for the bind_pingpong_blk(). One is absorbed within
> cdm_enable and cdm_disable calls to bind and unbind the pingpong resp.
> And yes, for that we dont need a separate ops as its within the same file.
>
> This will handle cases where we transition from YUV to non-YUV cases and
> vice-versa without an encoder disable in between which I believe happens
> in the IGT cases.
>
> But the dpu_encoder_helper_phys_cleanup() path is only in the encoder
> disable() path without a non-YUV frame in the middle so lets say we were
> in YUV mode but then just disabled the encoder we do need the cleanup
> there and since thats outside of the dpu_hw_cdm, we do need this op.
>
> I agree we need to protect this with the DPU revision check.
>
> >> +}
> >> +
> >> +struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cfg, void __iomem *addr)
> >> +{
> >> +       struct dpu_hw_cdm *c;
> >> +
> >> +       c = kzalloc(sizeof(*c), GFP_KERNEL);
> >> +       if (!c)
> >> +               return ERR_PTR(-ENOMEM);
> >> +
> >> +       c->hw.blk_addr = addr + cfg->base;
> >> +       c->hw.log_mask = DPU_DBG_MASK_CDM;
> >> +
> >> +       /* Assign ops */
> >> +       c->idx = cfg->id;
> >> +       c->caps = cfg;
> >> +       _setup_cdm_ops(&c->ops, c->caps->features);
> >> +
> >> +       return c;
> >> +}
> >> +
> >> +void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm)
> >> +{
> >> +       kfree(cdm);
> >
> > I'd prefer not to introduce another manual kzalloc/kfree pair, see
> > https://patchwork.freedesktop.org/series/120366/
> >
>
> I recall I did not want to have a manual kzalloc/kfree pair. But the
> issue was I think this series was not merged that time (and is isnt
> merged now either)

No response, no reviews since 15th August. Today is the 1st of December.

I'm close to deciding that unreviewed series have no issues and start
showing them to -next after a grace period of 1 month.

> and this is the one which passes drm_dev to
> dpu_rm_init. I thought maybe it was easier for you to absorb this change
> into that series instead of me pulling that whole series to make this
> one compile as we will not be adding new HW blocks after this for the
> next 2 cycles. It will only be using existing ones.
>
> If its too much trouble for you, I will rebase on top of that series but
> I am pretty sure you will have to rebase and post that again anyway on
> top of the current msm-next.
>
> I am also going to do the same thing now with this series.
>
> So we can just decide that in whose rebase we will handle it.
>
> >> +}
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
> >> new file mode 100644
> >> index 000000000000..da60893a5c02
> >> --- /dev/null
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
> >> @@ -0,0 +1,135 @@
> >> +/* SPDX-License-Identifier: GPL-2.0-only */
> >> +/*
> >> + * Copyright (c) 2023, The Linux Foundation. All rights reserved.
> >> + */
> >> +
> >> +#ifndef _DPU_HW_CDM_H
> >> +#define _DPU_HW_CDM_H
> >> +
> >> +#include "dpu_hw_mdss.h"
> >> +#include "dpu_hw_top.h"
> >> +
> >> +struct dpu_hw_cdm;
> >> +
> >> +struct dpu_hw_cdm_cfg {
> >> +       u32 output_width;
> >> +       u32 output_height;
> >> +       u32 output_bit_depth;
> >> +       u32 h_cdwn_type;
> >> +       u32 v_cdwn_type;
> >> +       const struct dpu_format *output_fmt;
> >> +       u32 output_type;
> >> +       int pp_id;
> >> +};
> >> +
> >> +enum dpu_hw_cdwn_type {
> >> +       CDM_CDWN_DISABLE,
> >> +       CDM_CDWN_PIXEL_DROP,
> >> +       CDM_CDWN_AVG,
> >> +       CDM_CDWN_COSITE,
> >> +       CDM_CDWN_OFFSITE,
> >> +};
> >> +
> >> +enum dpu_hw_cdwn_output_type {
> >> +       CDM_CDWN_OUTPUT_HDMI,
> >> +       CDM_CDWN_OUTPUT_WB,
> >> +};
> >> +
> >> +enum dpu_hw_cdwn_output_bit_depth {
> >> +       CDM_CDWN_OUTPUT_8BIT,
> >> +       CDM_CDWN_OUTPUT_10BIT,
> >> +};
> >> +
> >> +/**
> >> + * struct dpu_hw_cdm_ops : Interface to the chroma down Hw driver functions
> >> + *                         Assumption is these functions will be called after
> >> + *                         clocks are enabled
> >> + *  @setup_csc:            Programs the csc matrix
> >> + *  @setup_cdwn:           Sets up the chroma down sub module
> >> + *  @enable:               Enables the output to interface and programs the
> >> + *                         output packer
> >> + *  @disable:              Puts the cdm in bypass mode
> >> + *  @bind_pingpong_blk:    enable/disable the connection with pingpong which
> >> + *                         will feed pixels to this cdm
> >> + */
> >> +struct dpu_hw_cdm_ops {
> >> +       /**
> >> +        * Programs the CSC matrix for conversion from RGB space to YUV space,
> >> +        * it is optional to call this function as this matrix is automatically
> >> +        * set during initialization, user should call this if it wants
> >> +        * to program a different matrix than default matrix.
> >> +        * @cdm:          Pointer to the chroma down context structure
> >> +        * @data          Pointer to CSC configuration data
> >> +        * return:        0 if success; error code otherwise
> >> +        */
> >> +       int (*setup_csc_data)(struct dpu_hw_cdm *cdm, struct dpu_csc_cfg *data);
> >> +
> >> +       /**
> >> +        * Programs the Chroma downsample part.
> >> +        * @cdm         Pointer to chroma down context
> >> +        * @cfg         Pointer to the cdm configuration data
> >> +        */
> >> +       int (*setup_cdwn)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
> >> +
> >> +       /**
> >> +        * Enable the CDM module
> >> +        * @cdm         Pointer to chroma down context
> >> +        */
> >> +       int (*enable)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
> >> +
> >> +       /**
> >> +        * Disable the CDM module
> >> +        * @cdm         Pointer to chroma down context
> >> +        */
> >> +       void (*disable)(struct dpu_hw_cdm *cdm);
> >> +
> >> +       /**
> >> +        * Enable/disable the connection with pingpong
> >> +        * @cdm         Pointer to chroma down context
> >> +        * @enable      Enable/disable control
> >> +        * @pp          pingpong block id.
> >> +        */
> >> +       void (*bind_pingpong_blk)(struct dpu_hw_cdm *cdm, bool enable,
> >> +                                 const enum dpu_pingpong pp);
> >> +};
> >> +
> >> +/**
> >> + * struct dpu_hw_cdm - cdm description
> >> + * @base: Hardware block base structure
> >> + * @hw: Block hardware details
> >> + * @idx: CDM index
> >> + * @caps: Pointer to cdm_cfg
> >> + * @ops: handle to operations possible for this CDM
> >> + */
> >> +struct dpu_hw_cdm {
> >> +       struct dpu_hw_blk base;
> >> +       struct dpu_hw_blk_reg_map hw;
> >> +
> >> +       /* chroma down */
> >> +       const struct dpu_cdm_cfg *caps;
> >> +       enum  dpu_cdm  idx;
> >> +
> >> +       /* ops */
> >> +       struct dpu_hw_cdm_ops ops;
> >> +};
> >> +
> >> +/**
> >> + * dpu_hw_cdm_init - initializes the cdm hw driver object.
> >> + * should be called once before accessing every cdm.
> >> + * @cdm: CDM catalog entry for which driver object is required
> >> + * @addr :   mapped register io address of MDSS
> >> + */
> >> +struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cdm, void __iomem *addr);
> >> +
> >> +/**
> >> + * dpu_hw_cdm_destroy - destroys cdm driver context
> >> + * @cdm:   Pointer to cdm driver context returned by dpu_hw_cdm_init
> >> + */
> >> +void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm);
> >> +
> >> +static inline struct dpu_hw_cdm *to_dpu_hw_cdm(struct dpu_hw_blk *hw)
> >> +{
> >> +       return container_of(hw, struct dpu_hw_cdm, base);
> >> +}
> >> +
> >> +#endif /*_DPU_HW_CDM_H */
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >> index 4d6dba18caf0..34f943102499 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >> @@ -463,6 +463,7 @@ struct dpu_mdss_color {
> >>   #define DPU_DBG_MASK_ROT      (1 << 9)
> >>   #define DPU_DBG_MASK_DSPP     (1 << 10)
> >>   #define DPU_DBG_MASK_DSC      (1 << 11)
> >> +#define DPU_DBG_MASK_CDM      (1 << 12)
> >>
> >>   /**
> >>    * struct dpu_hw_tear_check - Struct contains parameters to configure
> >> --
> >> 2.40.1
> >>
> >
> >
> > --
> > With best wishes
> > Dmitry



-- 
With best wishes
Dmitry

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

* Re: [PATCH 06/16] drm/msm/dpu: add dpu_hw_cdm abstraction for CDM block
@ 2023-12-01  7:05         ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-12-01  7:05 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Fri, 1 Dec 2023 at 01:36, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 8/30/2023 5:00 PM, Dmitry Baryshkov wrote:
> > On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >> CDM block comes with its own set of registers and operations
> >> which can be done. In-line with other hardware sub-blocks, this
> >> change adds the dpu_hw_cdm abstraction for the CDM block.
> >>
> >> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> >> ---
> >>   drivers/gpu/drm/msm/Makefile                |   1 +
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c  | 272 ++++++++++++++++++++
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h  | 135 ++++++++++
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h |   1 +
> >>   4 files changed, 409 insertions(+)
> >>   create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
> >>   create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
> >>
> >> diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
> >> index 8d02d8c33069..2010cb1ca995 100644
> >> --- a/drivers/gpu/drm/msm/Makefile
> >> +++ b/drivers/gpu/drm/msm/Makefile
> >> @@ -63,6 +63,7 @@ msm-$(CONFIG_DRM_MSM_DPU) += \
> >>          disp/dpu1/dpu_encoder_phys_wb.o \
> >>          disp/dpu1/dpu_formats.o \
> >>          disp/dpu1/dpu_hw_catalog.o \
> >> +       disp/dpu1/dpu_hw_cdm.o \
> >>          disp/dpu1/dpu_hw_ctl.o \
> >>          disp/dpu1/dpu_hw_dsc.o \
> >>          disp/dpu1/dpu_hw_dsc_1_2.o \
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
> >> new file mode 100644
> >> index 000000000000..a2f7ee8f54e4
> >> --- /dev/null
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
> >> @@ -0,0 +1,272 @@
> >> +// SPDX-License-Identifier: GPL-2.0-only
> >> +/*
> >> + * Copyright (c) 2023, The Linux Foundation. All rights reserved.
> >> + */
> >> +
> >> +#include <drm/drm_managed.h>
> >> +
> >> +#include "dpu_hw_mdss.h"
> >> +#include "dpu_hw_util.h"
> >> +#include "dpu_hw_catalog.h"
> >> +#include "dpu_hw_cdm.h"
> >> +#include "dpu_kms.h"
> >> +
> >> +#define CDM_CSC_10_OPMODE                  0x000
> >> +#define CDM_CSC_10_BASE                    0x004
> >> +
> >> +#define CDM_CDWN2_OP_MODE                  0x100
> >> +#define CDM_CDWN2_CLAMP_OUT                0x104
> >> +#define CDM_CDWN2_PARAMS_3D_0              0x108
> >> +#define CDM_CDWN2_PARAMS_3D_1              0x10C
> >> +#define CDM_CDWN2_COEFF_COSITE_H_0         0x110
> >> +#define CDM_CDWN2_COEFF_COSITE_H_1         0x114
> >> +#define CDM_CDWN2_COEFF_COSITE_H_2         0x118
> >> +#define CDM_CDWN2_COEFF_OFFSITE_H_0        0x11C
> >> +#define CDM_CDWN2_COEFF_OFFSITE_H_1        0x120
> >> +#define CDM_CDWN2_COEFF_OFFSITE_H_2        0x124
> >> +#define CDM_CDWN2_COEFF_COSITE_V           0x128
> >> +#define CDM_CDWN2_COEFF_OFFSITE_V          0x12C
> >> +#define CDM_CDWN2_OUT_SIZE                 0x130
> >> +
> >> +#define CDM_HDMI_PACK_OP_MODE              0x200
> >> +#define CDM_CSC_10_MATRIX_COEFF_0          0x004
> >> +
> >> +#define CDM_MUX                            0x224
> >> +
> >> +/**
> >> + * Horizontal coefficients for cosite chroma downscale
> >> + * s13 representation of coefficients
> >> + */
> >> +static u32 cosite_h_coeff[] = {0x00000016, 0x000001cc, 0x0100009e};
> >> +
> >> +/**
> >> + * Horizontal coefficients for offsite chroma downscale
> >> + */
> >> +static u32 offsite_h_coeff[] = {0x000b0005, 0x01db01eb, 0x00e40046};
> >> +
> >> +/**
> >> + * Vertical coefficients for cosite chroma downscale
> >> + */
> >> +static u32 cosite_v_coeff[] = {0x00080004};
> >> +/**
> >> + * Vertical coefficients for offsite chroma downscale
> >> + */
> >> +static u32 offsite_v_coeff[] = {0x00060002};
> >> +
> >> +static int dpu_hw_cdm_setup_csc_10bit(struct dpu_hw_cdm *ctx, struct dpu_csc_cfg *data)
> >> +{
> >> +       dpu_hw_csc_setup(&ctx->hw, CDM_CSC_10_MATRIX_COEFF_0, data, true);
> >
> > Where was this defined?
> >
>
> Its in this file itself
>
> +#define CDM_CSC_10_MATRIX_COEFF_0          0x004
>
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static int dpu_hw_cdm_setup_cdwn(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cfg)
> >> +{
> >> +       struct dpu_hw_blk_reg_map *c = &ctx->hw;
> >> +       u32 opmode = 0;
> >> +       u32 out_size = 0;
> >> +
> >> +       if (cfg->output_bit_depth == CDM_CDWN_OUTPUT_10BIT)
> >> +               opmode &= ~BIT(7);
> >> +       else
> >> +               opmode |= BIT(7);
> >> +
> >> +       /* ENABLE DWNS_H bit */
> >> +       opmode |= BIT(1);
> >> +
> >> +       switch (cfg->h_cdwn_type) {
> >> +       case CDM_CDWN_DISABLE:
> >> +               /* CLEAR METHOD_H field */
> >> +               opmode &= ~(0x18);
> >> +               /* CLEAR DWNS_H bit */
> >> +               opmode &= ~BIT(1);
> >> +               break;
> >> +       case CDM_CDWN_PIXEL_DROP:
> >> +               /* Clear METHOD_H field (pixel drop is 0) */
> >> +               opmode &= ~(0x18);
> >> +               break;
> >> +       case CDM_CDWN_AVG:
> >> +               /* Clear METHOD_H field (Average is 0x1) */
> >> +               opmode &= ~(0x18);
> >> +               opmode |= (0x1 << 0x3);
> >> +               break;
> >> +       case CDM_CDWN_COSITE:
> >> +               /* Clear METHOD_H field (Average is 0x2) */
> >> +               opmode &= ~(0x18);
> >> +               opmode |= (0x2 << 0x3);
> >> +               /* Co-site horizontal coefficients */
> >> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_0,
> >> +                               cosite_h_coeff[0]);
> >> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_1,
> >> +                               cosite_h_coeff[1]);
> >> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_2,
> >> +                               cosite_h_coeff[2]);
> >> +               break;
> >> +       case CDM_CDWN_OFFSITE:
> >> +               /* Clear METHOD_H field (Average is 0x3) */
> >> +               opmode &= ~(0x18);
> >> +               opmode |= (0x3 << 0x3);
> >> +
> >> +               /* Off-site horizontal coefficients */
> >> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_0,
> >> +                               offsite_h_coeff[0]);
> >> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_1,
> >> +                               offsite_h_coeff[1]);
> >> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_2,
> >> +                               offsite_h_coeff[2]);
> >> +               break;
> >> +       default:
> >> +               pr_err("%s invalid horz down sampling type\n", __func__);
> >> +               return -EINVAL;
> >> +       }
> >> +
> >> +       /* ENABLE DWNS_V bit */
> >> +       opmode |= BIT(2);
> >> +
> >> +       switch (cfg->v_cdwn_type) {
> >> +       case CDM_CDWN_DISABLE:
> >> +               /* CLEAR METHOD_V field */
> >> +               opmode &= ~(0x60);
> >
> > #define, GENMASK
> >
> >> +               /* CLEAR DWNS_V bit */
> >> +               opmode &= ~BIT(2);
> >> +               break;
> >> +       case CDM_CDWN_PIXEL_DROP:
> >> +               /* Clear METHOD_V field (pixel drop is 0) */
> >> +               opmode &= ~(0x60);
> >> +               break;
> >> +       case CDM_CDWN_AVG:
> >> +               /* Clear METHOD_V field (Average is 0x1) */
> >> +               opmode &= ~(0x60);
> >> +               opmode |= (0x1 << 0x5);
> >
> > #define
> >
> >> +               break;
> >> +       case CDM_CDWN_COSITE:
> >> +               /* Clear METHOD_V field (Average is 0x2) */
> >> +               opmode &= ~(0x60);
> >> +               opmode |= (0x2 << 0x5);
> >> +               /* Co-site vertical coefficients */
> >> +               DPU_REG_WRITE(c,
> >> +                               CDM_CDWN2_COEFF_COSITE_V,
> >> +                               cosite_v_coeff[0]);
> >
> > align to opening bracket
> >
> >> +               break;
> >> +       case CDM_CDWN_OFFSITE:
> >> +               /* Clear METHOD_V field (Average is 0x3) */
> >> +               opmode &= ~(0x60);
> >> +               opmode |= (0x3 << 0x5);
> >> +
> >> +               /* Off-site vertical coefficients */
> >> +               DPU_REG_WRITE(c,
> >> +                               CDM_CDWN2_COEFF_OFFSITE_V,
> >> +                               offsite_v_coeff[0]);
> >
> > align to opening bracket
> >
> >> +               break;
> >> +       default:
> >> +               return -EINVAL;
> >> +       }
> >> +
> >> +       if (cfg->v_cdwn_type || cfg->h_cdwn_type)
> >> +               opmode |= BIT(0); /* EN CDWN module */
> >
> > #define
> >
>
> Ack to all comments about GENMASK and #define
>
> >> +       else
> >> +               opmode &= ~BIT(0);
> >> +
> >> +       out_size = (cfg->output_width & 0xFFFF) |
> >> +               ((cfg->output_height & 0xFFFF) << 16);
> >> +       DPU_REG_WRITE(c, CDM_CDWN2_OUT_SIZE, out_size);
> >> +       DPU_REG_WRITE(c, CDM_CDWN2_OP_MODE, opmode);
> >> +       DPU_REG_WRITE(c, CDM_CDWN2_CLAMP_OUT,
> >> +                       ((0x3FF << 16) | 0x0));
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +int dpu_hw_cdm_enable(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cdm)
> >> +{
> >> +       struct dpu_hw_blk_reg_map *c = &ctx->hw;
> >> +       const struct dpu_format *fmt;
> >> +       u32 opmode = 0;
> >> +       u32 csc = 0;
> >> +
> >> +       if (!ctx || !cdm)
> >> +               return -EINVAL;
> >> +
> >> +       fmt = cdm->output_fmt;
> >> +
> >> +       if (!DPU_FORMAT_IS_YUV(fmt))
> >> +               return -EINVAL;
> >> +
> >> +       if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
> >> +               if (fmt->chroma_sample != DPU_CHROMA_H1V2)
> >> +                       return -EINVAL; /*unsupported format */
> >> +               opmode = BIT(0);
> >> +               opmode |= (fmt->chroma_sample << 1);
> >> +       }
> >> +
> >> +       csc |= BIT(2);
> >> +       csc &= ~BIT(1);
> >> +       csc |= BIT(0);
> >
> > Can we get some sensible #defines for all this magic, please?
> >
>
> Ack, will do.
>
> >> +
> >> +       if (ctx && ctx->ops.bind_pingpong_blk)
> >> +               ctx->ops.bind_pingpong_blk(ctx, true,
> >> +                               cdm->pp_id);
> >> +
> >> +       DPU_REG_WRITE(c, CDM_CSC_10_OPMODE, csc);
> >> +       DPU_REG_WRITE(c, CDM_HDMI_PACK_OP_MODE, opmode);
> >> +       return 0;
> >> +}
> >> +
> >> +void dpu_hw_cdm_disable(struct dpu_hw_cdm *ctx)
> >> +{
> >> +       if (!ctx)
> >> +               return;
> >> +
> >> +       if (ctx && ctx->ops.bind_pingpong_blk)
> >> +               ctx->ops.bind_pingpong_blk(ctx, false, 0);
> >
> > PINGPONG_NONE.
> >
> >> +}
> >> +
> >> +static void dpu_hw_cdm_bind_pingpong_blk(struct dpu_hw_cdm *ctx, bool enable,
> >> +                                        const enum dpu_pingpong pp)
> >> +{
> >> +       struct dpu_hw_blk_reg_map *c;
> >> +       int mux_cfg = 0xF;
> >> +
> >> +       if (!ctx || (enable && (pp < PINGPONG_0 || pp >= PINGPONG_MAX)))
> >> +               return;
> >
> > I'd say, this is useless. We don't have such checks in other
> > bind_pingpong_blk() callbacks.
> >
> > Also there should be a guarding check for DPU >= 5.0 either here or at
> > the ops init.
> >
>
> Will add it at ops init
>
> >> +
> >> +       c = &ctx->hw;
> >> +
> >> +       if (enable)
> >> +               mux_cfg = (pp - PINGPONG_0) & 0x7;
> >> +
> >> +       DPU_REG_WRITE(c, CDM_MUX, mux_cfg);
> >> +}
> >> +
> >> +static void _setup_cdm_ops(struct dpu_hw_cdm_ops *ops, unsigned long features)
> >
> > Please inline
> >
>
> OK
>
> >> +{
> >> +       ops->setup_csc_data = dpu_hw_cdm_setup_csc_10bit;
> >> +       ops->setup_cdwn = dpu_hw_cdm_setup_cdwn;
> >> +       ops->enable = dpu_hw_cdm_enable;
> >> +       ops->disable = dpu_hw_cdm_disable;
> >> +       ops->bind_pingpong_blk = dpu_hw_cdm_bind_pingpong_blk;
> >
> > As you seem to call this function directly, we might as well drop the
> > callback from the ops.
> >
>
> There are two paths for the bind_pingpong_blk(). One is absorbed within
> cdm_enable and cdm_disable calls to bind and unbind the pingpong resp.
> And yes, for that we dont need a separate ops as its within the same file.
>
> This will handle cases where we transition from YUV to non-YUV cases and
> vice-versa without an encoder disable in between which I believe happens
> in the IGT cases.
>
> But the dpu_encoder_helper_phys_cleanup() path is only in the encoder
> disable() path without a non-YUV frame in the middle so lets say we were
> in YUV mode but then just disabled the encoder we do need the cleanup
> there and since thats outside of the dpu_hw_cdm, we do need this op.
>
> I agree we need to protect this with the DPU revision check.
>
> >> +}
> >> +
> >> +struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cfg, void __iomem *addr)
> >> +{
> >> +       struct dpu_hw_cdm *c;
> >> +
> >> +       c = kzalloc(sizeof(*c), GFP_KERNEL);
> >> +       if (!c)
> >> +               return ERR_PTR(-ENOMEM);
> >> +
> >> +       c->hw.blk_addr = addr + cfg->base;
> >> +       c->hw.log_mask = DPU_DBG_MASK_CDM;
> >> +
> >> +       /* Assign ops */
> >> +       c->idx = cfg->id;
> >> +       c->caps = cfg;
> >> +       _setup_cdm_ops(&c->ops, c->caps->features);
> >> +
> >> +       return c;
> >> +}
> >> +
> >> +void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm)
> >> +{
> >> +       kfree(cdm);
> >
> > I'd prefer not to introduce another manual kzalloc/kfree pair, see
> > https://patchwork.freedesktop.org/series/120366/
> >
>
> I recall I did not want to have a manual kzalloc/kfree pair. But the
> issue was I think this series was not merged that time (and is isnt
> merged now either)

No response, no reviews since 15th August. Today is the 1st of December.

I'm close to deciding that unreviewed series have no issues and start
showing them to -next after a grace period of 1 month.

> and this is the one which passes drm_dev to
> dpu_rm_init. I thought maybe it was easier for you to absorb this change
> into that series instead of me pulling that whole series to make this
> one compile as we will not be adding new HW blocks after this for the
> next 2 cycles. It will only be using existing ones.
>
> If its too much trouble for you, I will rebase on top of that series but
> I am pretty sure you will have to rebase and post that again anyway on
> top of the current msm-next.
>
> I am also going to do the same thing now with this series.
>
> So we can just decide that in whose rebase we will handle it.
>
> >> +}
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
> >> new file mode 100644
> >> index 000000000000..da60893a5c02
> >> --- /dev/null
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
> >> @@ -0,0 +1,135 @@
> >> +/* SPDX-License-Identifier: GPL-2.0-only */
> >> +/*
> >> + * Copyright (c) 2023, The Linux Foundation. All rights reserved.
> >> + */
> >> +
> >> +#ifndef _DPU_HW_CDM_H
> >> +#define _DPU_HW_CDM_H
> >> +
> >> +#include "dpu_hw_mdss.h"
> >> +#include "dpu_hw_top.h"
> >> +
> >> +struct dpu_hw_cdm;
> >> +
> >> +struct dpu_hw_cdm_cfg {
> >> +       u32 output_width;
> >> +       u32 output_height;
> >> +       u32 output_bit_depth;
> >> +       u32 h_cdwn_type;
> >> +       u32 v_cdwn_type;
> >> +       const struct dpu_format *output_fmt;
> >> +       u32 output_type;
> >> +       int pp_id;
> >> +};
> >> +
> >> +enum dpu_hw_cdwn_type {
> >> +       CDM_CDWN_DISABLE,
> >> +       CDM_CDWN_PIXEL_DROP,
> >> +       CDM_CDWN_AVG,
> >> +       CDM_CDWN_COSITE,
> >> +       CDM_CDWN_OFFSITE,
> >> +};
> >> +
> >> +enum dpu_hw_cdwn_output_type {
> >> +       CDM_CDWN_OUTPUT_HDMI,
> >> +       CDM_CDWN_OUTPUT_WB,
> >> +};
> >> +
> >> +enum dpu_hw_cdwn_output_bit_depth {
> >> +       CDM_CDWN_OUTPUT_8BIT,
> >> +       CDM_CDWN_OUTPUT_10BIT,
> >> +};
> >> +
> >> +/**
> >> + * struct dpu_hw_cdm_ops : Interface to the chroma down Hw driver functions
> >> + *                         Assumption is these functions will be called after
> >> + *                         clocks are enabled
> >> + *  @setup_csc:            Programs the csc matrix
> >> + *  @setup_cdwn:           Sets up the chroma down sub module
> >> + *  @enable:               Enables the output to interface and programs the
> >> + *                         output packer
> >> + *  @disable:              Puts the cdm in bypass mode
> >> + *  @bind_pingpong_blk:    enable/disable the connection with pingpong which
> >> + *                         will feed pixels to this cdm
> >> + */
> >> +struct dpu_hw_cdm_ops {
> >> +       /**
> >> +        * Programs the CSC matrix for conversion from RGB space to YUV space,
> >> +        * it is optional to call this function as this matrix is automatically
> >> +        * set during initialization, user should call this if it wants
> >> +        * to program a different matrix than default matrix.
> >> +        * @cdm:          Pointer to the chroma down context structure
> >> +        * @data          Pointer to CSC configuration data
> >> +        * return:        0 if success; error code otherwise
> >> +        */
> >> +       int (*setup_csc_data)(struct dpu_hw_cdm *cdm, struct dpu_csc_cfg *data);
> >> +
> >> +       /**
> >> +        * Programs the Chroma downsample part.
> >> +        * @cdm         Pointer to chroma down context
> >> +        * @cfg         Pointer to the cdm configuration data
> >> +        */
> >> +       int (*setup_cdwn)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
> >> +
> >> +       /**
> >> +        * Enable the CDM module
> >> +        * @cdm         Pointer to chroma down context
> >> +        */
> >> +       int (*enable)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
> >> +
> >> +       /**
> >> +        * Disable the CDM module
> >> +        * @cdm         Pointer to chroma down context
> >> +        */
> >> +       void (*disable)(struct dpu_hw_cdm *cdm);
> >> +
> >> +       /**
> >> +        * Enable/disable the connection with pingpong
> >> +        * @cdm         Pointer to chroma down context
> >> +        * @enable      Enable/disable control
> >> +        * @pp          pingpong block id.
> >> +        */
> >> +       void (*bind_pingpong_blk)(struct dpu_hw_cdm *cdm, bool enable,
> >> +                                 const enum dpu_pingpong pp);
> >> +};
> >> +
> >> +/**
> >> + * struct dpu_hw_cdm - cdm description
> >> + * @base: Hardware block base structure
> >> + * @hw: Block hardware details
> >> + * @idx: CDM index
> >> + * @caps: Pointer to cdm_cfg
> >> + * @ops: handle to operations possible for this CDM
> >> + */
> >> +struct dpu_hw_cdm {
> >> +       struct dpu_hw_blk base;
> >> +       struct dpu_hw_blk_reg_map hw;
> >> +
> >> +       /* chroma down */
> >> +       const struct dpu_cdm_cfg *caps;
> >> +       enum  dpu_cdm  idx;
> >> +
> >> +       /* ops */
> >> +       struct dpu_hw_cdm_ops ops;
> >> +};
> >> +
> >> +/**
> >> + * dpu_hw_cdm_init - initializes the cdm hw driver object.
> >> + * should be called once before accessing every cdm.
> >> + * @cdm: CDM catalog entry for which driver object is required
> >> + * @addr :   mapped register io address of MDSS
> >> + */
> >> +struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cdm, void __iomem *addr);
> >> +
> >> +/**
> >> + * dpu_hw_cdm_destroy - destroys cdm driver context
> >> + * @cdm:   Pointer to cdm driver context returned by dpu_hw_cdm_init
> >> + */
> >> +void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm);
> >> +
> >> +static inline struct dpu_hw_cdm *to_dpu_hw_cdm(struct dpu_hw_blk *hw)
> >> +{
> >> +       return container_of(hw, struct dpu_hw_cdm, base);
> >> +}
> >> +
> >> +#endif /*_DPU_HW_CDM_H */
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >> index 4d6dba18caf0..34f943102499 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >> @@ -463,6 +463,7 @@ struct dpu_mdss_color {
> >>   #define DPU_DBG_MASK_ROT      (1 << 9)
> >>   #define DPU_DBG_MASK_DSPP     (1 << 10)
> >>   #define DPU_DBG_MASK_DSC      (1 << 11)
> >> +#define DPU_DBG_MASK_CDM      (1 << 12)
> >>
> >>   /**
> >>    * struct dpu_hw_tear_check - Struct contains parameters to configure
> >> --
> >> 2.40.1
> >>
> >
> >
> > --
> > With best wishes
> > Dmitry



-- 
With best wishes
Dmitry

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

* Re: [PATCH 14/16] drm/msm/dpu: do not allow YUV formats if no CDM block is present
  2023-12-01  0:50       ` Abhinav Kumar
@ 2023-12-01  7:14         ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-12-01  7:14 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel

On Fri, 1 Dec 2023 at 02:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 8/30/2023 5:24 PM, Dmitry Baryshkov wrote:
> > On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >> On chipsets where CDM block is not available OR where support has
> >> not been added yet do not allow YUV formats for writeback block.
> >>
> >> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> >> ---
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 6 ++++++
> >>   1 file changed, 6 insertions(+)
> >>
> >> 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 7fc174b33ae2..d8edca9bc964 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
> >> @@ -406,6 +406,12 @@ static int dpu_encoder_phys_wb_atomic_check(
> >>                  return ret;
> >>          }
> >>
> >> +       if (DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(fb))) &&
> >> +           !phys_enc->dpu_kms->catalog->cdm) {
> >> +               DPU_ERROR("cannot support YUV formats without CDM block\n");
> >> +               return -EINVAL;
> >> +       }
> >
> > Can we have YUV formats in wb_formats if we do not support CDM? That
> > would be an error.
>
> I can drop this one once i address the comments on the next patch.
>
> Yeah the reason for this change was we had one formats array for wb and
> were using that for all chipsets. We can have two arrays : one only rgb
> and the other rgb+yuv to address this.

Yes, this sounds fine to me.



-- 
With best wishes
Dmitry

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

* Re: [PATCH 14/16] drm/msm/dpu: do not allow YUV formats if no CDM block is present
@ 2023-12-01  7:14         ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-12-01  7:14 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Fri, 1 Dec 2023 at 02:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 8/30/2023 5:24 PM, Dmitry Baryshkov wrote:
> > On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >> On chipsets where CDM block is not available OR where support has
> >> not been added yet do not allow YUV formats for writeback block.
> >>
> >> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> >> ---
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 6 ++++++
> >>   1 file changed, 6 insertions(+)
> >>
> >> 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 7fc174b33ae2..d8edca9bc964 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
> >> @@ -406,6 +406,12 @@ static int dpu_encoder_phys_wb_atomic_check(
> >>                  return ret;
> >>          }
> >>
> >> +       if (DPU_FORMAT_IS_YUV(to_dpu_format(msm_framebuffer_format(fb))) &&
> >> +           !phys_enc->dpu_kms->catalog->cdm) {
> >> +               DPU_ERROR("cannot support YUV formats without CDM block\n");
> >> +               return -EINVAL;
> >> +       }
> >
> > Can we have YUV formats in wb_formats if we do not support CDM? That
> > would be an error.
>
> I can drop this one once i address the comments on the next patch.
>
> Yeah the reason for this change was we had one formats array for wb and
> were using that for all chipsets. We can have two arrays : one only rgb
> and the other rgb+yuv to address this.

Yes, this sounds fine to me.



-- 
With best wishes
Dmitry

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

* Re: [PATCH 11/16] drm/msm/dpu: add an API to setup the CDM block for writeback
  2023-12-01  0:41       ` Abhinav Kumar
@ 2023-12-01  7:20         ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-12-01  7:20 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel

On Fri, 1 Dec 2023 at 02:41, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 8/30/2023 5:11 PM, Dmitry Baryshkov wrote:
> > On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >> Add an API dpu_encoder_helper_phys_setup_cdm() which can be used by
> >> the writeback encoder to setup the CDM block.
> >>
> >> Currently, this is defined and used within the writeback's physical
> >> encoder layer however, the function can be modified to be used to setup
> >> the CDM block even for non-writeback interfaces.
> >>
> >> Until those modifications are planned and made, keep it local to
> >> writeback.
> >>
> >> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> >> ---
> >>   .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   3 +
> >>   .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 123 +++++++++++++++++-
> >>   2 files changed, 125 insertions(+), 1 deletion(-)
> >>
> >> 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 510c1c41ddbc..93a8ae67beff 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >> @@ -16,6 +16,7 @@
> >>   #include "dpu_hw_pingpong.h"
> >>   #include "dpu_hw_ctl.h"
> >>   #include "dpu_hw_top.h"
> >> +#include "dpu_hw_cdm.h"
> >>   #include "dpu_encoder.h"
> >>   #include "dpu_crtc.h"
> >>
> >> @@ -209,6 +210,7 @@ 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
> >> @@ -218,6 +220,7 @@ 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 4c2736c3ee6d..11935aac9fd5 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
> >> @@ -24,6 +24,20 @@
> >>   #define to_dpu_encoder_phys_wb(x) \
> >>          container_of(x, struct dpu_encoder_phys_wb, base)
> >>
> >> +#define TO_S15D16(_x_)((_x_) << 7)
> >> +
> >> +static struct dpu_csc_cfg dpu_encoder_phys_wb_rgb2yuv_601l = {
> >> +       {
> >> +               TO_S15D16(0x0083), TO_S15D16(0x0102), TO_S15D16(0x0032),
> >> +               TO_S15D16(0x1fb5), TO_S15D16(0x1f6c), TO_S15D16(0x00e1),
> >> +               TO_S15D16(0x00e1), TO_S15D16(0x1f45), TO_S15D16(0x1fdc)
> >> +       },
> >> +       { 0x00, 0x00, 0x00 },
> >> +       { 0x0040, 0x0200, 0x0200 },
> >> +       { 0x000, 0x3ff, 0x000, 0x3ff, 0x000, 0x3ff },
> >> +       { 0x040, 0x3ac, 0x040, 0x3c0, 0x040, 0x3c0 },
> >> +};
> >
> > Nit: we probably need to have a single place with all dpu_csc_cfg entries.
> >
>
> hmmm ... so we have YUV2RGB matrices for dpu plane and RGB2YUV matrices
> for WB and DP.
>
> We can move all this to dpu_hw_util.c but lets do that in the DP series
> as that completes the consumer list of these matrices.

Doing it earlier is usually better. Can we please do it as a part of
this series?

>
> >> +
> >>   /**
> >>    * dpu_encoder_phys_wb_is_master - report wb always as master encoder
> >>    * @phys_enc:  Pointer to physical encoder
> >> @@ -225,6 +239,112 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
> >>          }
> >>   }
> >>
> >> +/**
> >> + * dpu_encoder_phys_wb_setup_cdp - setup chroma down sampling block
> >> + * @phys_enc:Pointer to physical encoder
> >> + */
> >> +static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
> >> +{
> >> +       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;
> >> +       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;
> >> +
> >> +       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.disable)
> >> +                       hw_cdm->ops.disable(hw_cdm);
> >> +
> >> +               return;
> >> +       }
> >> +
> >> +       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_fmt = dpu_fmt;
> >> +       cdm_cfg->output_type = CDM_CDWN_OUTPUT_WB;
> >> +       cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
> >> +                       CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
> >> +
> >> +       /* 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 && hw_cdm->ops.setup_csc_data) {
> >> +               ret = hw_cdm->ops.setup_csc_data(hw_cdm, &dpu_encoder_phys_wb_rgb2yuv_601l);
> >> +               if (ret < 0) {
> >> +                       DPU_ERROR("[enc:%d] failed to setup CSC; ret:%d\n",
> >> +                                 DRMID(phys_enc->parent), ret);
> >> +                       return;
> >> +               }
> >> +       }
> >> +
> >> +       if (hw_cdm && hw_cdm->ops.setup_cdwn) {
> >
> > You have checked for (!hw_cdm) several lines above. We can drop this
> > condition here.
> >
>
> Ack.
>
> >> +               ret = hw_cdm->ops.setup_cdwn(hw_cdm, cdm_cfg);
> >> +               if (ret < 0) {
> >> +                       DPU_ERROR("[enc:%d] failed to setup CDWN; ret:%d\n",
> >> +                                 DRMID(phys_enc->parent), ret);
> >> +                       return;
> >> +               }
> >> +       }
> >> +
> >> +       if (hw_cdm && hw_pp && hw_cdm->ops.enable) {
> >
> > And what if !hw_pp ? Can it happen here? No, if I understand correctly.
> >
>
> I dont see any other protection for !hw_pp in this flow so would prefer
> to keep it.

But can we end up in this function if we have no hw_pp at all?

>
> >> +               cdm_cfg->pp_id = hw_pp->idx;
> >> +               ret = hw_cdm->ops.enable(hw_cdm, cdm_cfg);
> >
> > As we are calling these three ops in a row, can we merge them together
> > into a single callback to be called from dpu_encoder.c?
> >
>
> Good idea. I can add a csc_cfg entry to cdm_cfg and merge all three into
> the enable() op itself and drop the other two.
>
> >> +               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
> >> @@ -348,8 +468,9 @@ static void dpu_encoder_phys_wb_setup(
> >>
> >>          dpu_encoder_phys_wb_setup_fb(phys_enc, fb);
> >>
> >> -       dpu_encoder_phys_wb_setup_ctl(phys_enc);
> >> +       dpu_encoder_helper_phys_setup_cdm(phys_enc);
> >>
> >> +       dpu_encoder_phys_wb_setup_ctl(phys_enc);
> >>   }
> >>
> >>   static void _dpu_encoder_phys_wb_frame_done_helper(void *arg)
> >> --
> >> 2.40.1
> >>
> >
> >



-- 
With best wishes
Dmitry

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

* Re: [PATCH 11/16] drm/msm/dpu: add an API to setup the CDM block for writeback
@ 2023-12-01  7:20         ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-12-01  7:20 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Fri, 1 Dec 2023 at 02:41, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 8/30/2023 5:11 PM, Dmitry Baryshkov wrote:
> > On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >> Add an API dpu_encoder_helper_phys_setup_cdm() which can be used by
> >> the writeback encoder to setup the CDM block.
> >>
> >> Currently, this is defined and used within the writeback's physical
> >> encoder layer however, the function can be modified to be used to setup
> >> the CDM block even for non-writeback interfaces.
> >>
> >> Until those modifications are planned and made, keep it local to
> >> writeback.
> >>
> >> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> >> ---
> >>   .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   3 +
> >>   .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 123 +++++++++++++++++-
> >>   2 files changed, 125 insertions(+), 1 deletion(-)
> >>
> >> 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 510c1c41ddbc..93a8ae67beff 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >> @@ -16,6 +16,7 @@
> >>   #include "dpu_hw_pingpong.h"
> >>   #include "dpu_hw_ctl.h"
> >>   #include "dpu_hw_top.h"
> >> +#include "dpu_hw_cdm.h"
> >>   #include "dpu_encoder.h"
> >>   #include "dpu_crtc.h"
> >>
> >> @@ -209,6 +210,7 @@ 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
> >> @@ -218,6 +220,7 @@ 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 4c2736c3ee6d..11935aac9fd5 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
> >> @@ -24,6 +24,20 @@
> >>   #define to_dpu_encoder_phys_wb(x) \
> >>          container_of(x, struct dpu_encoder_phys_wb, base)
> >>
> >> +#define TO_S15D16(_x_)((_x_) << 7)
> >> +
> >> +static struct dpu_csc_cfg dpu_encoder_phys_wb_rgb2yuv_601l = {
> >> +       {
> >> +               TO_S15D16(0x0083), TO_S15D16(0x0102), TO_S15D16(0x0032),
> >> +               TO_S15D16(0x1fb5), TO_S15D16(0x1f6c), TO_S15D16(0x00e1),
> >> +               TO_S15D16(0x00e1), TO_S15D16(0x1f45), TO_S15D16(0x1fdc)
> >> +       },
> >> +       { 0x00, 0x00, 0x00 },
> >> +       { 0x0040, 0x0200, 0x0200 },
> >> +       { 0x000, 0x3ff, 0x000, 0x3ff, 0x000, 0x3ff },
> >> +       { 0x040, 0x3ac, 0x040, 0x3c0, 0x040, 0x3c0 },
> >> +};
> >
> > Nit: we probably need to have a single place with all dpu_csc_cfg entries.
> >
>
> hmmm ... so we have YUV2RGB matrices for dpu plane and RGB2YUV matrices
> for WB and DP.
>
> We can move all this to dpu_hw_util.c but lets do that in the DP series
> as that completes the consumer list of these matrices.

Doing it earlier is usually better. Can we please do it as a part of
this series?

>
> >> +
> >>   /**
> >>    * dpu_encoder_phys_wb_is_master - report wb always as master encoder
> >>    * @phys_enc:  Pointer to physical encoder
> >> @@ -225,6 +239,112 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
> >>          }
> >>   }
> >>
> >> +/**
> >> + * dpu_encoder_phys_wb_setup_cdp - setup chroma down sampling block
> >> + * @phys_enc:Pointer to physical encoder
> >> + */
> >> +static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
> >> +{
> >> +       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;
> >> +       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;
> >> +
> >> +       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.disable)
> >> +                       hw_cdm->ops.disable(hw_cdm);
> >> +
> >> +               return;
> >> +       }
> >> +
> >> +       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_fmt = dpu_fmt;
> >> +       cdm_cfg->output_type = CDM_CDWN_OUTPUT_WB;
> >> +       cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
> >> +                       CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
> >> +
> >> +       /* 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 && hw_cdm->ops.setup_csc_data) {
> >> +               ret = hw_cdm->ops.setup_csc_data(hw_cdm, &dpu_encoder_phys_wb_rgb2yuv_601l);
> >> +               if (ret < 0) {
> >> +                       DPU_ERROR("[enc:%d] failed to setup CSC; ret:%d\n",
> >> +                                 DRMID(phys_enc->parent), ret);
> >> +                       return;
> >> +               }
> >> +       }
> >> +
> >> +       if (hw_cdm && hw_cdm->ops.setup_cdwn) {
> >
> > You have checked for (!hw_cdm) several lines above. We can drop this
> > condition here.
> >
>
> Ack.
>
> >> +               ret = hw_cdm->ops.setup_cdwn(hw_cdm, cdm_cfg);
> >> +               if (ret < 0) {
> >> +                       DPU_ERROR("[enc:%d] failed to setup CDWN; ret:%d\n",
> >> +                                 DRMID(phys_enc->parent), ret);
> >> +                       return;
> >> +               }
> >> +       }
> >> +
> >> +       if (hw_cdm && hw_pp && hw_cdm->ops.enable) {
> >
> > And what if !hw_pp ? Can it happen here? No, if I understand correctly.
> >
>
> I dont see any other protection for !hw_pp in this flow so would prefer
> to keep it.

But can we end up in this function if we have no hw_pp at all?

>
> >> +               cdm_cfg->pp_id = hw_pp->idx;
> >> +               ret = hw_cdm->ops.enable(hw_cdm, cdm_cfg);
> >
> > As we are calling these three ops in a row, can we merge them together
> > into a single callback to be called from dpu_encoder.c?
> >
>
> Good idea. I can add a csc_cfg entry to cdm_cfg and merge all three into
> the enable() op itself and drop the other two.
>
> >> +               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
> >> @@ -348,8 +468,9 @@ static void dpu_encoder_phys_wb_setup(
> >>
> >>          dpu_encoder_phys_wb_setup_fb(phys_enc, fb);
> >>
> >> -       dpu_encoder_phys_wb_setup_ctl(phys_enc);
> >> +       dpu_encoder_helper_phys_setup_cdm(phys_enc);
> >>
> >> +       dpu_encoder_phys_wb_setup_ctl(phys_enc);
> >>   }
> >>
> >>   static void _dpu_encoder_phys_wb_frame_done_helper(void *arg)
> >> --
> >> 2.40.1
> >>
> >
> >



-- 
With best wishes
Dmitry

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

* Re: [PATCH 10/16] drm/msm/dpu: add support to disable CDM block during encoder cleanup
  2023-11-30 23:58       ` Abhinav Kumar
@ 2023-12-01  8:36         ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-12-01  8:36 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel

On Fri, 1 Dec 2023 at 01:58, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 8/30/2023 5:14 PM, Dmitry Baryshkov wrote:
> > On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >> In preparation of setting up CDM block, add the logic to disable it
> >> properly during encoder cleanup.
> >>
> >> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> >> ---
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c      | 8 ++++++++
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 2 ++
> >>   2 files changed, 10 insertions(+)
> >>
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> index 582680804016..1b1e07292a9e 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> @@ -26,6 +26,7 @@
> >>   #include "dpu_hw_dspp.h"
> >>   #include "dpu_hw_dsc.h"
> >>   #include "dpu_hw_merge3d.h"
> >> +#include "dpu_hw_cdm.h"
> >>   #include "dpu_formats.h"
> >>   #include "dpu_encoder_phys.h"
> >>   #include "dpu_crtc.h"
> >> @@ -2097,6 +2098,13 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
> >>                                          phys_enc->hw_pp->merge_3d->idx);
> >>          }
> >>
> >> +       if (phys_enc->hw_cdm && phys_enc->hw_cdm->ops.bind_pingpong_blk && phys_enc->hw_pp) {
> >> +               phys_enc->hw_cdm->ops.bind_pingpong_blk(phys_enc->hw_cdm,
> >> +                                                       false, phys_enc->hw_pp->idx);
> >
> > But it was already bound in the cdm->enable, wasn't it?

Yes :-(

> >
>
> This is disable. I think you missed the "false" parameter.
>
> > Also the update_pending_flush_cdm should be called even for DPU < 5.0,
> > where there should be no bind_pingpong_blk callback.
> >
>
> Ack. This is a good catch!
>
> >> +               if (phys_enc->hw_ctl->ops.update_pending_flush_cdm)
> >> +                       phys_enc->hw_ctl->ops.update_pending_flush_cdm(phys_enc->hw_ctl);
> >> +       }
> >> +
> >>          if (dpu_enc->dsc) {
> >>                  dpu_encoder_unprep_dsc(dpu_enc);
> >>                  dpu_enc->dsc = NULL;
> >> 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 24dbc28be4f8..510c1c41ddbc 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >> @@ -150,6 +150,7 @@ enum dpu_intr_idx {
> >>    * @hw_pp:             Hardware interface to the ping pong registers
> >>    * @hw_intf:           Hardware interface to the intf registers
> >>    * @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
> >>    * @cached_mode:       DRM mode cached at mode_set time, acted on in enable
> >>    * @enabled:           Whether the encoder has enabled and running a mode
> >> @@ -178,6 +179,7 @@ struct dpu_encoder_phys {
> >>          struct dpu_hw_pingpong *hw_pp;
> >>          struct dpu_hw_intf *hw_intf;
> >>          struct dpu_hw_wb *hw_wb;
> >> +       struct dpu_hw_cdm *hw_cdm;
> >>          struct dpu_kms *dpu_kms;
> >>          struct drm_display_mode cached_mode;
> >>          enum dpu_enc_split_role split_role;
> >> --
> >> 2.40.1
> >>
> >
> >



-- 
With best wishes
Dmitry

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

* Re: [PATCH 10/16] drm/msm/dpu: add support to disable CDM block during encoder cleanup
@ 2023-12-01  8:36         ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-12-01  8:36 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Fri, 1 Dec 2023 at 01:58, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 8/30/2023 5:14 PM, Dmitry Baryshkov wrote:
> > On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >> In preparation of setting up CDM block, add the logic to disable it
> >> properly during encoder cleanup.
> >>
> >> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> >> ---
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c      | 8 ++++++++
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 2 ++
> >>   2 files changed, 10 insertions(+)
> >>
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> index 582680804016..1b1e07292a9e 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> @@ -26,6 +26,7 @@
> >>   #include "dpu_hw_dspp.h"
> >>   #include "dpu_hw_dsc.h"
> >>   #include "dpu_hw_merge3d.h"
> >> +#include "dpu_hw_cdm.h"
> >>   #include "dpu_formats.h"
> >>   #include "dpu_encoder_phys.h"
> >>   #include "dpu_crtc.h"
> >> @@ -2097,6 +2098,13 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
> >>                                          phys_enc->hw_pp->merge_3d->idx);
> >>          }
> >>
> >> +       if (phys_enc->hw_cdm && phys_enc->hw_cdm->ops.bind_pingpong_blk && phys_enc->hw_pp) {
> >> +               phys_enc->hw_cdm->ops.bind_pingpong_blk(phys_enc->hw_cdm,
> >> +                                                       false, phys_enc->hw_pp->idx);
> >
> > But it was already bound in the cdm->enable, wasn't it?

Yes :-(

> >
>
> This is disable. I think you missed the "false" parameter.
>
> > Also the update_pending_flush_cdm should be called even for DPU < 5.0,
> > where there should be no bind_pingpong_blk callback.
> >
>
> Ack. This is a good catch!
>
> >> +               if (phys_enc->hw_ctl->ops.update_pending_flush_cdm)
> >> +                       phys_enc->hw_ctl->ops.update_pending_flush_cdm(phys_enc->hw_ctl);
> >> +       }
> >> +
> >>          if (dpu_enc->dsc) {
> >>                  dpu_encoder_unprep_dsc(dpu_enc);
> >>                  dpu_enc->dsc = NULL;
> >> 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 24dbc28be4f8..510c1c41ddbc 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >> @@ -150,6 +150,7 @@ enum dpu_intr_idx {
> >>    * @hw_pp:             Hardware interface to the ping pong registers
> >>    * @hw_intf:           Hardware interface to the intf registers
> >>    * @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
> >>    * @cached_mode:       DRM mode cached at mode_set time, acted on in enable
> >>    * @enabled:           Whether the encoder has enabled and running a mode
> >> @@ -178,6 +179,7 @@ struct dpu_encoder_phys {
> >>          struct dpu_hw_pingpong *hw_pp;
> >>          struct dpu_hw_intf *hw_intf;
> >>          struct dpu_hw_wb *hw_wb;
> >> +       struct dpu_hw_cdm *hw_cdm;
> >>          struct dpu_kms *dpu_kms;
> >>          struct drm_display_mode cached_mode;
> >>          enum dpu_enc_split_role split_role;
> >> --
> >> 2.40.1
> >>
> >
> >



-- 
With best wishes
Dmitry

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

* Re: [PATCH 08/16] drm/msm/dpu: add support to allocate CDM from RM
  2023-11-30 23:50       ` Abhinav Kumar
@ 2023-12-01  8:39         ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-12-01  8:39 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel

On Fri, 1 Dec 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 8/30/2023 5:06 PM, Dmitry Baryshkov wrote:
> > On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >> Even though there is usually only one CDM block, it can be
> >> used by either HDMI, DisplayPort OR Writeback interfaces.
> >>
> >> Hence its allocation needs to be tracked properly by the
> >> resource manager to ensure appropriate availability of the
> >> block.
> >
> > It almost feels like an overkill, as up to now there is at most one CDM block.
> >
>
> Yes but even that one CDM block can be used by any connector. So as we
> discussed on IRC, this just implements the FCFS and we need RM to be the
> manager of that one block.

Yes. "almost"

>
> >>
> >> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> >> ---
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  2 +-
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h |  1 +
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h     |  1 +
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c      | 45 +++++++++++++++++++--
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h      |  4 +-
> >>   5 files changed, 48 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> index 6cf6597148fd..582680804016 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> @@ -663,7 +663,7 @@ static int dpu_encoder_virt_atomic_check(
> >>
> >>                  if (!crtc_state->active_changed || crtc_state->enable)
> >>                          ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
> >> -                                       drm_enc, crtc_state, topology);
> >> +                                       drm_enc, crtc_state, topology, false);
> >>          }
> >>
> >>          trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >> index 34f943102499..07f75f295844 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >> @@ -98,6 +98,7 @@ enum dpu_hw_blk_type {
> >>          DPU_HW_BLK_DSPP,
> >>          DPU_HW_BLK_MERGE_3D,
> >>          DPU_HW_BLK_DSC,
> >> +       DPU_HW_BLK_CDM,
> >>          DPU_HW_BLK_MAX,
> >>   };
> >>
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> >> index b6f53ca6e962..61aa58643fda 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> >> @@ -136,6 +136,7 @@ struct dpu_global_state {
> >>          uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
> >>          uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
> >>          uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
> >> +       uint32_t cdm_to_enc_id;
> >>   };
> >>
> >>   struct dpu_global_state
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >> index 7b6444a3fcb1..e7d4beb4661e 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >> @@ -29,10 +29,12 @@ static inline bool reserved_by_other(uint32_t *res_map, int idx,
> >>   /**
> >>    * struct dpu_rm_requirements - Reservation requirements parameter bundle
> >>    * @topology:  selected topology for the display
> >> + * @needs_cdm: whether the display needs a CDM block for the current mode
> >>    * @hw_res:       Hardware resources required as reported by the encoders
> >>    */
> >>   struct dpu_rm_requirements {
> >>          struct msm_display_topology topology;
> >> +       bool needs_cdm;
> >>   };
> >>
> >>   int dpu_rm_destroy(struct dpu_rm *rm)
> >> @@ -505,6 +507,26 @@ static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
> >>          return 0;
> >>   }
> >>
> >> +static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
> >> +                              struct dpu_global_state *global_state,
> >> +                              struct drm_encoder *enc)
> >> +{
> >> +       /* try allocating only one CDM block */
> >> +       if (!rm->cdm_blk) {
> >> +               DPU_ERROR("CDM block does not exist\n");
> >> +               return -EIO;
> >> +       }
> >> +
> >> +       if (global_state->cdm_to_enc_id) {
> >> +               DPU_ERROR("CDM_0 is already allocated\n");
> >> +               return -EIO;
> >> +       }
> >> +
> >> +       global_state->cdm_to_enc_id = enc->base.id;
> >> +
> >> +       return 0;
> >> +}
> >> +
> >>   static int _dpu_rm_make_reservation(
> >>                  struct dpu_rm *rm,
> >>                  struct dpu_global_state *global_state,
> >> @@ -530,15 +552,25 @@ static int _dpu_rm_make_reservation(
> >>          if (ret)
> >>                  return ret;
> >>
> >> +       if (reqs->needs_cdm) {
> >> +               ret = _dpu_rm_reserve_cdm(rm, global_state, enc);
> >> +               if (ret) {
> >> +                       DPU_ERROR("unable to find CDM blk\n");
> >> +                       return ret;
> >> +               }
> >> +       }
> >> +
> >>          return ret;
> >>   }
> >>
> >>   static int _dpu_rm_populate_requirements(
> >>                  struct drm_encoder *enc,
> >>                  struct dpu_rm_requirements *reqs,
> >> -               struct msm_display_topology req_topology)
> >> +               struct msm_display_topology req_topology,
> >> +               bool needs_cdm)
> >
> > Push it to the topology, please. It is a part of the topology at some
> > point of view.
> >
>
> hmmm ... ok with a pinch of salt as we somewhat deviate from the true
> topology definition that topology is just how lm, dsc and intf blocks
> are used. it was not intended to hold cdm.

Why not? I mean it is more logical compared to adding the 'needs_cdm'
argument which gets passed through together with the topology.

>
> >>   {
> >>          reqs->topology = req_topology;
> >> +       reqs->needs_cdm = needs_cdm;
> >>
> >>          DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
> >>                        reqs->topology.num_lm, reqs->topology.num_dsc,
> >> @@ -571,6 +603,7 @@ void dpu_rm_release(struct dpu_global_state *global_state,
> >>                  ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
> >>          _dpu_rm_clear_mapping(global_state->dspp_to_enc_id,
> >>                  ARRAY_SIZE(global_state->dspp_to_enc_id), enc->base.id);
> >> +       _dpu_rm_clear_mapping(&global_state->cdm_to_enc_id, 1, enc->base.id);
> >>   }
> >>
> >>   int dpu_rm_reserve(
> >> @@ -578,7 +611,8 @@ int dpu_rm_reserve(
> >>                  struct dpu_global_state *global_state,
> >>                  struct drm_encoder *enc,
> >>                  struct drm_crtc_state *crtc_state,
> >> -               struct msm_display_topology topology)
> >> +               struct msm_display_topology topology,
> >> +               bool needs_cdm)
> >>   {
> >>          struct dpu_rm_requirements reqs;
> >>          int ret;
> >> @@ -595,7 +629,7 @@ int dpu_rm_reserve(
> >>          DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
> >>                        enc->base.id, crtc_state->crtc->base.id);
> >>
> >> -       ret = _dpu_rm_populate_requirements(enc, &reqs, topology);
> >> +       ret = _dpu_rm_populate_requirements(enc, &reqs, topology, needs_cdm);
> >>          if (ret) {
> >>                  DPU_ERROR("failed to populate hw requirements\n");
> >>                  return ret;
> >> @@ -644,6 +678,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> >>                  hw_to_enc_id = global_state->dsc_to_enc_id;
> >>                  max_blks = ARRAY_SIZE(rm->dsc_blks);
> >>                  break;
> >> +       case DPU_HW_BLK_CDM:
> >> +               hw_blks = &rm->cdm_blk;
> >> +               hw_to_enc_id = &global_state->cdm_to_enc_id;
> >> +               max_blks = 1;
> >> +               break;
> >>          default:
> >>                  DPU_ERROR("blk type %d not managed by rm\n", type);
> >>                  return 0;
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> >> index 29b221491926..74262d3cb6c3 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> >> @@ -69,13 +69,15 @@ int dpu_rm_destroy(struct dpu_rm *rm);
> >>    * @drm_enc: DRM Encoder handle
> >>    * @crtc_state: Proposed Atomic DRM CRTC State handle
> >>    * @topology: Pointer to topology info for the display
> >> + * @needs_cdm: bool to indicate whether current encoder needs CDM
> >>    * @Return: 0 on Success otherwise -ERROR
> >>    */
> >>   int dpu_rm_reserve(struct dpu_rm *rm,
> >>                  struct dpu_global_state *global_state,
> >>                  struct drm_encoder *drm_enc,
> >>                  struct drm_crtc_state *crtc_state,
> >> -               struct msm_display_topology topology);
> >> +               struct msm_display_topology topology,
> >> +               bool needs_cdm);
> >>
> >>   /**
> >>    * dpu_rm_reserve - Given the encoder for the display chain, release any
> >> --
> >> 2.40.1
> >>
> >
> >



-- 
With best wishes
Dmitry

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

* Re: [PATCH 08/16] drm/msm/dpu: add support to allocate CDM from RM
@ 2023-12-01  8:39         ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-12-01  8:39 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Fri, 1 Dec 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 8/30/2023 5:06 PM, Dmitry Baryshkov wrote:
> > On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >> Even though there is usually only one CDM block, it can be
> >> used by either HDMI, DisplayPort OR Writeback interfaces.
> >>
> >> Hence its allocation needs to be tracked properly by the
> >> resource manager to ensure appropriate availability of the
> >> block.
> >
> > It almost feels like an overkill, as up to now there is at most one CDM block.
> >
>
> Yes but even that one CDM block can be used by any connector. So as we
> discussed on IRC, this just implements the FCFS and we need RM to be the
> manager of that one block.

Yes. "almost"

>
> >>
> >> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> >> ---
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  2 +-
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h |  1 +
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h     |  1 +
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c      | 45 +++++++++++++++++++--
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h      |  4 +-
> >>   5 files changed, 48 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> index 6cf6597148fd..582680804016 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> @@ -663,7 +663,7 @@ static int dpu_encoder_virt_atomic_check(
> >>
> >>                  if (!crtc_state->active_changed || crtc_state->enable)
> >>                          ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
> >> -                                       drm_enc, crtc_state, topology);
> >> +                                       drm_enc, crtc_state, topology, false);
> >>          }
> >>
> >>          trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >> index 34f943102499..07f75f295844 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >> @@ -98,6 +98,7 @@ enum dpu_hw_blk_type {
> >>          DPU_HW_BLK_DSPP,
> >>          DPU_HW_BLK_MERGE_3D,
> >>          DPU_HW_BLK_DSC,
> >> +       DPU_HW_BLK_CDM,
> >>          DPU_HW_BLK_MAX,
> >>   };
> >>
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> >> index b6f53ca6e962..61aa58643fda 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> >> @@ -136,6 +136,7 @@ struct dpu_global_state {
> >>          uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
> >>          uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
> >>          uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
> >> +       uint32_t cdm_to_enc_id;
> >>   };
> >>
> >>   struct dpu_global_state
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >> index 7b6444a3fcb1..e7d4beb4661e 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >> @@ -29,10 +29,12 @@ static inline bool reserved_by_other(uint32_t *res_map, int idx,
> >>   /**
> >>    * struct dpu_rm_requirements - Reservation requirements parameter bundle
> >>    * @topology:  selected topology for the display
> >> + * @needs_cdm: whether the display needs a CDM block for the current mode
> >>    * @hw_res:       Hardware resources required as reported by the encoders
> >>    */
> >>   struct dpu_rm_requirements {
> >>          struct msm_display_topology topology;
> >> +       bool needs_cdm;
> >>   };
> >>
> >>   int dpu_rm_destroy(struct dpu_rm *rm)
> >> @@ -505,6 +507,26 @@ static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
> >>          return 0;
> >>   }
> >>
> >> +static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
> >> +                              struct dpu_global_state *global_state,
> >> +                              struct drm_encoder *enc)
> >> +{
> >> +       /* try allocating only one CDM block */
> >> +       if (!rm->cdm_blk) {
> >> +               DPU_ERROR("CDM block does not exist\n");
> >> +               return -EIO;
> >> +       }
> >> +
> >> +       if (global_state->cdm_to_enc_id) {
> >> +               DPU_ERROR("CDM_0 is already allocated\n");
> >> +               return -EIO;
> >> +       }
> >> +
> >> +       global_state->cdm_to_enc_id = enc->base.id;
> >> +
> >> +       return 0;
> >> +}
> >> +
> >>   static int _dpu_rm_make_reservation(
> >>                  struct dpu_rm *rm,
> >>                  struct dpu_global_state *global_state,
> >> @@ -530,15 +552,25 @@ static int _dpu_rm_make_reservation(
> >>          if (ret)
> >>                  return ret;
> >>
> >> +       if (reqs->needs_cdm) {
> >> +               ret = _dpu_rm_reserve_cdm(rm, global_state, enc);
> >> +               if (ret) {
> >> +                       DPU_ERROR("unable to find CDM blk\n");
> >> +                       return ret;
> >> +               }
> >> +       }
> >> +
> >>          return ret;
> >>   }
> >>
> >>   static int _dpu_rm_populate_requirements(
> >>                  struct drm_encoder *enc,
> >>                  struct dpu_rm_requirements *reqs,
> >> -               struct msm_display_topology req_topology)
> >> +               struct msm_display_topology req_topology,
> >> +               bool needs_cdm)
> >
> > Push it to the topology, please. It is a part of the topology at some
> > point of view.
> >
>
> hmmm ... ok with a pinch of salt as we somewhat deviate from the true
> topology definition that topology is just how lm, dsc and intf blocks
> are used. it was not intended to hold cdm.

Why not? I mean it is more logical compared to adding the 'needs_cdm'
argument which gets passed through together with the topology.

>
> >>   {
> >>          reqs->topology = req_topology;
> >> +       reqs->needs_cdm = needs_cdm;
> >>
> >>          DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
> >>                        reqs->topology.num_lm, reqs->topology.num_dsc,
> >> @@ -571,6 +603,7 @@ void dpu_rm_release(struct dpu_global_state *global_state,
> >>                  ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
> >>          _dpu_rm_clear_mapping(global_state->dspp_to_enc_id,
> >>                  ARRAY_SIZE(global_state->dspp_to_enc_id), enc->base.id);
> >> +       _dpu_rm_clear_mapping(&global_state->cdm_to_enc_id, 1, enc->base.id);
> >>   }
> >>
> >>   int dpu_rm_reserve(
> >> @@ -578,7 +611,8 @@ int dpu_rm_reserve(
> >>                  struct dpu_global_state *global_state,
> >>                  struct drm_encoder *enc,
> >>                  struct drm_crtc_state *crtc_state,
> >> -               struct msm_display_topology topology)
> >> +               struct msm_display_topology topology,
> >> +               bool needs_cdm)
> >>   {
> >>          struct dpu_rm_requirements reqs;
> >>          int ret;
> >> @@ -595,7 +629,7 @@ int dpu_rm_reserve(
> >>          DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
> >>                        enc->base.id, crtc_state->crtc->base.id);
> >>
> >> -       ret = _dpu_rm_populate_requirements(enc, &reqs, topology);
> >> +       ret = _dpu_rm_populate_requirements(enc, &reqs, topology, needs_cdm);
> >>          if (ret) {
> >>                  DPU_ERROR("failed to populate hw requirements\n");
> >>                  return ret;
> >> @@ -644,6 +678,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> >>                  hw_to_enc_id = global_state->dsc_to_enc_id;
> >>                  max_blks = ARRAY_SIZE(rm->dsc_blks);
> >>                  break;
> >> +       case DPU_HW_BLK_CDM:
> >> +               hw_blks = &rm->cdm_blk;
> >> +               hw_to_enc_id = &global_state->cdm_to_enc_id;
> >> +               max_blks = 1;
> >> +               break;
> >>          default:
> >>                  DPU_ERROR("blk type %d not managed by rm\n", type);
> >>                  return 0;
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> >> index 29b221491926..74262d3cb6c3 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> >> @@ -69,13 +69,15 @@ int dpu_rm_destroy(struct dpu_rm *rm);
> >>    * @drm_enc: DRM Encoder handle
> >>    * @crtc_state: Proposed Atomic DRM CRTC State handle
> >>    * @topology: Pointer to topology info for the display
> >> + * @needs_cdm: bool to indicate whether current encoder needs CDM
> >>    * @Return: 0 on Success otherwise -ERROR
> >>    */
> >>   int dpu_rm_reserve(struct dpu_rm *rm,
> >>                  struct dpu_global_state *global_state,
> >>                  struct drm_encoder *drm_enc,
> >>                  struct drm_crtc_state *crtc_state,
> >> -               struct msm_display_topology topology);
> >> +               struct msm_display_topology topology,
> >> +               bool needs_cdm);
> >>
> >>   /**
> >>    * dpu_rm_reserve - Given the encoder for the display chain, release any
> >> --
> >> 2.40.1
> >>
> >
> >



-- 
With best wishes
Dmitry

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

* Re: [PATCH 06/16] drm/msm/dpu: add dpu_hw_cdm abstraction for CDM block
  2023-12-01  7:05         ` Dmitry Baryshkov
@ 2023-12-01 18:19           ` Abhinav Kumar
  -1 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-12-01 18:19 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-kernel, linux-arm-msm



On 11/30/2023 11:05 PM, Dmitry Baryshkov wrote:
> On Fri, 1 Dec 2023 at 01:36, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 8/30/2023 5:00 PM, Dmitry Baryshkov wrote:
>>> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>>>
>>>> CDM block comes with its own set of registers and operations
>>>> which can be done. In-line with other hardware sub-blocks, this
>>>> change adds the dpu_hw_cdm abstraction for the CDM block.
>>>>
>>>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>>>> ---
>>>>    drivers/gpu/drm/msm/Makefile                |   1 +
>>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c  | 272 ++++++++++++++++++++
>>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h  | 135 ++++++++++
>>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h |   1 +
>>>>    4 files changed, 409 insertions(+)
>>>>    create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
>>>>    create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
>>>> index 8d02d8c33069..2010cb1ca995 100644
>>>> --- a/drivers/gpu/drm/msm/Makefile
>>>> +++ b/drivers/gpu/drm/msm/Makefile
>>>> @@ -63,6 +63,7 @@ msm-$(CONFIG_DRM_MSM_DPU) += \
>>>>           disp/dpu1/dpu_encoder_phys_wb.o \
>>>>           disp/dpu1/dpu_formats.o \
>>>>           disp/dpu1/dpu_hw_catalog.o \
>>>> +       disp/dpu1/dpu_hw_cdm.o \
>>>>           disp/dpu1/dpu_hw_ctl.o \
>>>>           disp/dpu1/dpu_hw_dsc.o \
>>>>           disp/dpu1/dpu_hw_dsc_1_2.o \
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
>>>> new file mode 100644
>>>> index 000000000000..a2f7ee8f54e4
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
>>>> @@ -0,0 +1,272 @@
>>>> +// SPDX-License-Identifier: GPL-2.0-only
>>>> +/*
>>>> + * Copyright (c) 2023, The Linux Foundation. All rights reserved.
>>>> + */
>>>> +
>>>> +#include <drm/drm_managed.h>
>>>> +
>>>> +#include "dpu_hw_mdss.h"
>>>> +#include "dpu_hw_util.h"
>>>> +#include "dpu_hw_catalog.h"
>>>> +#include "dpu_hw_cdm.h"
>>>> +#include "dpu_kms.h"
>>>> +
>>>> +#define CDM_CSC_10_OPMODE                  0x000
>>>> +#define CDM_CSC_10_BASE                    0x004
>>>> +
>>>> +#define CDM_CDWN2_OP_MODE                  0x100
>>>> +#define CDM_CDWN2_CLAMP_OUT                0x104
>>>> +#define CDM_CDWN2_PARAMS_3D_0              0x108
>>>> +#define CDM_CDWN2_PARAMS_3D_1              0x10C
>>>> +#define CDM_CDWN2_COEFF_COSITE_H_0         0x110
>>>> +#define CDM_CDWN2_COEFF_COSITE_H_1         0x114
>>>> +#define CDM_CDWN2_COEFF_COSITE_H_2         0x118
>>>> +#define CDM_CDWN2_COEFF_OFFSITE_H_0        0x11C
>>>> +#define CDM_CDWN2_COEFF_OFFSITE_H_1        0x120
>>>> +#define CDM_CDWN2_COEFF_OFFSITE_H_2        0x124
>>>> +#define CDM_CDWN2_COEFF_COSITE_V           0x128
>>>> +#define CDM_CDWN2_COEFF_OFFSITE_V          0x12C
>>>> +#define CDM_CDWN2_OUT_SIZE                 0x130
>>>> +
>>>> +#define CDM_HDMI_PACK_OP_MODE              0x200
>>>> +#define CDM_CSC_10_MATRIX_COEFF_0          0x004
>>>> +
>>>> +#define CDM_MUX                            0x224
>>>> +
>>>> +/**
>>>> + * Horizontal coefficients for cosite chroma downscale
>>>> + * s13 representation of coefficients
>>>> + */
>>>> +static u32 cosite_h_coeff[] = {0x00000016, 0x000001cc, 0x0100009e};
>>>> +
>>>> +/**
>>>> + * Horizontal coefficients for offsite chroma downscale
>>>> + */
>>>> +static u32 offsite_h_coeff[] = {0x000b0005, 0x01db01eb, 0x00e40046};
>>>> +
>>>> +/**
>>>> + * Vertical coefficients for cosite chroma downscale
>>>> + */
>>>> +static u32 cosite_v_coeff[] = {0x00080004};
>>>> +/**
>>>> + * Vertical coefficients for offsite chroma downscale
>>>> + */
>>>> +static u32 offsite_v_coeff[] = {0x00060002};
>>>> +
>>>> +static int dpu_hw_cdm_setup_csc_10bit(struct dpu_hw_cdm *ctx, struct dpu_csc_cfg *data)
>>>> +{
>>>> +       dpu_hw_csc_setup(&ctx->hw, CDM_CSC_10_MATRIX_COEFF_0, data, true);
>>>
>>> Where was this defined?
>>>
>>
>> Its in this file itself
>>
>> +#define CDM_CSC_10_MATRIX_COEFF_0          0x004
>>
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static int dpu_hw_cdm_setup_cdwn(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cfg)
>>>> +{
>>>> +       struct dpu_hw_blk_reg_map *c = &ctx->hw;
>>>> +       u32 opmode = 0;
>>>> +       u32 out_size = 0;
>>>> +
>>>> +       if (cfg->output_bit_depth == CDM_CDWN_OUTPUT_10BIT)
>>>> +               opmode &= ~BIT(7);
>>>> +       else
>>>> +               opmode |= BIT(7);
>>>> +
>>>> +       /* ENABLE DWNS_H bit */
>>>> +       opmode |= BIT(1);
>>>> +
>>>> +       switch (cfg->h_cdwn_type) {
>>>> +       case CDM_CDWN_DISABLE:
>>>> +               /* CLEAR METHOD_H field */
>>>> +               opmode &= ~(0x18);
>>>> +               /* CLEAR DWNS_H bit */
>>>> +               opmode &= ~BIT(1);
>>>> +               break;
>>>> +       case CDM_CDWN_PIXEL_DROP:
>>>> +               /* Clear METHOD_H field (pixel drop is 0) */
>>>> +               opmode &= ~(0x18);
>>>> +               break;
>>>> +       case CDM_CDWN_AVG:
>>>> +               /* Clear METHOD_H field (Average is 0x1) */
>>>> +               opmode &= ~(0x18);
>>>> +               opmode |= (0x1 << 0x3);
>>>> +               break;
>>>> +       case CDM_CDWN_COSITE:
>>>> +               /* Clear METHOD_H field (Average is 0x2) */
>>>> +               opmode &= ~(0x18);
>>>> +               opmode |= (0x2 << 0x3);
>>>> +               /* Co-site horizontal coefficients */
>>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_0,
>>>> +                               cosite_h_coeff[0]);
>>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_1,
>>>> +                               cosite_h_coeff[1]);
>>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_2,
>>>> +                               cosite_h_coeff[2]);
>>>> +               break;
>>>> +       case CDM_CDWN_OFFSITE:
>>>> +               /* Clear METHOD_H field (Average is 0x3) */
>>>> +               opmode &= ~(0x18);
>>>> +               opmode |= (0x3 << 0x3);
>>>> +
>>>> +               /* Off-site horizontal coefficients */
>>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_0,
>>>> +                               offsite_h_coeff[0]);
>>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_1,
>>>> +                               offsite_h_coeff[1]);
>>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_2,
>>>> +                               offsite_h_coeff[2]);
>>>> +               break;
>>>> +       default:
>>>> +               pr_err("%s invalid horz down sampling type\n", __func__);
>>>> +               return -EINVAL;
>>>> +       }
>>>> +
>>>> +       /* ENABLE DWNS_V bit */
>>>> +       opmode |= BIT(2);
>>>> +
>>>> +       switch (cfg->v_cdwn_type) {
>>>> +       case CDM_CDWN_DISABLE:
>>>> +               /* CLEAR METHOD_V field */
>>>> +               opmode &= ~(0x60);
>>>
>>> #define, GENMASK
>>>
>>>> +               /* CLEAR DWNS_V bit */
>>>> +               opmode &= ~BIT(2);
>>>> +               break;
>>>> +       case CDM_CDWN_PIXEL_DROP:
>>>> +               /* Clear METHOD_V field (pixel drop is 0) */
>>>> +               opmode &= ~(0x60);
>>>> +               break;
>>>> +       case CDM_CDWN_AVG:
>>>> +               /* Clear METHOD_V field (Average is 0x1) */
>>>> +               opmode &= ~(0x60);
>>>> +               opmode |= (0x1 << 0x5);
>>>
>>> #define
>>>
>>>> +               break;
>>>> +       case CDM_CDWN_COSITE:
>>>> +               /* Clear METHOD_V field (Average is 0x2) */
>>>> +               opmode &= ~(0x60);
>>>> +               opmode |= (0x2 << 0x5);
>>>> +               /* Co-site vertical coefficients */
>>>> +               DPU_REG_WRITE(c,
>>>> +                               CDM_CDWN2_COEFF_COSITE_V,
>>>> +                               cosite_v_coeff[0]);
>>>
>>> align to opening bracket
>>>
>>>> +               break;
>>>> +       case CDM_CDWN_OFFSITE:
>>>> +               /* Clear METHOD_V field (Average is 0x3) */
>>>> +               opmode &= ~(0x60);
>>>> +               opmode |= (0x3 << 0x5);
>>>> +
>>>> +               /* Off-site vertical coefficients */
>>>> +               DPU_REG_WRITE(c,
>>>> +                               CDM_CDWN2_COEFF_OFFSITE_V,
>>>> +                               offsite_v_coeff[0]);
>>>
>>> align to opening bracket
>>>
>>>> +               break;
>>>> +       default:
>>>> +               return -EINVAL;
>>>> +       }
>>>> +
>>>> +       if (cfg->v_cdwn_type || cfg->h_cdwn_type)
>>>> +               opmode |= BIT(0); /* EN CDWN module */
>>>
>>> #define
>>>
>>
>> Ack to all comments about GENMASK and #define
>>
>>>> +       else
>>>> +               opmode &= ~BIT(0);
>>>> +
>>>> +       out_size = (cfg->output_width & 0xFFFF) |
>>>> +               ((cfg->output_height & 0xFFFF) << 16);
>>>> +       DPU_REG_WRITE(c, CDM_CDWN2_OUT_SIZE, out_size);
>>>> +       DPU_REG_WRITE(c, CDM_CDWN2_OP_MODE, opmode);
>>>> +       DPU_REG_WRITE(c, CDM_CDWN2_CLAMP_OUT,
>>>> +                       ((0x3FF << 16) | 0x0));
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +int dpu_hw_cdm_enable(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cdm)
>>>> +{
>>>> +       struct dpu_hw_blk_reg_map *c = &ctx->hw;
>>>> +       const struct dpu_format *fmt;
>>>> +       u32 opmode = 0;
>>>> +       u32 csc = 0;
>>>> +
>>>> +       if (!ctx || !cdm)
>>>> +               return -EINVAL;
>>>> +
>>>> +       fmt = cdm->output_fmt;
>>>> +
>>>> +       if (!DPU_FORMAT_IS_YUV(fmt))
>>>> +               return -EINVAL;
>>>> +
>>>> +       if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
>>>> +               if (fmt->chroma_sample != DPU_CHROMA_H1V2)
>>>> +                       return -EINVAL; /*unsupported format */
>>>> +               opmode = BIT(0);
>>>> +               opmode |= (fmt->chroma_sample << 1);
>>>> +       }
>>>> +
>>>> +       csc |= BIT(2);
>>>> +       csc &= ~BIT(1);
>>>> +       csc |= BIT(0);
>>>
>>> Can we get some sensible #defines for all this magic, please?
>>>
>>
>> Ack, will do.
>>
>>>> +
>>>> +       if (ctx && ctx->ops.bind_pingpong_blk)
>>>> +               ctx->ops.bind_pingpong_blk(ctx, true,
>>>> +                               cdm->pp_id);
>>>> +
>>>> +       DPU_REG_WRITE(c, CDM_CSC_10_OPMODE, csc);
>>>> +       DPU_REG_WRITE(c, CDM_HDMI_PACK_OP_MODE, opmode);
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +void dpu_hw_cdm_disable(struct dpu_hw_cdm *ctx)
>>>> +{
>>>> +       if (!ctx)
>>>> +               return;
>>>> +
>>>> +       if (ctx && ctx->ops.bind_pingpong_blk)
>>>> +               ctx->ops.bind_pingpong_blk(ctx, false, 0);
>>>
>>> PINGPONG_NONE.
>>>
>>>> +}
>>>> +
>>>> +static void dpu_hw_cdm_bind_pingpong_blk(struct dpu_hw_cdm *ctx, bool enable,
>>>> +                                        const enum dpu_pingpong pp)
>>>> +{
>>>> +       struct dpu_hw_blk_reg_map *c;
>>>> +       int mux_cfg = 0xF;
>>>> +
>>>> +       if (!ctx || (enable && (pp < PINGPONG_0 || pp >= PINGPONG_MAX)))
>>>> +               return;
>>>
>>> I'd say, this is useless. We don't have such checks in other
>>> bind_pingpong_blk() callbacks.
>>>
>>> Also there should be a guarding check for DPU >= 5.0 either here or at
>>> the ops init.
>>>
>>
>> Will add it at ops init
>>
>>>> +
>>>> +       c = &ctx->hw;
>>>> +
>>>> +       if (enable)
>>>> +               mux_cfg = (pp - PINGPONG_0) & 0x7;
>>>> +
>>>> +       DPU_REG_WRITE(c, CDM_MUX, mux_cfg);
>>>> +}
>>>> +
>>>> +static void _setup_cdm_ops(struct dpu_hw_cdm_ops *ops, unsigned long features)
>>>
>>> Please inline
>>>
>>
>> OK
>>
>>>> +{
>>>> +       ops->setup_csc_data = dpu_hw_cdm_setup_csc_10bit;
>>>> +       ops->setup_cdwn = dpu_hw_cdm_setup_cdwn;
>>>> +       ops->enable = dpu_hw_cdm_enable;
>>>> +       ops->disable = dpu_hw_cdm_disable;
>>>> +       ops->bind_pingpong_blk = dpu_hw_cdm_bind_pingpong_blk;
>>>
>>> As you seem to call this function directly, we might as well drop the
>>> callback from the ops.
>>>
>>
>> There are two paths for the bind_pingpong_blk(). One is absorbed within
>> cdm_enable and cdm_disable calls to bind and unbind the pingpong resp.
>> And yes, for that we dont need a separate ops as its within the same file.
>>
>> This will handle cases where we transition from YUV to non-YUV cases and
>> vice-versa without an encoder disable in between which I believe happens
>> in the IGT cases.
>>
>> But the dpu_encoder_helper_phys_cleanup() path is only in the encoder
>> disable() path without a non-YUV frame in the middle so lets say we were
>> in YUV mode but then just disabled the encoder we do need the cleanup
>> there and since thats outside of the dpu_hw_cdm, we do need this op.
>>
>> I agree we need to protect this with the DPU revision check.
>>
>>>> +}
>>>> +
>>>> +struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cfg, void __iomem *addr)
>>>> +{
>>>> +       struct dpu_hw_cdm *c;
>>>> +
>>>> +       c = kzalloc(sizeof(*c), GFP_KERNEL);
>>>> +       if (!c)
>>>> +               return ERR_PTR(-ENOMEM);
>>>> +
>>>> +       c->hw.blk_addr = addr + cfg->base;
>>>> +       c->hw.log_mask = DPU_DBG_MASK_CDM;
>>>> +
>>>> +       /* Assign ops */
>>>> +       c->idx = cfg->id;
>>>> +       c->caps = cfg;
>>>> +       _setup_cdm_ops(&c->ops, c->caps->features);
>>>> +
>>>> +       return c;
>>>> +}
>>>> +
>>>> +void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm)
>>>> +{
>>>> +       kfree(cdm);
>>>
>>> I'd prefer not to introduce another manual kzalloc/kfree pair, see
>>> https://patchwork.freedesktop.org/series/120366/
>>>
>>
>> I recall I did not want to have a manual kzalloc/kfree pair. But the
>> issue was I think this series was not merged that time (and is isnt
>> merged now either)
> 
> No response, no reviews since 15th August. Today is the 1st of December.
> 
> I'm close to deciding that unreviewed series have no issues and start
> showing them to -next after a grace period of 1 month.
> 
>> and this is the one which passes drm_dev to
>> dpu_rm_init. I thought maybe it was easier for you to absorb this change
>> into that series instead of me pulling that whole series to make this
>> one compile as we will not be adding new HW blocks after this for the
>> next 2 cycles. It will only be using existing ones.
>>
>> If its too much trouble for you, I will rebase on top of that series but
>> I am pretty sure you will have to rebase and post that again anyway on
>> top of the current msm-next.
>>
>> I am also going to do the same thing now with this series.
>>

There were 4 patches in that series which didnt get a R-b. Perhaps 
jessica can finish the reviews which she started on that one.

Leaving her a note on IRC would not have hurt like its a common practice 
sometimes with other reviewers.

Now, do you want to rebase this on msm-next and re-send so that I can 
rebase on top of yours?

>> So we can just decide that in whose rebase we will handle it.
>>
>>>> +}
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
>>>> new file mode 100644
>>>> index 000000000000..da60893a5c02
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
>>>> @@ -0,0 +1,135 @@
>>>> +/* SPDX-License-Identifier: GPL-2.0-only */
>>>> +/*
>>>> + * Copyright (c) 2023, The Linux Foundation. All rights reserved.
>>>> + */
>>>> +
>>>> +#ifndef _DPU_HW_CDM_H
>>>> +#define _DPU_HW_CDM_H
>>>> +
>>>> +#include "dpu_hw_mdss.h"
>>>> +#include "dpu_hw_top.h"
>>>> +
>>>> +struct dpu_hw_cdm;
>>>> +
>>>> +struct dpu_hw_cdm_cfg {
>>>> +       u32 output_width;
>>>> +       u32 output_height;
>>>> +       u32 output_bit_depth;
>>>> +       u32 h_cdwn_type;
>>>> +       u32 v_cdwn_type;
>>>> +       const struct dpu_format *output_fmt;
>>>> +       u32 output_type;
>>>> +       int pp_id;
>>>> +};
>>>> +
>>>> +enum dpu_hw_cdwn_type {
>>>> +       CDM_CDWN_DISABLE,
>>>> +       CDM_CDWN_PIXEL_DROP,
>>>> +       CDM_CDWN_AVG,
>>>> +       CDM_CDWN_COSITE,
>>>> +       CDM_CDWN_OFFSITE,
>>>> +};
>>>> +
>>>> +enum dpu_hw_cdwn_output_type {
>>>> +       CDM_CDWN_OUTPUT_HDMI,
>>>> +       CDM_CDWN_OUTPUT_WB,
>>>> +};
>>>> +
>>>> +enum dpu_hw_cdwn_output_bit_depth {
>>>> +       CDM_CDWN_OUTPUT_8BIT,
>>>> +       CDM_CDWN_OUTPUT_10BIT,
>>>> +};
>>>> +
>>>> +/**
>>>> + * struct dpu_hw_cdm_ops : Interface to the chroma down Hw driver functions
>>>> + *                         Assumption is these functions will be called after
>>>> + *                         clocks are enabled
>>>> + *  @setup_csc:            Programs the csc matrix
>>>> + *  @setup_cdwn:           Sets up the chroma down sub module
>>>> + *  @enable:               Enables the output to interface and programs the
>>>> + *                         output packer
>>>> + *  @disable:              Puts the cdm in bypass mode
>>>> + *  @bind_pingpong_blk:    enable/disable the connection with pingpong which
>>>> + *                         will feed pixels to this cdm
>>>> + */
>>>> +struct dpu_hw_cdm_ops {
>>>> +       /**
>>>> +        * Programs the CSC matrix for conversion from RGB space to YUV space,
>>>> +        * it is optional to call this function as this matrix is automatically
>>>> +        * set during initialization, user should call this if it wants
>>>> +        * to program a different matrix than default matrix.
>>>> +        * @cdm:          Pointer to the chroma down context structure
>>>> +        * @data          Pointer to CSC configuration data
>>>> +        * return:        0 if success; error code otherwise
>>>> +        */
>>>> +       int (*setup_csc_data)(struct dpu_hw_cdm *cdm, struct dpu_csc_cfg *data);
>>>> +
>>>> +       /**
>>>> +        * Programs the Chroma downsample part.
>>>> +        * @cdm         Pointer to chroma down context
>>>> +        * @cfg         Pointer to the cdm configuration data
>>>> +        */
>>>> +       int (*setup_cdwn)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
>>>> +
>>>> +       /**
>>>> +        * Enable the CDM module
>>>> +        * @cdm         Pointer to chroma down context
>>>> +        */
>>>> +       int (*enable)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
>>>> +
>>>> +       /**
>>>> +        * Disable the CDM module
>>>> +        * @cdm         Pointer to chroma down context
>>>> +        */
>>>> +       void (*disable)(struct dpu_hw_cdm *cdm);
>>>> +
>>>> +       /**
>>>> +        * Enable/disable the connection with pingpong
>>>> +        * @cdm         Pointer to chroma down context
>>>> +        * @enable      Enable/disable control
>>>> +        * @pp          pingpong block id.
>>>> +        */
>>>> +       void (*bind_pingpong_blk)(struct dpu_hw_cdm *cdm, bool enable,
>>>> +                                 const enum dpu_pingpong pp);
>>>> +};
>>>> +
>>>> +/**
>>>> + * struct dpu_hw_cdm - cdm description
>>>> + * @base: Hardware block base structure
>>>> + * @hw: Block hardware details
>>>> + * @idx: CDM index
>>>> + * @caps: Pointer to cdm_cfg
>>>> + * @ops: handle to operations possible for this CDM
>>>> + */
>>>> +struct dpu_hw_cdm {
>>>> +       struct dpu_hw_blk base;
>>>> +       struct dpu_hw_blk_reg_map hw;
>>>> +
>>>> +       /* chroma down */
>>>> +       const struct dpu_cdm_cfg *caps;
>>>> +       enum  dpu_cdm  idx;
>>>> +
>>>> +       /* ops */
>>>> +       struct dpu_hw_cdm_ops ops;
>>>> +};
>>>> +
>>>> +/**
>>>> + * dpu_hw_cdm_init - initializes the cdm hw driver object.
>>>> + * should be called once before accessing every cdm.
>>>> + * @cdm: CDM catalog entry for which driver object is required
>>>> + * @addr :   mapped register io address of MDSS
>>>> + */
>>>> +struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cdm, void __iomem *addr);
>>>> +
>>>> +/**
>>>> + * dpu_hw_cdm_destroy - destroys cdm driver context
>>>> + * @cdm:   Pointer to cdm driver context returned by dpu_hw_cdm_init
>>>> + */
>>>> +void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm);
>>>> +
>>>> +static inline struct dpu_hw_cdm *to_dpu_hw_cdm(struct dpu_hw_blk *hw)
>>>> +{
>>>> +       return container_of(hw, struct dpu_hw_cdm, base);
>>>> +}
>>>> +
>>>> +#endif /*_DPU_HW_CDM_H */
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>>>> index 4d6dba18caf0..34f943102499 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>>>> @@ -463,6 +463,7 @@ struct dpu_mdss_color {
>>>>    #define DPU_DBG_MASK_ROT      (1 << 9)
>>>>    #define DPU_DBG_MASK_DSPP     (1 << 10)
>>>>    #define DPU_DBG_MASK_DSC      (1 << 11)
>>>> +#define DPU_DBG_MASK_CDM      (1 << 12)
>>>>
>>>>    /**
>>>>     * struct dpu_hw_tear_check - Struct contains parameters to configure
>>>> --
>>>> 2.40.1
>>>>
>>>
>>>
>>> --
>>> With best wishes
>>> Dmitry
> 
> 
> 

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

* Re: [PATCH 06/16] drm/msm/dpu: add dpu_hw_cdm abstraction for CDM block
@ 2023-12-01 18:19           ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-12-01 18:19 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul



On 11/30/2023 11:05 PM, Dmitry Baryshkov wrote:
> On Fri, 1 Dec 2023 at 01:36, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 8/30/2023 5:00 PM, Dmitry Baryshkov wrote:
>>> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>>>
>>>> CDM block comes with its own set of registers and operations
>>>> which can be done. In-line with other hardware sub-blocks, this
>>>> change adds the dpu_hw_cdm abstraction for the CDM block.
>>>>
>>>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>>>> ---
>>>>    drivers/gpu/drm/msm/Makefile                |   1 +
>>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c  | 272 ++++++++++++++++++++
>>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h  | 135 ++++++++++
>>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h |   1 +
>>>>    4 files changed, 409 insertions(+)
>>>>    create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
>>>>    create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
>>>> index 8d02d8c33069..2010cb1ca995 100644
>>>> --- a/drivers/gpu/drm/msm/Makefile
>>>> +++ b/drivers/gpu/drm/msm/Makefile
>>>> @@ -63,6 +63,7 @@ msm-$(CONFIG_DRM_MSM_DPU) += \
>>>>           disp/dpu1/dpu_encoder_phys_wb.o \
>>>>           disp/dpu1/dpu_formats.o \
>>>>           disp/dpu1/dpu_hw_catalog.o \
>>>> +       disp/dpu1/dpu_hw_cdm.o \
>>>>           disp/dpu1/dpu_hw_ctl.o \
>>>>           disp/dpu1/dpu_hw_dsc.o \
>>>>           disp/dpu1/dpu_hw_dsc_1_2.o \
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
>>>> new file mode 100644
>>>> index 000000000000..a2f7ee8f54e4
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
>>>> @@ -0,0 +1,272 @@
>>>> +// SPDX-License-Identifier: GPL-2.0-only
>>>> +/*
>>>> + * Copyright (c) 2023, The Linux Foundation. All rights reserved.
>>>> + */
>>>> +
>>>> +#include <drm/drm_managed.h>
>>>> +
>>>> +#include "dpu_hw_mdss.h"
>>>> +#include "dpu_hw_util.h"
>>>> +#include "dpu_hw_catalog.h"
>>>> +#include "dpu_hw_cdm.h"
>>>> +#include "dpu_kms.h"
>>>> +
>>>> +#define CDM_CSC_10_OPMODE                  0x000
>>>> +#define CDM_CSC_10_BASE                    0x004
>>>> +
>>>> +#define CDM_CDWN2_OP_MODE                  0x100
>>>> +#define CDM_CDWN2_CLAMP_OUT                0x104
>>>> +#define CDM_CDWN2_PARAMS_3D_0              0x108
>>>> +#define CDM_CDWN2_PARAMS_3D_1              0x10C
>>>> +#define CDM_CDWN2_COEFF_COSITE_H_0         0x110
>>>> +#define CDM_CDWN2_COEFF_COSITE_H_1         0x114
>>>> +#define CDM_CDWN2_COEFF_COSITE_H_2         0x118
>>>> +#define CDM_CDWN2_COEFF_OFFSITE_H_0        0x11C
>>>> +#define CDM_CDWN2_COEFF_OFFSITE_H_1        0x120
>>>> +#define CDM_CDWN2_COEFF_OFFSITE_H_2        0x124
>>>> +#define CDM_CDWN2_COEFF_COSITE_V           0x128
>>>> +#define CDM_CDWN2_COEFF_OFFSITE_V          0x12C
>>>> +#define CDM_CDWN2_OUT_SIZE                 0x130
>>>> +
>>>> +#define CDM_HDMI_PACK_OP_MODE              0x200
>>>> +#define CDM_CSC_10_MATRIX_COEFF_0          0x004
>>>> +
>>>> +#define CDM_MUX                            0x224
>>>> +
>>>> +/**
>>>> + * Horizontal coefficients for cosite chroma downscale
>>>> + * s13 representation of coefficients
>>>> + */
>>>> +static u32 cosite_h_coeff[] = {0x00000016, 0x000001cc, 0x0100009e};
>>>> +
>>>> +/**
>>>> + * Horizontal coefficients for offsite chroma downscale
>>>> + */
>>>> +static u32 offsite_h_coeff[] = {0x000b0005, 0x01db01eb, 0x00e40046};
>>>> +
>>>> +/**
>>>> + * Vertical coefficients for cosite chroma downscale
>>>> + */
>>>> +static u32 cosite_v_coeff[] = {0x00080004};
>>>> +/**
>>>> + * Vertical coefficients for offsite chroma downscale
>>>> + */
>>>> +static u32 offsite_v_coeff[] = {0x00060002};
>>>> +
>>>> +static int dpu_hw_cdm_setup_csc_10bit(struct dpu_hw_cdm *ctx, struct dpu_csc_cfg *data)
>>>> +{
>>>> +       dpu_hw_csc_setup(&ctx->hw, CDM_CSC_10_MATRIX_COEFF_0, data, true);
>>>
>>> Where was this defined?
>>>
>>
>> Its in this file itself
>>
>> +#define CDM_CSC_10_MATRIX_COEFF_0          0x004
>>
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +static int dpu_hw_cdm_setup_cdwn(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cfg)
>>>> +{
>>>> +       struct dpu_hw_blk_reg_map *c = &ctx->hw;
>>>> +       u32 opmode = 0;
>>>> +       u32 out_size = 0;
>>>> +
>>>> +       if (cfg->output_bit_depth == CDM_CDWN_OUTPUT_10BIT)
>>>> +               opmode &= ~BIT(7);
>>>> +       else
>>>> +               opmode |= BIT(7);
>>>> +
>>>> +       /* ENABLE DWNS_H bit */
>>>> +       opmode |= BIT(1);
>>>> +
>>>> +       switch (cfg->h_cdwn_type) {
>>>> +       case CDM_CDWN_DISABLE:
>>>> +               /* CLEAR METHOD_H field */
>>>> +               opmode &= ~(0x18);
>>>> +               /* CLEAR DWNS_H bit */
>>>> +               opmode &= ~BIT(1);
>>>> +               break;
>>>> +       case CDM_CDWN_PIXEL_DROP:
>>>> +               /* Clear METHOD_H field (pixel drop is 0) */
>>>> +               opmode &= ~(0x18);
>>>> +               break;
>>>> +       case CDM_CDWN_AVG:
>>>> +               /* Clear METHOD_H field (Average is 0x1) */
>>>> +               opmode &= ~(0x18);
>>>> +               opmode |= (0x1 << 0x3);
>>>> +               break;
>>>> +       case CDM_CDWN_COSITE:
>>>> +               /* Clear METHOD_H field (Average is 0x2) */
>>>> +               opmode &= ~(0x18);
>>>> +               opmode |= (0x2 << 0x3);
>>>> +               /* Co-site horizontal coefficients */
>>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_0,
>>>> +                               cosite_h_coeff[0]);
>>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_1,
>>>> +                               cosite_h_coeff[1]);
>>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_2,
>>>> +                               cosite_h_coeff[2]);
>>>> +               break;
>>>> +       case CDM_CDWN_OFFSITE:
>>>> +               /* Clear METHOD_H field (Average is 0x3) */
>>>> +               opmode &= ~(0x18);
>>>> +               opmode |= (0x3 << 0x3);
>>>> +
>>>> +               /* Off-site horizontal coefficients */
>>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_0,
>>>> +                               offsite_h_coeff[0]);
>>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_1,
>>>> +                               offsite_h_coeff[1]);
>>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_2,
>>>> +                               offsite_h_coeff[2]);
>>>> +               break;
>>>> +       default:
>>>> +               pr_err("%s invalid horz down sampling type\n", __func__);
>>>> +               return -EINVAL;
>>>> +       }
>>>> +
>>>> +       /* ENABLE DWNS_V bit */
>>>> +       opmode |= BIT(2);
>>>> +
>>>> +       switch (cfg->v_cdwn_type) {
>>>> +       case CDM_CDWN_DISABLE:
>>>> +               /* CLEAR METHOD_V field */
>>>> +               opmode &= ~(0x60);
>>>
>>> #define, GENMASK
>>>
>>>> +               /* CLEAR DWNS_V bit */
>>>> +               opmode &= ~BIT(2);
>>>> +               break;
>>>> +       case CDM_CDWN_PIXEL_DROP:
>>>> +               /* Clear METHOD_V field (pixel drop is 0) */
>>>> +               opmode &= ~(0x60);
>>>> +               break;
>>>> +       case CDM_CDWN_AVG:
>>>> +               /* Clear METHOD_V field (Average is 0x1) */
>>>> +               opmode &= ~(0x60);
>>>> +               opmode |= (0x1 << 0x5);
>>>
>>> #define
>>>
>>>> +               break;
>>>> +       case CDM_CDWN_COSITE:
>>>> +               /* Clear METHOD_V field (Average is 0x2) */
>>>> +               opmode &= ~(0x60);
>>>> +               opmode |= (0x2 << 0x5);
>>>> +               /* Co-site vertical coefficients */
>>>> +               DPU_REG_WRITE(c,
>>>> +                               CDM_CDWN2_COEFF_COSITE_V,
>>>> +                               cosite_v_coeff[0]);
>>>
>>> align to opening bracket
>>>
>>>> +               break;
>>>> +       case CDM_CDWN_OFFSITE:
>>>> +               /* Clear METHOD_V field (Average is 0x3) */
>>>> +               opmode &= ~(0x60);
>>>> +               opmode |= (0x3 << 0x5);
>>>> +
>>>> +               /* Off-site vertical coefficients */
>>>> +               DPU_REG_WRITE(c,
>>>> +                               CDM_CDWN2_COEFF_OFFSITE_V,
>>>> +                               offsite_v_coeff[0]);
>>>
>>> align to opening bracket
>>>
>>>> +               break;
>>>> +       default:
>>>> +               return -EINVAL;
>>>> +       }
>>>> +
>>>> +       if (cfg->v_cdwn_type || cfg->h_cdwn_type)
>>>> +               opmode |= BIT(0); /* EN CDWN module */
>>>
>>> #define
>>>
>>
>> Ack to all comments about GENMASK and #define
>>
>>>> +       else
>>>> +               opmode &= ~BIT(0);
>>>> +
>>>> +       out_size = (cfg->output_width & 0xFFFF) |
>>>> +               ((cfg->output_height & 0xFFFF) << 16);
>>>> +       DPU_REG_WRITE(c, CDM_CDWN2_OUT_SIZE, out_size);
>>>> +       DPU_REG_WRITE(c, CDM_CDWN2_OP_MODE, opmode);
>>>> +       DPU_REG_WRITE(c, CDM_CDWN2_CLAMP_OUT,
>>>> +                       ((0x3FF << 16) | 0x0));
>>>> +
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +int dpu_hw_cdm_enable(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cdm)
>>>> +{
>>>> +       struct dpu_hw_blk_reg_map *c = &ctx->hw;
>>>> +       const struct dpu_format *fmt;
>>>> +       u32 opmode = 0;
>>>> +       u32 csc = 0;
>>>> +
>>>> +       if (!ctx || !cdm)
>>>> +               return -EINVAL;
>>>> +
>>>> +       fmt = cdm->output_fmt;
>>>> +
>>>> +       if (!DPU_FORMAT_IS_YUV(fmt))
>>>> +               return -EINVAL;
>>>> +
>>>> +       if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
>>>> +               if (fmt->chroma_sample != DPU_CHROMA_H1V2)
>>>> +                       return -EINVAL; /*unsupported format */
>>>> +               opmode = BIT(0);
>>>> +               opmode |= (fmt->chroma_sample << 1);
>>>> +       }
>>>> +
>>>> +       csc |= BIT(2);
>>>> +       csc &= ~BIT(1);
>>>> +       csc |= BIT(0);
>>>
>>> Can we get some sensible #defines for all this magic, please?
>>>
>>
>> Ack, will do.
>>
>>>> +
>>>> +       if (ctx && ctx->ops.bind_pingpong_blk)
>>>> +               ctx->ops.bind_pingpong_blk(ctx, true,
>>>> +                               cdm->pp_id);
>>>> +
>>>> +       DPU_REG_WRITE(c, CDM_CSC_10_OPMODE, csc);
>>>> +       DPU_REG_WRITE(c, CDM_HDMI_PACK_OP_MODE, opmode);
>>>> +       return 0;
>>>> +}
>>>> +
>>>> +void dpu_hw_cdm_disable(struct dpu_hw_cdm *ctx)
>>>> +{
>>>> +       if (!ctx)
>>>> +               return;
>>>> +
>>>> +       if (ctx && ctx->ops.bind_pingpong_blk)
>>>> +               ctx->ops.bind_pingpong_blk(ctx, false, 0);
>>>
>>> PINGPONG_NONE.
>>>
>>>> +}
>>>> +
>>>> +static void dpu_hw_cdm_bind_pingpong_blk(struct dpu_hw_cdm *ctx, bool enable,
>>>> +                                        const enum dpu_pingpong pp)
>>>> +{
>>>> +       struct dpu_hw_blk_reg_map *c;
>>>> +       int mux_cfg = 0xF;
>>>> +
>>>> +       if (!ctx || (enable && (pp < PINGPONG_0 || pp >= PINGPONG_MAX)))
>>>> +               return;
>>>
>>> I'd say, this is useless. We don't have such checks in other
>>> bind_pingpong_blk() callbacks.
>>>
>>> Also there should be a guarding check for DPU >= 5.0 either here or at
>>> the ops init.
>>>
>>
>> Will add it at ops init
>>
>>>> +
>>>> +       c = &ctx->hw;
>>>> +
>>>> +       if (enable)
>>>> +               mux_cfg = (pp - PINGPONG_0) & 0x7;
>>>> +
>>>> +       DPU_REG_WRITE(c, CDM_MUX, mux_cfg);
>>>> +}
>>>> +
>>>> +static void _setup_cdm_ops(struct dpu_hw_cdm_ops *ops, unsigned long features)
>>>
>>> Please inline
>>>
>>
>> OK
>>
>>>> +{
>>>> +       ops->setup_csc_data = dpu_hw_cdm_setup_csc_10bit;
>>>> +       ops->setup_cdwn = dpu_hw_cdm_setup_cdwn;
>>>> +       ops->enable = dpu_hw_cdm_enable;
>>>> +       ops->disable = dpu_hw_cdm_disable;
>>>> +       ops->bind_pingpong_blk = dpu_hw_cdm_bind_pingpong_blk;
>>>
>>> As you seem to call this function directly, we might as well drop the
>>> callback from the ops.
>>>
>>
>> There are two paths for the bind_pingpong_blk(). One is absorbed within
>> cdm_enable and cdm_disable calls to bind and unbind the pingpong resp.
>> And yes, for that we dont need a separate ops as its within the same file.
>>
>> This will handle cases where we transition from YUV to non-YUV cases and
>> vice-versa without an encoder disable in between which I believe happens
>> in the IGT cases.
>>
>> But the dpu_encoder_helper_phys_cleanup() path is only in the encoder
>> disable() path without a non-YUV frame in the middle so lets say we were
>> in YUV mode but then just disabled the encoder we do need the cleanup
>> there and since thats outside of the dpu_hw_cdm, we do need this op.
>>
>> I agree we need to protect this with the DPU revision check.
>>
>>>> +}
>>>> +
>>>> +struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cfg, void __iomem *addr)
>>>> +{
>>>> +       struct dpu_hw_cdm *c;
>>>> +
>>>> +       c = kzalloc(sizeof(*c), GFP_KERNEL);
>>>> +       if (!c)
>>>> +               return ERR_PTR(-ENOMEM);
>>>> +
>>>> +       c->hw.blk_addr = addr + cfg->base;
>>>> +       c->hw.log_mask = DPU_DBG_MASK_CDM;
>>>> +
>>>> +       /* Assign ops */
>>>> +       c->idx = cfg->id;
>>>> +       c->caps = cfg;
>>>> +       _setup_cdm_ops(&c->ops, c->caps->features);
>>>> +
>>>> +       return c;
>>>> +}
>>>> +
>>>> +void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm)
>>>> +{
>>>> +       kfree(cdm);
>>>
>>> I'd prefer not to introduce another manual kzalloc/kfree pair, see
>>> https://patchwork.freedesktop.org/series/120366/
>>>
>>
>> I recall I did not want to have a manual kzalloc/kfree pair. But the
>> issue was I think this series was not merged that time (and is isnt
>> merged now either)
> 
> No response, no reviews since 15th August. Today is the 1st of December.
> 
> I'm close to deciding that unreviewed series have no issues and start
> showing them to -next after a grace period of 1 month.
> 
>> and this is the one which passes drm_dev to
>> dpu_rm_init. I thought maybe it was easier for you to absorb this change
>> into that series instead of me pulling that whole series to make this
>> one compile as we will not be adding new HW blocks after this for the
>> next 2 cycles. It will only be using existing ones.
>>
>> If its too much trouble for you, I will rebase on top of that series but
>> I am pretty sure you will have to rebase and post that again anyway on
>> top of the current msm-next.
>>
>> I am also going to do the same thing now with this series.
>>

There were 4 patches in that series which didnt get a R-b. Perhaps 
jessica can finish the reviews which she started on that one.

Leaving her a note on IRC would not have hurt like its a common practice 
sometimes with other reviewers.

Now, do you want to rebase this on msm-next and re-send so that I can 
rebase on top of yours?

>> So we can just decide that in whose rebase we will handle it.
>>
>>>> +}
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
>>>> new file mode 100644
>>>> index 000000000000..da60893a5c02
>>>> --- /dev/null
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
>>>> @@ -0,0 +1,135 @@
>>>> +/* SPDX-License-Identifier: GPL-2.0-only */
>>>> +/*
>>>> + * Copyright (c) 2023, The Linux Foundation. All rights reserved.
>>>> + */
>>>> +
>>>> +#ifndef _DPU_HW_CDM_H
>>>> +#define _DPU_HW_CDM_H
>>>> +
>>>> +#include "dpu_hw_mdss.h"
>>>> +#include "dpu_hw_top.h"
>>>> +
>>>> +struct dpu_hw_cdm;
>>>> +
>>>> +struct dpu_hw_cdm_cfg {
>>>> +       u32 output_width;
>>>> +       u32 output_height;
>>>> +       u32 output_bit_depth;
>>>> +       u32 h_cdwn_type;
>>>> +       u32 v_cdwn_type;
>>>> +       const struct dpu_format *output_fmt;
>>>> +       u32 output_type;
>>>> +       int pp_id;
>>>> +};
>>>> +
>>>> +enum dpu_hw_cdwn_type {
>>>> +       CDM_CDWN_DISABLE,
>>>> +       CDM_CDWN_PIXEL_DROP,
>>>> +       CDM_CDWN_AVG,
>>>> +       CDM_CDWN_COSITE,
>>>> +       CDM_CDWN_OFFSITE,
>>>> +};
>>>> +
>>>> +enum dpu_hw_cdwn_output_type {
>>>> +       CDM_CDWN_OUTPUT_HDMI,
>>>> +       CDM_CDWN_OUTPUT_WB,
>>>> +};
>>>> +
>>>> +enum dpu_hw_cdwn_output_bit_depth {
>>>> +       CDM_CDWN_OUTPUT_8BIT,
>>>> +       CDM_CDWN_OUTPUT_10BIT,
>>>> +};
>>>> +
>>>> +/**
>>>> + * struct dpu_hw_cdm_ops : Interface to the chroma down Hw driver functions
>>>> + *                         Assumption is these functions will be called after
>>>> + *                         clocks are enabled
>>>> + *  @setup_csc:            Programs the csc matrix
>>>> + *  @setup_cdwn:           Sets up the chroma down sub module
>>>> + *  @enable:               Enables the output to interface and programs the
>>>> + *                         output packer
>>>> + *  @disable:              Puts the cdm in bypass mode
>>>> + *  @bind_pingpong_blk:    enable/disable the connection with pingpong which
>>>> + *                         will feed pixels to this cdm
>>>> + */
>>>> +struct dpu_hw_cdm_ops {
>>>> +       /**
>>>> +        * Programs the CSC matrix for conversion from RGB space to YUV space,
>>>> +        * it is optional to call this function as this matrix is automatically
>>>> +        * set during initialization, user should call this if it wants
>>>> +        * to program a different matrix than default matrix.
>>>> +        * @cdm:          Pointer to the chroma down context structure
>>>> +        * @data          Pointer to CSC configuration data
>>>> +        * return:        0 if success; error code otherwise
>>>> +        */
>>>> +       int (*setup_csc_data)(struct dpu_hw_cdm *cdm, struct dpu_csc_cfg *data);
>>>> +
>>>> +       /**
>>>> +        * Programs the Chroma downsample part.
>>>> +        * @cdm         Pointer to chroma down context
>>>> +        * @cfg         Pointer to the cdm configuration data
>>>> +        */
>>>> +       int (*setup_cdwn)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
>>>> +
>>>> +       /**
>>>> +        * Enable the CDM module
>>>> +        * @cdm         Pointer to chroma down context
>>>> +        */
>>>> +       int (*enable)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
>>>> +
>>>> +       /**
>>>> +        * Disable the CDM module
>>>> +        * @cdm         Pointer to chroma down context
>>>> +        */
>>>> +       void (*disable)(struct dpu_hw_cdm *cdm);
>>>> +
>>>> +       /**
>>>> +        * Enable/disable the connection with pingpong
>>>> +        * @cdm         Pointer to chroma down context
>>>> +        * @enable      Enable/disable control
>>>> +        * @pp          pingpong block id.
>>>> +        */
>>>> +       void (*bind_pingpong_blk)(struct dpu_hw_cdm *cdm, bool enable,
>>>> +                                 const enum dpu_pingpong pp);
>>>> +};
>>>> +
>>>> +/**
>>>> + * struct dpu_hw_cdm - cdm description
>>>> + * @base: Hardware block base structure
>>>> + * @hw: Block hardware details
>>>> + * @idx: CDM index
>>>> + * @caps: Pointer to cdm_cfg
>>>> + * @ops: handle to operations possible for this CDM
>>>> + */
>>>> +struct dpu_hw_cdm {
>>>> +       struct dpu_hw_blk base;
>>>> +       struct dpu_hw_blk_reg_map hw;
>>>> +
>>>> +       /* chroma down */
>>>> +       const struct dpu_cdm_cfg *caps;
>>>> +       enum  dpu_cdm  idx;
>>>> +
>>>> +       /* ops */
>>>> +       struct dpu_hw_cdm_ops ops;
>>>> +};
>>>> +
>>>> +/**
>>>> + * dpu_hw_cdm_init - initializes the cdm hw driver object.
>>>> + * should be called once before accessing every cdm.
>>>> + * @cdm: CDM catalog entry for which driver object is required
>>>> + * @addr :   mapped register io address of MDSS
>>>> + */
>>>> +struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cdm, void __iomem *addr);
>>>> +
>>>> +/**
>>>> + * dpu_hw_cdm_destroy - destroys cdm driver context
>>>> + * @cdm:   Pointer to cdm driver context returned by dpu_hw_cdm_init
>>>> + */
>>>> +void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm);
>>>> +
>>>> +static inline struct dpu_hw_cdm *to_dpu_hw_cdm(struct dpu_hw_blk *hw)
>>>> +{
>>>> +       return container_of(hw, struct dpu_hw_cdm, base);
>>>> +}
>>>> +
>>>> +#endif /*_DPU_HW_CDM_H */
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>>>> index 4d6dba18caf0..34f943102499 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>>>> @@ -463,6 +463,7 @@ struct dpu_mdss_color {
>>>>    #define DPU_DBG_MASK_ROT      (1 << 9)
>>>>    #define DPU_DBG_MASK_DSPP     (1 << 10)
>>>>    #define DPU_DBG_MASK_DSC      (1 << 11)
>>>> +#define DPU_DBG_MASK_CDM      (1 << 12)
>>>>
>>>>    /**
>>>>     * struct dpu_hw_tear_check - Struct contains parameters to configure
>>>> --
>>>> 2.40.1
>>>>
>>>
>>>
>>> --
>>> With best wishes
>>> Dmitry
> 
> 
> 

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

* Re: [PATCH 11/16] drm/msm/dpu: add an API to setup the CDM block for writeback
  2023-12-01  7:20         ` Dmitry Baryshkov
@ 2023-12-01 19:04           ` Abhinav Kumar
  -1 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-12-01 19:04 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel



On 11/30/2023 11:20 PM, Dmitry Baryshkov wrote:
> On Fri, 1 Dec 2023 at 02:41, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 8/30/2023 5:11 PM, Dmitry Baryshkov wrote:
>>> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>>>
>>>> Add an API dpu_encoder_helper_phys_setup_cdm() which can be used by
>>>> the writeback encoder to setup the CDM block.
>>>>
>>>> Currently, this is defined and used within the writeback's physical
>>>> encoder layer however, the function can be modified to be used to setup
>>>> the CDM block even for non-writeback interfaces.
>>>>
>>>> Until those modifications are planned and made, keep it local to
>>>> writeback.
>>>>
>>>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>>>> ---
>>>>    .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   3 +
>>>>    .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 123 +++++++++++++++++-
>>>>    2 files changed, 125 insertions(+), 1 deletion(-)
>>>>
>>>> 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 510c1c41ddbc..93a8ae67beff 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>>>> @@ -16,6 +16,7 @@
>>>>    #include "dpu_hw_pingpong.h"
>>>>    #include "dpu_hw_ctl.h"
>>>>    #include "dpu_hw_top.h"
>>>> +#include "dpu_hw_cdm.h"
>>>>    #include "dpu_encoder.h"
>>>>    #include "dpu_crtc.h"
>>>>
>>>> @@ -209,6 +210,7 @@ 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
>>>> @@ -218,6 +220,7 @@ 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 4c2736c3ee6d..11935aac9fd5 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
>>>> @@ -24,6 +24,20 @@
>>>>    #define to_dpu_encoder_phys_wb(x) \
>>>>           container_of(x, struct dpu_encoder_phys_wb, base)
>>>>
>>>> +#define TO_S15D16(_x_)((_x_) << 7)
>>>> +
>>>> +static struct dpu_csc_cfg dpu_encoder_phys_wb_rgb2yuv_601l = {
>>>> +       {
>>>> +               TO_S15D16(0x0083), TO_S15D16(0x0102), TO_S15D16(0x0032),
>>>> +               TO_S15D16(0x1fb5), TO_S15D16(0x1f6c), TO_S15D16(0x00e1),
>>>> +               TO_S15D16(0x00e1), TO_S15D16(0x1f45), TO_S15D16(0x1fdc)
>>>> +       },
>>>> +       { 0x00, 0x00, 0x00 },
>>>> +       { 0x0040, 0x0200, 0x0200 },
>>>> +       { 0x000, 0x3ff, 0x000, 0x3ff, 0x000, 0x3ff },
>>>> +       { 0x040, 0x3ac, 0x040, 0x3c0, 0x040, 0x3c0 },
>>>> +};
>>>
>>> Nit: we probably need to have a single place with all dpu_csc_cfg entries.
>>>
>>
>> hmmm ... so we have YUV2RGB matrices for dpu plane and RGB2YUV matrices
>> for WB and DP.
>>
>> We can move all this to dpu_hw_util.c but lets do that in the DP series
>> as that completes the consumer list of these matrices.
> 
> Doing it earlier is usually better. Can we please do it as a part of
> this series?
> 

Would be strange as RGB2YUV matrix is not used by anyone other than WB 
till DP lands.

If you are fine with that anomaly, no concerns.

>>
>>>> +
>>>>    /**
>>>>     * dpu_encoder_phys_wb_is_master - report wb always as master encoder
>>>>     * @phys_enc:  Pointer to physical encoder
>>>> @@ -225,6 +239,112 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
>>>>           }
>>>>    }
>>>>
>>>> +/**
>>>> + * dpu_encoder_phys_wb_setup_cdp - setup chroma down sampling block
>>>> + * @phys_enc:Pointer to physical encoder
>>>> + */
>>>> +static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
>>>> +{
>>>> +       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;
>>>> +       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;
>>>> +
>>>> +       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.disable)
>>>> +                       hw_cdm->ops.disable(hw_cdm);
>>>> +
>>>> +               return;
>>>> +       }
>>>> +
>>>> +       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_fmt = dpu_fmt;
>>>> +       cdm_cfg->output_type = CDM_CDWN_OUTPUT_WB;
>>>> +       cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
>>>> +                       CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
>>>> +
>>>> +       /* 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 && hw_cdm->ops.setup_csc_data) {
>>>> +               ret = hw_cdm->ops.setup_csc_data(hw_cdm, &dpu_encoder_phys_wb_rgb2yuv_601l);
>>>> +               if (ret < 0) {
>>>> +                       DPU_ERROR("[enc:%d] failed to setup CSC; ret:%d\n",
>>>> +                                 DRMID(phys_enc->parent), ret);
>>>> +                       return;
>>>> +               }
>>>> +       }
>>>> +
>>>> +       if (hw_cdm && hw_cdm->ops.setup_cdwn) {
>>>
>>> You have checked for (!hw_cdm) several lines above. We can drop this
>>> condition here.
>>>
>>
>> Ack.
>>
>>>> +               ret = hw_cdm->ops.setup_cdwn(hw_cdm, cdm_cfg);
>>>> +               if (ret < 0) {
>>>> +                       DPU_ERROR("[enc:%d] failed to setup CDWN; ret:%d\n",
>>>> +                                 DRMID(phys_enc->parent), ret);
>>>> +                       return;
>>>> +               }
>>>> +       }
>>>> +
>>>> +       if (hw_cdm && hw_pp && hw_cdm->ops.enable) {
>>>
>>> And what if !hw_pp ? Can it happen here? No, if I understand correctly.
>>>
>>
>> I dont see any other protection for !hw_pp in this flow so would prefer
>> to keep it.
> 
> But can we end up in this function if we have no hw_pp at all?
> 

Just from code flow yes,

dpu_encoder_prepare_for_kickoff ---> phys->ops.prepare_for_kickoff ---> 
this function

None of them have !hw_pp.

But, if hw_pp failed allocation, then atomic_check will fail so the 
commit will not happen.

I was thinking of the former, if we are fine with the latter we can drop.

>>
>>>> +               cdm_cfg->pp_id = hw_pp->idx;
>>>> +               ret = hw_cdm->ops.enable(hw_cdm, cdm_cfg);
>>>
>>> As we are calling these three ops in a row, can we merge them together
>>> into a single callback to be called from dpu_encoder.c?
>>>
>>
>> Good idea. I can add a csc_cfg entry to cdm_cfg and merge all three into
>> the enable() op itself and drop the other two.
>>
>>>> +               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
>>>> @@ -348,8 +468,9 @@ static void dpu_encoder_phys_wb_setup(
>>>>
>>>>           dpu_encoder_phys_wb_setup_fb(phys_enc, fb);
>>>>
>>>> -       dpu_encoder_phys_wb_setup_ctl(phys_enc);
>>>> +       dpu_encoder_helper_phys_setup_cdm(phys_enc);
>>>>
>>>> +       dpu_encoder_phys_wb_setup_ctl(phys_enc);
>>>>    }
>>>>
>>>>    static void _dpu_encoder_phys_wb_frame_done_helper(void *arg)
>>>> --
>>>> 2.40.1
>>>>
>>>
>>>
> 
> 
> 

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

* Re: [PATCH 11/16] drm/msm/dpu: add an API to setup the CDM block for writeback
@ 2023-12-01 19:04           ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-12-01 19:04 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul



On 11/30/2023 11:20 PM, Dmitry Baryshkov wrote:
> On Fri, 1 Dec 2023 at 02:41, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 8/30/2023 5:11 PM, Dmitry Baryshkov wrote:
>>> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>>>
>>>> Add an API dpu_encoder_helper_phys_setup_cdm() which can be used by
>>>> the writeback encoder to setup the CDM block.
>>>>
>>>> Currently, this is defined and used within the writeback's physical
>>>> encoder layer however, the function can be modified to be used to setup
>>>> the CDM block even for non-writeback interfaces.
>>>>
>>>> Until those modifications are planned and made, keep it local to
>>>> writeback.
>>>>
>>>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>>>> ---
>>>>    .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   3 +
>>>>    .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 123 +++++++++++++++++-
>>>>    2 files changed, 125 insertions(+), 1 deletion(-)
>>>>
>>>> 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 510c1c41ddbc..93a8ae67beff 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
>>>> @@ -16,6 +16,7 @@
>>>>    #include "dpu_hw_pingpong.h"
>>>>    #include "dpu_hw_ctl.h"
>>>>    #include "dpu_hw_top.h"
>>>> +#include "dpu_hw_cdm.h"
>>>>    #include "dpu_encoder.h"
>>>>    #include "dpu_crtc.h"
>>>>
>>>> @@ -209,6 +210,7 @@ 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
>>>> @@ -218,6 +220,7 @@ 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 4c2736c3ee6d..11935aac9fd5 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
>>>> @@ -24,6 +24,20 @@
>>>>    #define to_dpu_encoder_phys_wb(x) \
>>>>           container_of(x, struct dpu_encoder_phys_wb, base)
>>>>
>>>> +#define TO_S15D16(_x_)((_x_) << 7)
>>>> +
>>>> +static struct dpu_csc_cfg dpu_encoder_phys_wb_rgb2yuv_601l = {
>>>> +       {
>>>> +               TO_S15D16(0x0083), TO_S15D16(0x0102), TO_S15D16(0x0032),
>>>> +               TO_S15D16(0x1fb5), TO_S15D16(0x1f6c), TO_S15D16(0x00e1),
>>>> +               TO_S15D16(0x00e1), TO_S15D16(0x1f45), TO_S15D16(0x1fdc)
>>>> +       },
>>>> +       { 0x00, 0x00, 0x00 },
>>>> +       { 0x0040, 0x0200, 0x0200 },
>>>> +       { 0x000, 0x3ff, 0x000, 0x3ff, 0x000, 0x3ff },
>>>> +       { 0x040, 0x3ac, 0x040, 0x3c0, 0x040, 0x3c0 },
>>>> +};
>>>
>>> Nit: we probably need to have a single place with all dpu_csc_cfg entries.
>>>
>>
>> hmmm ... so we have YUV2RGB matrices for dpu plane and RGB2YUV matrices
>> for WB and DP.
>>
>> We can move all this to dpu_hw_util.c but lets do that in the DP series
>> as that completes the consumer list of these matrices.
> 
> Doing it earlier is usually better. Can we please do it as a part of
> this series?
> 

Would be strange as RGB2YUV matrix is not used by anyone other than WB 
till DP lands.

If you are fine with that anomaly, no concerns.

>>
>>>> +
>>>>    /**
>>>>     * dpu_encoder_phys_wb_is_master - report wb always as master encoder
>>>>     * @phys_enc:  Pointer to physical encoder
>>>> @@ -225,6 +239,112 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
>>>>           }
>>>>    }
>>>>
>>>> +/**
>>>> + * dpu_encoder_phys_wb_setup_cdp - setup chroma down sampling block
>>>> + * @phys_enc:Pointer to physical encoder
>>>> + */
>>>> +static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
>>>> +{
>>>> +       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;
>>>> +       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;
>>>> +
>>>> +       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.disable)
>>>> +                       hw_cdm->ops.disable(hw_cdm);
>>>> +
>>>> +               return;
>>>> +       }
>>>> +
>>>> +       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_fmt = dpu_fmt;
>>>> +       cdm_cfg->output_type = CDM_CDWN_OUTPUT_WB;
>>>> +       cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
>>>> +                       CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
>>>> +
>>>> +       /* 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 && hw_cdm->ops.setup_csc_data) {
>>>> +               ret = hw_cdm->ops.setup_csc_data(hw_cdm, &dpu_encoder_phys_wb_rgb2yuv_601l);
>>>> +               if (ret < 0) {
>>>> +                       DPU_ERROR("[enc:%d] failed to setup CSC; ret:%d\n",
>>>> +                                 DRMID(phys_enc->parent), ret);
>>>> +                       return;
>>>> +               }
>>>> +       }
>>>> +
>>>> +       if (hw_cdm && hw_cdm->ops.setup_cdwn) {
>>>
>>> You have checked for (!hw_cdm) several lines above. We can drop this
>>> condition here.
>>>
>>
>> Ack.
>>
>>>> +               ret = hw_cdm->ops.setup_cdwn(hw_cdm, cdm_cfg);
>>>> +               if (ret < 0) {
>>>> +                       DPU_ERROR("[enc:%d] failed to setup CDWN; ret:%d\n",
>>>> +                                 DRMID(phys_enc->parent), ret);
>>>> +                       return;
>>>> +               }
>>>> +       }
>>>> +
>>>> +       if (hw_cdm && hw_pp && hw_cdm->ops.enable) {
>>>
>>> And what if !hw_pp ? Can it happen here? No, if I understand correctly.
>>>
>>
>> I dont see any other protection for !hw_pp in this flow so would prefer
>> to keep it.
> 
> But can we end up in this function if we have no hw_pp at all?
> 

Just from code flow yes,

dpu_encoder_prepare_for_kickoff ---> phys->ops.prepare_for_kickoff ---> 
this function

None of them have !hw_pp.

But, if hw_pp failed allocation, then atomic_check will fail so the 
commit will not happen.

I was thinking of the former, if we are fine with the latter we can drop.

>>
>>>> +               cdm_cfg->pp_id = hw_pp->idx;
>>>> +               ret = hw_cdm->ops.enable(hw_cdm, cdm_cfg);
>>>
>>> As we are calling these three ops in a row, can we merge them together
>>> into a single callback to be called from dpu_encoder.c?
>>>
>>
>> Good idea. I can add a csc_cfg entry to cdm_cfg and merge all three into
>> the enable() op itself and drop the other two.
>>
>>>> +               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
>>>> @@ -348,8 +468,9 @@ static void dpu_encoder_phys_wb_setup(
>>>>
>>>>           dpu_encoder_phys_wb_setup_fb(phys_enc, fb);
>>>>
>>>> -       dpu_encoder_phys_wb_setup_ctl(phys_enc);
>>>> +       dpu_encoder_helper_phys_setup_cdm(phys_enc);
>>>>
>>>> +       dpu_encoder_phys_wb_setup_ctl(phys_enc);
>>>>    }
>>>>
>>>>    static void _dpu_encoder_phys_wb_frame_done_helper(void *arg)
>>>> --
>>>> 2.40.1
>>>>
>>>
>>>
> 
> 
> 

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

* Re: [PATCH 06/16] drm/msm/dpu: add dpu_hw_cdm abstraction for CDM block
  2023-12-01 18:19           ` Abhinav Kumar
@ 2023-12-01 21:10             ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-12-01 21:10 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-kernel, linux-arm-msm

On Fri, 1 Dec 2023 at 20:19, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 11/30/2023 11:05 PM, Dmitry Baryshkov wrote:
> > On Fri, 1 Dec 2023 at 01:36, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >>
> >>
> >> On 8/30/2023 5:00 PM, Dmitry Baryshkov wrote:
> >>> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>>>
> >>>> CDM block comes with its own set of registers and operations
> >>>> which can be done. In-line with other hardware sub-blocks, this
> >>>> change adds the dpu_hw_cdm abstraction for the CDM block.
> >>>>
> >>>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> >>>> ---
> >>>>    drivers/gpu/drm/msm/Makefile                |   1 +
> >>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c  | 272 ++++++++++++++++++++
> >>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h  | 135 ++++++++++
> >>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h |   1 +
> >>>>    4 files changed, 409 insertions(+)
> >>>>    create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
> >>>>    create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
> >>>>
> >>>> diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
> >>>> index 8d02d8c33069..2010cb1ca995 100644
> >>>> --- a/drivers/gpu/drm/msm/Makefile
> >>>> +++ b/drivers/gpu/drm/msm/Makefile
> >>>> @@ -63,6 +63,7 @@ msm-$(CONFIG_DRM_MSM_DPU) += \
> >>>>           disp/dpu1/dpu_encoder_phys_wb.o \
> >>>>           disp/dpu1/dpu_formats.o \
> >>>>           disp/dpu1/dpu_hw_catalog.o \
> >>>> +       disp/dpu1/dpu_hw_cdm.o \
> >>>>           disp/dpu1/dpu_hw_ctl.o \
> >>>>           disp/dpu1/dpu_hw_dsc.o \
> >>>>           disp/dpu1/dpu_hw_dsc_1_2.o \
> >>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
> >>>> new file mode 100644
> >>>> index 000000000000..a2f7ee8f54e4
> >>>> --- /dev/null
> >>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
> >>>> @@ -0,0 +1,272 @@
> >>>> +// SPDX-License-Identifier: GPL-2.0-only
> >>>> +/*
> >>>> + * Copyright (c) 2023, The Linux Foundation. All rights reserved.
> >>>> + */
> >>>> +
> >>>> +#include <drm/drm_managed.h>
> >>>> +
> >>>> +#include "dpu_hw_mdss.h"
> >>>> +#include "dpu_hw_util.h"
> >>>> +#include "dpu_hw_catalog.h"
> >>>> +#include "dpu_hw_cdm.h"
> >>>> +#include "dpu_kms.h"
> >>>> +
> >>>> +#define CDM_CSC_10_OPMODE                  0x000
> >>>> +#define CDM_CSC_10_BASE                    0x004
> >>>> +
> >>>> +#define CDM_CDWN2_OP_MODE                  0x100
> >>>> +#define CDM_CDWN2_CLAMP_OUT                0x104
> >>>> +#define CDM_CDWN2_PARAMS_3D_0              0x108
> >>>> +#define CDM_CDWN2_PARAMS_3D_1              0x10C
> >>>> +#define CDM_CDWN2_COEFF_COSITE_H_0         0x110
> >>>> +#define CDM_CDWN2_COEFF_COSITE_H_1         0x114
> >>>> +#define CDM_CDWN2_COEFF_COSITE_H_2         0x118
> >>>> +#define CDM_CDWN2_COEFF_OFFSITE_H_0        0x11C
> >>>> +#define CDM_CDWN2_COEFF_OFFSITE_H_1        0x120
> >>>> +#define CDM_CDWN2_COEFF_OFFSITE_H_2        0x124
> >>>> +#define CDM_CDWN2_COEFF_COSITE_V           0x128
> >>>> +#define CDM_CDWN2_COEFF_OFFSITE_V          0x12C
> >>>> +#define CDM_CDWN2_OUT_SIZE                 0x130
> >>>> +
> >>>> +#define CDM_HDMI_PACK_OP_MODE              0x200
> >>>> +#define CDM_CSC_10_MATRIX_COEFF_0          0x004
> >>>> +
> >>>> +#define CDM_MUX                            0x224
> >>>> +
> >>>> +/**
> >>>> + * Horizontal coefficients for cosite chroma downscale
> >>>> + * s13 representation of coefficients
> >>>> + */
> >>>> +static u32 cosite_h_coeff[] = {0x00000016, 0x000001cc, 0x0100009e};
> >>>> +
> >>>> +/**
> >>>> + * Horizontal coefficients for offsite chroma downscale
> >>>> + */
> >>>> +static u32 offsite_h_coeff[] = {0x000b0005, 0x01db01eb, 0x00e40046};
> >>>> +
> >>>> +/**
> >>>> + * Vertical coefficients for cosite chroma downscale
> >>>> + */
> >>>> +static u32 cosite_v_coeff[] = {0x00080004};
> >>>> +/**
> >>>> + * Vertical coefficients for offsite chroma downscale
> >>>> + */
> >>>> +static u32 offsite_v_coeff[] = {0x00060002};
> >>>> +
> >>>> +static int dpu_hw_cdm_setup_csc_10bit(struct dpu_hw_cdm *ctx, struct dpu_csc_cfg *data)
> >>>> +{
> >>>> +       dpu_hw_csc_setup(&ctx->hw, CDM_CSC_10_MATRIX_COEFF_0, data, true);
> >>>
> >>> Where was this defined?
> >>>
> >>
> >> Its in this file itself
> >>
> >> +#define CDM_CSC_10_MATRIX_COEFF_0          0x004
> >>
> >>>> +
> >>>> +       return 0;
> >>>> +}
> >>>> +
> >>>> +static int dpu_hw_cdm_setup_cdwn(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cfg)
> >>>> +{
> >>>> +       struct dpu_hw_blk_reg_map *c = &ctx->hw;
> >>>> +       u32 opmode = 0;
> >>>> +       u32 out_size = 0;
> >>>> +
> >>>> +       if (cfg->output_bit_depth == CDM_CDWN_OUTPUT_10BIT)
> >>>> +               opmode &= ~BIT(7);
> >>>> +       else
> >>>> +               opmode |= BIT(7);
> >>>> +
> >>>> +       /* ENABLE DWNS_H bit */
> >>>> +       opmode |= BIT(1);
> >>>> +
> >>>> +       switch (cfg->h_cdwn_type) {
> >>>> +       case CDM_CDWN_DISABLE:
> >>>> +               /* CLEAR METHOD_H field */
> >>>> +               opmode &= ~(0x18);
> >>>> +               /* CLEAR DWNS_H bit */
> >>>> +               opmode &= ~BIT(1);
> >>>> +               break;
> >>>> +       case CDM_CDWN_PIXEL_DROP:
> >>>> +               /* Clear METHOD_H field (pixel drop is 0) */
> >>>> +               opmode &= ~(0x18);
> >>>> +               break;
> >>>> +       case CDM_CDWN_AVG:
> >>>> +               /* Clear METHOD_H field (Average is 0x1) */
> >>>> +               opmode &= ~(0x18);
> >>>> +               opmode |= (0x1 << 0x3);
> >>>> +               break;
> >>>> +       case CDM_CDWN_COSITE:
> >>>> +               /* Clear METHOD_H field (Average is 0x2) */
> >>>> +               opmode &= ~(0x18);
> >>>> +               opmode |= (0x2 << 0x3);
> >>>> +               /* Co-site horizontal coefficients */
> >>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_0,
> >>>> +                               cosite_h_coeff[0]);
> >>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_1,
> >>>> +                               cosite_h_coeff[1]);
> >>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_2,
> >>>> +                               cosite_h_coeff[2]);
> >>>> +               break;
> >>>> +       case CDM_CDWN_OFFSITE:
> >>>> +               /* Clear METHOD_H field (Average is 0x3) */
> >>>> +               opmode &= ~(0x18);
> >>>> +               opmode |= (0x3 << 0x3);
> >>>> +
> >>>> +               /* Off-site horizontal coefficients */
> >>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_0,
> >>>> +                               offsite_h_coeff[0]);
> >>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_1,
> >>>> +                               offsite_h_coeff[1]);
> >>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_2,
> >>>> +                               offsite_h_coeff[2]);
> >>>> +               break;
> >>>> +       default:
> >>>> +               pr_err("%s invalid horz down sampling type\n", __func__);
> >>>> +               return -EINVAL;
> >>>> +       }
> >>>> +
> >>>> +       /* ENABLE DWNS_V bit */
> >>>> +       opmode |= BIT(2);
> >>>> +
> >>>> +       switch (cfg->v_cdwn_type) {
> >>>> +       case CDM_CDWN_DISABLE:
> >>>> +               /* CLEAR METHOD_V field */
> >>>> +               opmode &= ~(0x60);
> >>>
> >>> #define, GENMASK
> >>>
> >>>> +               /* CLEAR DWNS_V bit */
> >>>> +               opmode &= ~BIT(2);
> >>>> +               break;
> >>>> +       case CDM_CDWN_PIXEL_DROP:
> >>>> +               /* Clear METHOD_V field (pixel drop is 0) */
> >>>> +               opmode &= ~(0x60);
> >>>> +               break;
> >>>> +       case CDM_CDWN_AVG:
> >>>> +               /* Clear METHOD_V field (Average is 0x1) */
> >>>> +               opmode &= ~(0x60);
> >>>> +               opmode |= (0x1 << 0x5);
> >>>
> >>> #define
> >>>
> >>>> +               break;
> >>>> +       case CDM_CDWN_COSITE:
> >>>> +               /* Clear METHOD_V field (Average is 0x2) */
> >>>> +               opmode &= ~(0x60);
> >>>> +               opmode |= (0x2 << 0x5);
> >>>> +               /* Co-site vertical coefficients */
> >>>> +               DPU_REG_WRITE(c,
> >>>> +                               CDM_CDWN2_COEFF_COSITE_V,
> >>>> +                               cosite_v_coeff[0]);
> >>>
> >>> align to opening bracket
> >>>
> >>>> +               break;
> >>>> +       case CDM_CDWN_OFFSITE:
> >>>> +               /* Clear METHOD_V field (Average is 0x3) */
> >>>> +               opmode &= ~(0x60);
> >>>> +               opmode |= (0x3 << 0x5);
> >>>> +
> >>>> +               /* Off-site vertical coefficients */
> >>>> +               DPU_REG_WRITE(c,
> >>>> +                               CDM_CDWN2_COEFF_OFFSITE_V,
> >>>> +                               offsite_v_coeff[0]);
> >>>
> >>> align to opening bracket
> >>>
> >>>> +               break;
> >>>> +       default:
> >>>> +               return -EINVAL;
> >>>> +       }
> >>>> +
> >>>> +       if (cfg->v_cdwn_type || cfg->h_cdwn_type)
> >>>> +               opmode |= BIT(0); /* EN CDWN module */
> >>>
> >>> #define
> >>>
> >>
> >> Ack to all comments about GENMASK and #define
> >>
> >>>> +       else
> >>>> +               opmode &= ~BIT(0);
> >>>> +
> >>>> +       out_size = (cfg->output_width & 0xFFFF) |
> >>>> +               ((cfg->output_height & 0xFFFF) << 16);
> >>>> +       DPU_REG_WRITE(c, CDM_CDWN2_OUT_SIZE, out_size);
> >>>> +       DPU_REG_WRITE(c, CDM_CDWN2_OP_MODE, opmode);
> >>>> +       DPU_REG_WRITE(c, CDM_CDWN2_CLAMP_OUT,
> >>>> +                       ((0x3FF << 16) | 0x0));
> >>>> +
> >>>> +       return 0;
> >>>> +}
> >>>> +
> >>>> +int dpu_hw_cdm_enable(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cdm)
> >>>> +{
> >>>> +       struct dpu_hw_blk_reg_map *c = &ctx->hw;
> >>>> +       const struct dpu_format *fmt;
> >>>> +       u32 opmode = 0;
> >>>> +       u32 csc = 0;
> >>>> +
> >>>> +       if (!ctx || !cdm)
> >>>> +               return -EINVAL;
> >>>> +
> >>>> +       fmt = cdm->output_fmt;
> >>>> +
> >>>> +       if (!DPU_FORMAT_IS_YUV(fmt))
> >>>> +               return -EINVAL;
> >>>> +
> >>>> +       if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
> >>>> +               if (fmt->chroma_sample != DPU_CHROMA_H1V2)
> >>>> +                       return -EINVAL; /*unsupported format */
> >>>> +               opmode = BIT(0);
> >>>> +               opmode |= (fmt->chroma_sample << 1);
> >>>> +       }
> >>>> +
> >>>> +       csc |= BIT(2);
> >>>> +       csc &= ~BIT(1);
> >>>> +       csc |= BIT(0);
> >>>
> >>> Can we get some sensible #defines for all this magic, please?
> >>>
> >>
> >> Ack, will do.
> >>
> >>>> +
> >>>> +       if (ctx && ctx->ops.bind_pingpong_blk)
> >>>> +               ctx->ops.bind_pingpong_blk(ctx, true,
> >>>> +                               cdm->pp_id);
> >>>> +
> >>>> +       DPU_REG_WRITE(c, CDM_CSC_10_OPMODE, csc);
> >>>> +       DPU_REG_WRITE(c, CDM_HDMI_PACK_OP_MODE, opmode);
> >>>> +       return 0;
> >>>> +}
> >>>> +
> >>>> +void dpu_hw_cdm_disable(struct dpu_hw_cdm *ctx)
> >>>> +{
> >>>> +       if (!ctx)
> >>>> +               return;
> >>>> +
> >>>> +       if (ctx && ctx->ops.bind_pingpong_blk)
> >>>> +               ctx->ops.bind_pingpong_blk(ctx, false, 0);
> >>>
> >>> PINGPONG_NONE.
> >>>
> >>>> +}
> >>>> +
> >>>> +static void dpu_hw_cdm_bind_pingpong_blk(struct dpu_hw_cdm *ctx, bool enable,
> >>>> +                                        const enum dpu_pingpong pp)
> >>>> +{
> >>>> +       struct dpu_hw_blk_reg_map *c;
> >>>> +       int mux_cfg = 0xF;
> >>>> +
> >>>> +       if (!ctx || (enable && (pp < PINGPONG_0 || pp >= PINGPONG_MAX)))
> >>>> +               return;
> >>>
> >>> I'd say, this is useless. We don't have such checks in other
> >>> bind_pingpong_blk() callbacks.
> >>>
> >>> Also there should be a guarding check for DPU >= 5.0 either here or at
> >>> the ops init.
> >>>
> >>
> >> Will add it at ops init
> >>
> >>>> +
> >>>> +       c = &ctx->hw;
> >>>> +
> >>>> +       if (enable)
> >>>> +               mux_cfg = (pp - PINGPONG_0) & 0x7;
> >>>> +
> >>>> +       DPU_REG_WRITE(c, CDM_MUX, mux_cfg);
> >>>> +}
> >>>> +
> >>>> +static void _setup_cdm_ops(struct dpu_hw_cdm_ops *ops, unsigned long features)
> >>>
> >>> Please inline
> >>>
> >>
> >> OK
> >>
> >>>> +{
> >>>> +       ops->setup_csc_data = dpu_hw_cdm_setup_csc_10bit;
> >>>> +       ops->setup_cdwn = dpu_hw_cdm_setup_cdwn;
> >>>> +       ops->enable = dpu_hw_cdm_enable;
> >>>> +       ops->disable = dpu_hw_cdm_disable;
> >>>> +       ops->bind_pingpong_blk = dpu_hw_cdm_bind_pingpong_blk;
> >>>
> >>> As you seem to call this function directly, we might as well drop the
> >>> callback from the ops.
> >>>
> >>
> >> There are two paths for the bind_pingpong_blk(). One is absorbed within
> >> cdm_enable and cdm_disable calls to bind and unbind the pingpong resp.
> >> And yes, for that we dont need a separate ops as its within the same file.
> >>
> >> This will handle cases where we transition from YUV to non-YUV cases and
> >> vice-versa without an encoder disable in between which I believe happens
> >> in the IGT cases.
> >>
> >> But the dpu_encoder_helper_phys_cleanup() path is only in the encoder
> >> disable() path without a non-YUV frame in the middle so lets say we were
> >> in YUV mode but then just disabled the encoder we do need the cleanup
> >> there and since thats outside of the dpu_hw_cdm, we do need this op.
> >>
> >> I agree we need to protect this with the DPU revision check.
> >>
> >>>> +}
> >>>> +
> >>>> +struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cfg, void __iomem *addr)
> >>>> +{
> >>>> +       struct dpu_hw_cdm *c;
> >>>> +
> >>>> +       c = kzalloc(sizeof(*c), GFP_KERNEL);
> >>>> +       if (!c)
> >>>> +               return ERR_PTR(-ENOMEM);
> >>>> +
> >>>> +       c->hw.blk_addr = addr + cfg->base;
> >>>> +       c->hw.log_mask = DPU_DBG_MASK_CDM;
> >>>> +
> >>>> +       /* Assign ops */
> >>>> +       c->idx = cfg->id;
> >>>> +       c->caps = cfg;
> >>>> +       _setup_cdm_ops(&c->ops, c->caps->features);
> >>>> +
> >>>> +       return c;
> >>>> +}
> >>>> +
> >>>> +void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm)
> >>>> +{
> >>>> +       kfree(cdm);
> >>>
> >>> I'd prefer not to introduce another manual kzalloc/kfree pair, see
> >>> https://patchwork.freedesktop.org/series/120366/
> >>>
> >>
> >> I recall I did not want to have a manual kzalloc/kfree pair. But the
> >> issue was I think this series was not merged that time (and is isnt
> >> merged now either)
> >
> > No response, no reviews since 15th August. Today is the 1st of December.
> >
> > I'm close to deciding that unreviewed series have no issues and start
> > showing them to -next after a grace period of 1 month.
> >
> >> and this is the one which passes drm_dev to
> >> dpu_rm_init. I thought maybe it was easier for you to absorb this change
> >> into that series instead of me pulling that whole series to make this
> >> one compile as we will not be adding new HW blocks after this for the
> >> next 2 cycles. It will only be using existing ones.
> >>
> >> If its too much trouble for you, I will rebase on top of that series but
> >> I am pretty sure you will have to rebase and post that again anyway on
> >> top of the current msm-next.
> >>
> >> I am also going to do the same thing now with this series.
> >>
>
> There were 4 patches in that series which didnt get a R-b. Perhaps
> jessica can finish the reviews which she started on that one.
>
> Leaving her a note on IRC would not have hurt like its a common practice
> sometimes with other reviewers.
>
> Now, do you want to rebase this on msm-next and re-send so that I can
> rebase on top of yours?

Sure, I'll do it now.

>
> >> So we can just decide that in whose rebase we will handle it.
> >>
> >>>> +}
> >>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
> >>>> new file mode 100644
> >>>> index 000000000000..da60893a5c02
> >>>> --- /dev/null
> >>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
> >>>> @@ -0,0 +1,135 @@
> >>>> +/* SPDX-License-Identifier: GPL-2.0-only */
> >>>> +/*
> >>>> + * Copyright (c) 2023, The Linux Foundation. All rights reserved.
> >>>> + */
> >>>> +
> >>>> +#ifndef _DPU_HW_CDM_H
> >>>> +#define _DPU_HW_CDM_H
> >>>> +
> >>>> +#include "dpu_hw_mdss.h"
> >>>> +#include "dpu_hw_top.h"
> >>>> +
> >>>> +struct dpu_hw_cdm;
> >>>> +
> >>>> +struct dpu_hw_cdm_cfg {
> >>>> +       u32 output_width;
> >>>> +       u32 output_height;
> >>>> +       u32 output_bit_depth;
> >>>> +       u32 h_cdwn_type;
> >>>> +       u32 v_cdwn_type;
> >>>> +       const struct dpu_format *output_fmt;
> >>>> +       u32 output_type;
> >>>> +       int pp_id;
> >>>> +};
> >>>> +
> >>>> +enum dpu_hw_cdwn_type {
> >>>> +       CDM_CDWN_DISABLE,
> >>>> +       CDM_CDWN_PIXEL_DROP,
> >>>> +       CDM_CDWN_AVG,
> >>>> +       CDM_CDWN_COSITE,
> >>>> +       CDM_CDWN_OFFSITE,
> >>>> +};
> >>>> +
> >>>> +enum dpu_hw_cdwn_output_type {
> >>>> +       CDM_CDWN_OUTPUT_HDMI,
> >>>> +       CDM_CDWN_OUTPUT_WB,
> >>>> +};
> >>>> +
> >>>> +enum dpu_hw_cdwn_output_bit_depth {
> >>>> +       CDM_CDWN_OUTPUT_8BIT,
> >>>> +       CDM_CDWN_OUTPUT_10BIT,
> >>>> +};
> >>>> +
> >>>> +/**
> >>>> + * struct dpu_hw_cdm_ops : Interface to the chroma down Hw driver functions
> >>>> + *                         Assumption is these functions will be called after
> >>>> + *                         clocks are enabled
> >>>> + *  @setup_csc:            Programs the csc matrix
> >>>> + *  @setup_cdwn:           Sets up the chroma down sub module
> >>>> + *  @enable:               Enables the output to interface and programs the
> >>>> + *                         output packer
> >>>> + *  @disable:              Puts the cdm in bypass mode
> >>>> + *  @bind_pingpong_blk:    enable/disable the connection with pingpong which
> >>>> + *                         will feed pixels to this cdm
> >>>> + */
> >>>> +struct dpu_hw_cdm_ops {
> >>>> +       /**
> >>>> +        * Programs the CSC matrix for conversion from RGB space to YUV space,
> >>>> +        * it is optional to call this function as this matrix is automatically
> >>>> +        * set during initialization, user should call this if it wants
> >>>> +        * to program a different matrix than default matrix.
> >>>> +        * @cdm:          Pointer to the chroma down context structure
> >>>> +        * @data          Pointer to CSC configuration data
> >>>> +        * return:        0 if success; error code otherwise
> >>>> +        */
> >>>> +       int (*setup_csc_data)(struct dpu_hw_cdm *cdm, struct dpu_csc_cfg *data);
> >>>> +
> >>>> +       /**
> >>>> +        * Programs the Chroma downsample part.
> >>>> +        * @cdm         Pointer to chroma down context
> >>>> +        * @cfg         Pointer to the cdm configuration data
> >>>> +        */
> >>>> +       int (*setup_cdwn)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
> >>>> +
> >>>> +       /**
> >>>> +        * Enable the CDM module
> >>>> +        * @cdm         Pointer to chroma down context
> >>>> +        */
> >>>> +       int (*enable)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
> >>>> +
> >>>> +       /**
> >>>> +        * Disable the CDM module
> >>>> +        * @cdm         Pointer to chroma down context
> >>>> +        */
> >>>> +       void (*disable)(struct dpu_hw_cdm *cdm);
> >>>> +
> >>>> +       /**
> >>>> +        * Enable/disable the connection with pingpong
> >>>> +        * @cdm         Pointer to chroma down context
> >>>> +        * @enable      Enable/disable control
> >>>> +        * @pp          pingpong block id.
> >>>> +        */
> >>>> +       void (*bind_pingpong_blk)(struct dpu_hw_cdm *cdm, bool enable,
> >>>> +                                 const enum dpu_pingpong pp);
> >>>> +};
> >>>> +
> >>>> +/**
> >>>> + * struct dpu_hw_cdm - cdm description
> >>>> + * @base: Hardware block base structure
> >>>> + * @hw: Block hardware details
> >>>> + * @idx: CDM index
> >>>> + * @caps: Pointer to cdm_cfg
> >>>> + * @ops: handle to operations possible for this CDM
> >>>> + */
> >>>> +struct dpu_hw_cdm {
> >>>> +       struct dpu_hw_blk base;
> >>>> +       struct dpu_hw_blk_reg_map hw;
> >>>> +
> >>>> +       /* chroma down */
> >>>> +       const struct dpu_cdm_cfg *caps;
> >>>> +       enum  dpu_cdm  idx;
> >>>> +
> >>>> +       /* ops */
> >>>> +       struct dpu_hw_cdm_ops ops;
> >>>> +};
> >>>> +
> >>>> +/**
> >>>> + * dpu_hw_cdm_init - initializes the cdm hw driver object.
> >>>> + * should be called once before accessing every cdm.
> >>>> + * @cdm: CDM catalog entry for which driver object is required
> >>>> + * @addr :   mapped register io address of MDSS
> >>>> + */
> >>>> +struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cdm, void __iomem *addr);
> >>>> +
> >>>> +/**
> >>>> + * dpu_hw_cdm_destroy - destroys cdm driver context
> >>>> + * @cdm:   Pointer to cdm driver context returned by dpu_hw_cdm_init
> >>>> + */
> >>>> +void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm);
> >>>> +
> >>>> +static inline struct dpu_hw_cdm *to_dpu_hw_cdm(struct dpu_hw_blk *hw)
> >>>> +{
> >>>> +       return container_of(hw, struct dpu_hw_cdm, base);
> >>>> +}
> >>>> +
> >>>> +#endif /*_DPU_HW_CDM_H */
> >>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >>>> index 4d6dba18caf0..34f943102499 100644
> >>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >>>> @@ -463,6 +463,7 @@ struct dpu_mdss_color {
> >>>>    #define DPU_DBG_MASK_ROT      (1 << 9)
> >>>>    #define DPU_DBG_MASK_DSPP     (1 << 10)
> >>>>    #define DPU_DBG_MASK_DSC      (1 << 11)
> >>>> +#define DPU_DBG_MASK_CDM      (1 << 12)
> >>>>
> >>>>    /**
> >>>>     * struct dpu_hw_tear_check - Struct contains parameters to configure
> >>>> --
> >>>> 2.40.1
> >>>>
> >>>
> >>>
> >>> --
> >>> With best wishes
> >>> Dmitry
> >
> >
> >



-- 
With best wishes
Dmitry

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

* Re: [PATCH 06/16] drm/msm/dpu: add dpu_hw_cdm abstraction for CDM block
@ 2023-12-01 21:10             ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-12-01 21:10 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Fri, 1 Dec 2023 at 20:19, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 11/30/2023 11:05 PM, Dmitry Baryshkov wrote:
> > On Fri, 1 Dec 2023 at 01:36, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >>
> >>
> >> On 8/30/2023 5:00 PM, Dmitry Baryshkov wrote:
> >>> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>>>
> >>>> CDM block comes with its own set of registers and operations
> >>>> which can be done. In-line with other hardware sub-blocks, this
> >>>> change adds the dpu_hw_cdm abstraction for the CDM block.
> >>>>
> >>>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> >>>> ---
> >>>>    drivers/gpu/drm/msm/Makefile                |   1 +
> >>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c  | 272 ++++++++++++++++++++
> >>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h  | 135 ++++++++++
> >>>>    drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h |   1 +
> >>>>    4 files changed, 409 insertions(+)
> >>>>    create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
> >>>>    create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
> >>>>
> >>>> diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
> >>>> index 8d02d8c33069..2010cb1ca995 100644
> >>>> --- a/drivers/gpu/drm/msm/Makefile
> >>>> +++ b/drivers/gpu/drm/msm/Makefile
> >>>> @@ -63,6 +63,7 @@ msm-$(CONFIG_DRM_MSM_DPU) += \
> >>>>           disp/dpu1/dpu_encoder_phys_wb.o \
> >>>>           disp/dpu1/dpu_formats.o \
> >>>>           disp/dpu1/dpu_hw_catalog.o \
> >>>> +       disp/dpu1/dpu_hw_cdm.o \
> >>>>           disp/dpu1/dpu_hw_ctl.o \
> >>>>           disp/dpu1/dpu_hw_dsc.o \
> >>>>           disp/dpu1/dpu_hw_dsc_1_2.o \
> >>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
> >>>> new file mode 100644
> >>>> index 000000000000..a2f7ee8f54e4
> >>>> --- /dev/null
> >>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
> >>>> @@ -0,0 +1,272 @@
> >>>> +// SPDX-License-Identifier: GPL-2.0-only
> >>>> +/*
> >>>> + * Copyright (c) 2023, The Linux Foundation. All rights reserved.
> >>>> + */
> >>>> +
> >>>> +#include <drm/drm_managed.h>
> >>>> +
> >>>> +#include "dpu_hw_mdss.h"
> >>>> +#include "dpu_hw_util.h"
> >>>> +#include "dpu_hw_catalog.h"
> >>>> +#include "dpu_hw_cdm.h"
> >>>> +#include "dpu_kms.h"
> >>>> +
> >>>> +#define CDM_CSC_10_OPMODE                  0x000
> >>>> +#define CDM_CSC_10_BASE                    0x004
> >>>> +
> >>>> +#define CDM_CDWN2_OP_MODE                  0x100
> >>>> +#define CDM_CDWN2_CLAMP_OUT                0x104
> >>>> +#define CDM_CDWN2_PARAMS_3D_0              0x108
> >>>> +#define CDM_CDWN2_PARAMS_3D_1              0x10C
> >>>> +#define CDM_CDWN2_COEFF_COSITE_H_0         0x110
> >>>> +#define CDM_CDWN2_COEFF_COSITE_H_1         0x114
> >>>> +#define CDM_CDWN2_COEFF_COSITE_H_2         0x118
> >>>> +#define CDM_CDWN2_COEFF_OFFSITE_H_0        0x11C
> >>>> +#define CDM_CDWN2_COEFF_OFFSITE_H_1        0x120
> >>>> +#define CDM_CDWN2_COEFF_OFFSITE_H_2        0x124
> >>>> +#define CDM_CDWN2_COEFF_COSITE_V           0x128
> >>>> +#define CDM_CDWN2_COEFF_OFFSITE_V          0x12C
> >>>> +#define CDM_CDWN2_OUT_SIZE                 0x130
> >>>> +
> >>>> +#define CDM_HDMI_PACK_OP_MODE              0x200
> >>>> +#define CDM_CSC_10_MATRIX_COEFF_0          0x004
> >>>> +
> >>>> +#define CDM_MUX                            0x224
> >>>> +
> >>>> +/**
> >>>> + * Horizontal coefficients for cosite chroma downscale
> >>>> + * s13 representation of coefficients
> >>>> + */
> >>>> +static u32 cosite_h_coeff[] = {0x00000016, 0x000001cc, 0x0100009e};
> >>>> +
> >>>> +/**
> >>>> + * Horizontal coefficients for offsite chroma downscale
> >>>> + */
> >>>> +static u32 offsite_h_coeff[] = {0x000b0005, 0x01db01eb, 0x00e40046};
> >>>> +
> >>>> +/**
> >>>> + * Vertical coefficients for cosite chroma downscale
> >>>> + */
> >>>> +static u32 cosite_v_coeff[] = {0x00080004};
> >>>> +/**
> >>>> + * Vertical coefficients for offsite chroma downscale
> >>>> + */
> >>>> +static u32 offsite_v_coeff[] = {0x00060002};
> >>>> +
> >>>> +static int dpu_hw_cdm_setup_csc_10bit(struct dpu_hw_cdm *ctx, struct dpu_csc_cfg *data)
> >>>> +{
> >>>> +       dpu_hw_csc_setup(&ctx->hw, CDM_CSC_10_MATRIX_COEFF_0, data, true);
> >>>
> >>> Where was this defined?
> >>>
> >>
> >> Its in this file itself
> >>
> >> +#define CDM_CSC_10_MATRIX_COEFF_0          0x004
> >>
> >>>> +
> >>>> +       return 0;
> >>>> +}
> >>>> +
> >>>> +static int dpu_hw_cdm_setup_cdwn(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cfg)
> >>>> +{
> >>>> +       struct dpu_hw_blk_reg_map *c = &ctx->hw;
> >>>> +       u32 opmode = 0;
> >>>> +       u32 out_size = 0;
> >>>> +
> >>>> +       if (cfg->output_bit_depth == CDM_CDWN_OUTPUT_10BIT)
> >>>> +               opmode &= ~BIT(7);
> >>>> +       else
> >>>> +               opmode |= BIT(7);
> >>>> +
> >>>> +       /* ENABLE DWNS_H bit */
> >>>> +       opmode |= BIT(1);
> >>>> +
> >>>> +       switch (cfg->h_cdwn_type) {
> >>>> +       case CDM_CDWN_DISABLE:
> >>>> +               /* CLEAR METHOD_H field */
> >>>> +               opmode &= ~(0x18);
> >>>> +               /* CLEAR DWNS_H bit */
> >>>> +               opmode &= ~BIT(1);
> >>>> +               break;
> >>>> +       case CDM_CDWN_PIXEL_DROP:
> >>>> +               /* Clear METHOD_H field (pixel drop is 0) */
> >>>> +               opmode &= ~(0x18);
> >>>> +               break;
> >>>> +       case CDM_CDWN_AVG:
> >>>> +               /* Clear METHOD_H field (Average is 0x1) */
> >>>> +               opmode &= ~(0x18);
> >>>> +               opmode |= (0x1 << 0x3);
> >>>> +               break;
> >>>> +       case CDM_CDWN_COSITE:
> >>>> +               /* Clear METHOD_H field (Average is 0x2) */
> >>>> +               opmode &= ~(0x18);
> >>>> +               opmode |= (0x2 << 0x3);
> >>>> +               /* Co-site horizontal coefficients */
> >>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_0,
> >>>> +                               cosite_h_coeff[0]);
> >>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_1,
> >>>> +                               cosite_h_coeff[1]);
> >>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_2,
> >>>> +                               cosite_h_coeff[2]);
> >>>> +               break;
> >>>> +       case CDM_CDWN_OFFSITE:
> >>>> +               /* Clear METHOD_H field (Average is 0x3) */
> >>>> +               opmode &= ~(0x18);
> >>>> +               opmode |= (0x3 << 0x3);
> >>>> +
> >>>> +               /* Off-site horizontal coefficients */
> >>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_0,
> >>>> +                               offsite_h_coeff[0]);
> >>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_1,
> >>>> +                               offsite_h_coeff[1]);
> >>>> +               DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_2,
> >>>> +                               offsite_h_coeff[2]);
> >>>> +               break;
> >>>> +       default:
> >>>> +               pr_err("%s invalid horz down sampling type\n", __func__);
> >>>> +               return -EINVAL;
> >>>> +       }
> >>>> +
> >>>> +       /* ENABLE DWNS_V bit */
> >>>> +       opmode |= BIT(2);
> >>>> +
> >>>> +       switch (cfg->v_cdwn_type) {
> >>>> +       case CDM_CDWN_DISABLE:
> >>>> +               /* CLEAR METHOD_V field */
> >>>> +               opmode &= ~(0x60);
> >>>
> >>> #define, GENMASK
> >>>
> >>>> +               /* CLEAR DWNS_V bit */
> >>>> +               opmode &= ~BIT(2);
> >>>> +               break;
> >>>> +       case CDM_CDWN_PIXEL_DROP:
> >>>> +               /* Clear METHOD_V field (pixel drop is 0) */
> >>>> +               opmode &= ~(0x60);
> >>>> +               break;
> >>>> +       case CDM_CDWN_AVG:
> >>>> +               /* Clear METHOD_V field (Average is 0x1) */
> >>>> +               opmode &= ~(0x60);
> >>>> +               opmode |= (0x1 << 0x5);
> >>>
> >>> #define
> >>>
> >>>> +               break;
> >>>> +       case CDM_CDWN_COSITE:
> >>>> +               /* Clear METHOD_V field (Average is 0x2) */
> >>>> +               opmode &= ~(0x60);
> >>>> +               opmode |= (0x2 << 0x5);
> >>>> +               /* Co-site vertical coefficients */
> >>>> +               DPU_REG_WRITE(c,
> >>>> +                               CDM_CDWN2_COEFF_COSITE_V,
> >>>> +                               cosite_v_coeff[0]);
> >>>
> >>> align to opening bracket
> >>>
> >>>> +               break;
> >>>> +       case CDM_CDWN_OFFSITE:
> >>>> +               /* Clear METHOD_V field (Average is 0x3) */
> >>>> +               opmode &= ~(0x60);
> >>>> +               opmode |= (0x3 << 0x5);
> >>>> +
> >>>> +               /* Off-site vertical coefficients */
> >>>> +               DPU_REG_WRITE(c,
> >>>> +                               CDM_CDWN2_COEFF_OFFSITE_V,
> >>>> +                               offsite_v_coeff[0]);
> >>>
> >>> align to opening bracket
> >>>
> >>>> +               break;
> >>>> +       default:
> >>>> +               return -EINVAL;
> >>>> +       }
> >>>> +
> >>>> +       if (cfg->v_cdwn_type || cfg->h_cdwn_type)
> >>>> +               opmode |= BIT(0); /* EN CDWN module */
> >>>
> >>> #define
> >>>
> >>
> >> Ack to all comments about GENMASK and #define
> >>
> >>>> +       else
> >>>> +               opmode &= ~BIT(0);
> >>>> +
> >>>> +       out_size = (cfg->output_width & 0xFFFF) |
> >>>> +               ((cfg->output_height & 0xFFFF) << 16);
> >>>> +       DPU_REG_WRITE(c, CDM_CDWN2_OUT_SIZE, out_size);
> >>>> +       DPU_REG_WRITE(c, CDM_CDWN2_OP_MODE, opmode);
> >>>> +       DPU_REG_WRITE(c, CDM_CDWN2_CLAMP_OUT,
> >>>> +                       ((0x3FF << 16) | 0x0));
> >>>> +
> >>>> +       return 0;
> >>>> +}
> >>>> +
> >>>> +int dpu_hw_cdm_enable(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cdm)
> >>>> +{
> >>>> +       struct dpu_hw_blk_reg_map *c = &ctx->hw;
> >>>> +       const struct dpu_format *fmt;
> >>>> +       u32 opmode = 0;
> >>>> +       u32 csc = 0;
> >>>> +
> >>>> +       if (!ctx || !cdm)
> >>>> +               return -EINVAL;
> >>>> +
> >>>> +       fmt = cdm->output_fmt;
> >>>> +
> >>>> +       if (!DPU_FORMAT_IS_YUV(fmt))
> >>>> +               return -EINVAL;
> >>>> +
> >>>> +       if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
> >>>> +               if (fmt->chroma_sample != DPU_CHROMA_H1V2)
> >>>> +                       return -EINVAL; /*unsupported format */
> >>>> +               opmode = BIT(0);
> >>>> +               opmode |= (fmt->chroma_sample << 1);
> >>>> +       }
> >>>> +
> >>>> +       csc |= BIT(2);
> >>>> +       csc &= ~BIT(1);
> >>>> +       csc |= BIT(0);
> >>>
> >>> Can we get some sensible #defines for all this magic, please?
> >>>
> >>
> >> Ack, will do.
> >>
> >>>> +
> >>>> +       if (ctx && ctx->ops.bind_pingpong_blk)
> >>>> +               ctx->ops.bind_pingpong_blk(ctx, true,
> >>>> +                               cdm->pp_id);
> >>>> +
> >>>> +       DPU_REG_WRITE(c, CDM_CSC_10_OPMODE, csc);
> >>>> +       DPU_REG_WRITE(c, CDM_HDMI_PACK_OP_MODE, opmode);
> >>>> +       return 0;
> >>>> +}
> >>>> +
> >>>> +void dpu_hw_cdm_disable(struct dpu_hw_cdm *ctx)
> >>>> +{
> >>>> +       if (!ctx)
> >>>> +               return;
> >>>> +
> >>>> +       if (ctx && ctx->ops.bind_pingpong_blk)
> >>>> +               ctx->ops.bind_pingpong_blk(ctx, false, 0);
> >>>
> >>> PINGPONG_NONE.
> >>>
> >>>> +}
> >>>> +
> >>>> +static void dpu_hw_cdm_bind_pingpong_blk(struct dpu_hw_cdm *ctx, bool enable,
> >>>> +                                        const enum dpu_pingpong pp)
> >>>> +{
> >>>> +       struct dpu_hw_blk_reg_map *c;
> >>>> +       int mux_cfg = 0xF;
> >>>> +
> >>>> +       if (!ctx || (enable && (pp < PINGPONG_0 || pp >= PINGPONG_MAX)))
> >>>> +               return;
> >>>
> >>> I'd say, this is useless. We don't have such checks in other
> >>> bind_pingpong_blk() callbacks.
> >>>
> >>> Also there should be a guarding check for DPU >= 5.0 either here or at
> >>> the ops init.
> >>>
> >>
> >> Will add it at ops init
> >>
> >>>> +
> >>>> +       c = &ctx->hw;
> >>>> +
> >>>> +       if (enable)
> >>>> +               mux_cfg = (pp - PINGPONG_0) & 0x7;
> >>>> +
> >>>> +       DPU_REG_WRITE(c, CDM_MUX, mux_cfg);
> >>>> +}
> >>>> +
> >>>> +static void _setup_cdm_ops(struct dpu_hw_cdm_ops *ops, unsigned long features)
> >>>
> >>> Please inline
> >>>
> >>
> >> OK
> >>
> >>>> +{
> >>>> +       ops->setup_csc_data = dpu_hw_cdm_setup_csc_10bit;
> >>>> +       ops->setup_cdwn = dpu_hw_cdm_setup_cdwn;
> >>>> +       ops->enable = dpu_hw_cdm_enable;
> >>>> +       ops->disable = dpu_hw_cdm_disable;
> >>>> +       ops->bind_pingpong_blk = dpu_hw_cdm_bind_pingpong_blk;
> >>>
> >>> As you seem to call this function directly, we might as well drop the
> >>> callback from the ops.
> >>>
> >>
> >> There are two paths for the bind_pingpong_blk(). One is absorbed within
> >> cdm_enable and cdm_disable calls to bind and unbind the pingpong resp.
> >> And yes, for that we dont need a separate ops as its within the same file.
> >>
> >> This will handle cases where we transition from YUV to non-YUV cases and
> >> vice-versa without an encoder disable in between which I believe happens
> >> in the IGT cases.
> >>
> >> But the dpu_encoder_helper_phys_cleanup() path is only in the encoder
> >> disable() path without a non-YUV frame in the middle so lets say we were
> >> in YUV mode but then just disabled the encoder we do need the cleanup
> >> there and since thats outside of the dpu_hw_cdm, we do need this op.
> >>
> >> I agree we need to protect this with the DPU revision check.
> >>
> >>>> +}
> >>>> +
> >>>> +struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cfg, void __iomem *addr)
> >>>> +{
> >>>> +       struct dpu_hw_cdm *c;
> >>>> +
> >>>> +       c = kzalloc(sizeof(*c), GFP_KERNEL);
> >>>> +       if (!c)
> >>>> +               return ERR_PTR(-ENOMEM);
> >>>> +
> >>>> +       c->hw.blk_addr = addr + cfg->base;
> >>>> +       c->hw.log_mask = DPU_DBG_MASK_CDM;
> >>>> +
> >>>> +       /* Assign ops */
> >>>> +       c->idx = cfg->id;
> >>>> +       c->caps = cfg;
> >>>> +       _setup_cdm_ops(&c->ops, c->caps->features);
> >>>> +
> >>>> +       return c;
> >>>> +}
> >>>> +
> >>>> +void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm)
> >>>> +{
> >>>> +       kfree(cdm);
> >>>
> >>> I'd prefer not to introduce another manual kzalloc/kfree pair, see
> >>> https://patchwork.freedesktop.org/series/120366/
> >>>
> >>
> >> I recall I did not want to have a manual kzalloc/kfree pair. But the
> >> issue was I think this series was not merged that time (and is isnt
> >> merged now either)
> >
> > No response, no reviews since 15th August. Today is the 1st of December.
> >
> > I'm close to deciding that unreviewed series have no issues and start
> > showing them to -next after a grace period of 1 month.
> >
> >> and this is the one which passes drm_dev to
> >> dpu_rm_init. I thought maybe it was easier for you to absorb this change
> >> into that series instead of me pulling that whole series to make this
> >> one compile as we will not be adding new HW blocks after this for the
> >> next 2 cycles. It will only be using existing ones.
> >>
> >> If its too much trouble for you, I will rebase on top of that series but
> >> I am pretty sure you will have to rebase and post that again anyway on
> >> top of the current msm-next.
> >>
> >> I am also going to do the same thing now with this series.
> >>
>
> There were 4 patches in that series which didnt get a R-b. Perhaps
> jessica can finish the reviews which she started on that one.
>
> Leaving her a note on IRC would not have hurt like its a common practice
> sometimes with other reviewers.
>
> Now, do you want to rebase this on msm-next and re-send so that I can
> rebase on top of yours?

Sure, I'll do it now.

>
> >> So we can just decide that in whose rebase we will handle it.
> >>
> >>>> +}
> >>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
> >>>> new file mode 100644
> >>>> index 000000000000..da60893a5c02
> >>>> --- /dev/null
> >>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
> >>>> @@ -0,0 +1,135 @@
> >>>> +/* SPDX-License-Identifier: GPL-2.0-only */
> >>>> +/*
> >>>> + * Copyright (c) 2023, The Linux Foundation. All rights reserved.
> >>>> + */
> >>>> +
> >>>> +#ifndef _DPU_HW_CDM_H
> >>>> +#define _DPU_HW_CDM_H
> >>>> +
> >>>> +#include "dpu_hw_mdss.h"
> >>>> +#include "dpu_hw_top.h"
> >>>> +
> >>>> +struct dpu_hw_cdm;
> >>>> +
> >>>> +struct dpu_hw_cdm_cfg {
> >>>> +       u32 output_width;
> >>>> +       u32 output_height;
> >>>> +       u32 output_bit_depth;
> >>>> +       u32 h_cdwn_type;
> >>>> +       u32 v_cdwn_type;
> >>>> +       const struct dpu_format *output_fmt;
> >>>> +       u32 output_type;
> >>>> +       int pp_id;
> >>>> +};
> >>>> +
> >>>> +enum dpu_hw_cdwn_type {
> >>>> +       CDM_CDWN_DISABLE,
> >>>> +       CDM_CDWN_PIXEL_DROP,
> >>>> +       CDM_CDWN_AVG,
> >>>> +       CDM_CDWN_COSITE,
> >>>> +       CDM_CDWN_OFFSITE,
> >>>> +};
> >>>> +
> >>>> +enum dpu_hw_cdwn_output_type {
> >>>> +       CDM_CDWN_OUTPUT_HDMI,
> >>>> +       CDM_CDWN_OUTPUT_WB,
> >>>> +};
> >>>> +
> >>>> +enum dpu_hw_cdwn_output_bit_depth {
> >>>> +       CDM_CDWN_OUTPUT_8BIT,
> >>>> +       CDM_CDWN_OUTPUT_10BIT,
> >>>> +};
> >>>> +
> >>>> +/**
> >>>> + * struct dpu_hw_cdm_ops : Interface to the chroma down Hw driver functions
> >>>> + *                         Assumption is these functions will be called after
> >>>> + *                         clocks are enabled
> >>>> + *  @setup_csc:            Programs the csc matrix
> >>>> + *  @setup_cdwn:           Sets up the chroma down sub module
> >>>> + *  @enable:               Enables the output to interface and programs the
> >>>> + *                         output packer
> >>>> + *  @disable:              Puts the cdm in bypass mode
> >>>> + *  @bind_pingpong_blk:    enable/disable the connection with pingpong which
> >>>> + *                         will feed pixels to this cdm
> >>>> + */
> >>>> +struct dpu_hw_cdm_ops {
> >>>> +       /**
> >>>> +        * Programs the CSC matrix for conversion from RGB space to YUV space,
> >>>> +        * it is optional to call this function as this matrix is automatically
> >>>> +        * set during initialization, user should call this if it wants
> >>>> +        * to program a different matrix than default matrix.
> >>>> +        * @cdm:          Pointer to the chroma down context structure
> >>>> +        * @data          Pointer to CSC configuration data
> >>>> +        * return:        0 if success; error code otherwise
> >>>> +        */
> >>>> +       int (*setup_csc_data)(struct dpu_hw_cdm *cdm, struct dpu_csc_cfg *data);
> >>>> +
> >>>> +       /**
> >>>> +        * Programs the Chroma downsample part.
> >>>> +        * @cdm         Pointer to chroma down context
> >>>> +        * @cfg         Pointer to the cdm configuration data
> >>>> +        */
> >>>> +       int (*setup_cdwn)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
> >>>> +
> >>>> +       /**
> >>>> +        * Enable the CDM module
> >>>> +        * @cdm         Pointer to chroma down context
> >>>> +        */
> >>>> +       int (*enable)(struct dpu_hw_cdm *cdm, struct dpu_hw_cdm_cfg *cfg);
> >>>> +
> >>>> +       /**
> >>>> +        * Disable the CDM module
> >>>> +        * @cdm         Pointer to chroma down context
> >>>> +        */
> >>>> +       void (*disable)(struct dpu_hw_cdm *cdm);
> >>>> +
> >>>> +       /**
> >>>> +        * Enable/disable the connection with pingpong
> >>>> +        * @cdm         Pointer to chroma down context
> >>>> +        * @enable      Enable/disable control
> >>>> +        * @pp          pingpong block id.
> >>>> +        */
> >>>> +       void (*bind_pingpong_blk)(struct dpu_hw_cdm *cdm, bool enable,
> >>>> +                                 const enum dpu_pingpong pp);
> >>>> +};
> >>>> +
> >>>> +/**
> >>>> + * struct dpu_hw_cdm - cdm description
> >>>> + * @base: Hardware block base structure
> >>>> + * @hw: Block hardware details
> >>>> + * @idx: CDM index
> >>>> + * @caps: Pointer to cdm_cfg
> >>>> + * @ops: handle to operations possible for this CDM
> >>>> + */
> >>>> +struct dpu_hw_cdm {
> >>>> +       struct dpu_hw_blk base;
> >>>> +       struct dpu_hw_blk_reg_map hw;
> >>>> +
> >>>> +       /* chroma down */
> >>>> +       const struct dpu_cdm_cfg *caps;
> >>>> +       enum  dpu_cdm  idx;
> >>>> +
> >>>> +       /* ops */
> >>>> +       struct dpu_hw_cdm_ops ops;
> >>>> +};
> >>>> +
> >>>> +/**
> >>>> + * dpu_hw_cdm_init - initializes the cdm hw driver object.
> >>>> + * should be called once before accessing every cdm.
> >>>> + * @cdm: CDM catalog entry for which driver object is required
> >>>> + * @addr :   mapped register io address of MDSS
> >>>> + */
> >>>> +struct dpu_hw_cdm *dpu_hw_cdm_init(const struct dpu_cdm_cfg *cdm, void __iomem *addr);
> >>>> +
> >>>> +/**
> >>>> + * dpu_hw_cdm_destroy - destroys cdm driver context
> >>>> + * @cdm:   Pointer to cdm driver context returned by dpu_hw_cdm_init
> >>>> + */
> >>>> +void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm);
> >>>> +
> >>>> +static inline struct dpu_hw_cdm *to_dpu_hw_cdm(struct dpu_hw_blk *hw)
> >>>> +{
> >>>> +       return container_of(hw, struct dpu_hw_cdm, base);
> >>>> +}
> >>>> +
> >>>> +#endif /*_DPU_HW_CDM_H */
> >>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >>>> index 4d6dba18caf0..34f943102499 100644
> >>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >>>> @@ -463,6 +463,7 @@ struct dpu_mdss_color {
> >>>>    #define DPU_DBG_MASK_ROT      (1 << 9)
> >>>>    #define DPU_DBG_MASK_DSPP     (1 << 10)
> >>>>    #define DPU_DBG_MASK_DSC      (1 << 11)
> >>>> +#define DPU_DBG_MASK_CDM      (1 << 12)
> >>>>
> >>>>    /**
> >>>>     * struct dpu_hw_tear_check - Struct contains parameters to configure
> >>>> --
> >>>> 2.40.1
> >>>>
> >>>
> >>>
> >>> --
> >>> With best wishes
> >>> Dmitry
> >
> >
> >



-- 
With best wishes
Dmitry

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

* Re: [Freedreno] [PATCH 11/16] drm/msm/dpu: add an API to setup the CDM block for writeback
  2023-12-01 19:04           ` Abhinav Kumar
@ 2023-12-01 21:15             ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-12-01 21:15 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	Rob Clark, quic_parellan, Daniel Vetter, quic_jesszhan,
	Marijn Suijten, David Airlie, Sean Paul

On Fri, 1 Dec 2023 at 21:04, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 11/30/2023 11:20 PM, Dmitry Baryshkov wrote:
> > On Fri, 1 Dec 2023 at 02:41, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >>
> >>
> >> On 8/30/2023 5:11 PM, Dmitry Baryshkov wrote:
> >>> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>>>
> >>>> Add an API dpu_encoder_helper_phys_setup_cdm() which can be used by
> >>>> the writeback encoder to setup the CDM block.
> >>>>
> >>>> Currently, this is defined and used within the writeback's physical
> >>>> encoder layer however, the function can be modified to be used to setup
> >>>> the CDM block even for non-writeback interfaces.
> >>>>
> >>>> Until those modifications are planned and made, keep it local to
> >>>> writeback.
> >>>>
> >>>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> >>>> ---
> >>>>    .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   3 +
> >>>>    .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 123 +++++++++++++++++-
> >>>>    2 files changed, 125 insertions(+), 1 deletion(-)
> >>>>
> >>>> 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 510c1c41ddbc..93a8ae67beff 100644
> >>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >>>> @@ -16,6 +16,7 @@
> >>>>    #include "dpu_hw_pingpong.h"
> >>>>    #include "dpu_hw_ctl.h"
> >>>>    #include "dpu_hw_top.h"
> >>>> +#include "dpu_hw_cdm.h"
> >>>>    #include "dpu_encoder.h"
> >>>>    #include "dpu_crtc.h"
> >>>>
> >>>> @@ -209,6 +210,7 @@ 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
> >>>> @@ -218,6 +220,7 @@ 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 4c2736c3ee6d..11935aac9fd5 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
> >>>> @@ -24,6 +24,20 @@
> >>>>    #define to_dpu_encoder_phys_wb(x) \
> >>>>           container_of(x, struct dpu_encoder_phys_wb, base)
> >>>>
> >>>> +#define TO_S15D16(_x_)((_x_) << 7)
> >>>> +
> >>>> +static struct dpu_csc_cfg dpu_encoder_phys_wb_rgb2yuv_601l = {
> >>>> +       {
> >>>> +               TO_S15D16(0x0083), TO_S15D16(0x0102), TO_S15D16(0x0032),
> >>>> +               TO_S15D16(0x1fb5), TO_S15D16(0x1f6c), TO_S15D16(0x00e1),
> >>>> +               TO_S15D16(0x00e1), TO_S15D16(0x1f45), TO_S15D16(0x1fdc)
> >>>> +       },
> >>>> +       { 0x00, 0x00, 0x00 },
> >>>> +       { 0x0040, 0x0200, 0x0200 },
> >>>> +       { 0x000, 0x3ff, 0x000, 0x3ff, 0x000, 0x3ff },
> >>>> +       { 0x040, 0x3ac, 0x040, 0x3c0, 0x040, 0x3c0 },
> >>>> +};
> >>>
> >>> Nit: we probably need to have a single place with all dpu_csc_cfg entries.
> >>>
> >>
> >> hmmm ... so we have YUV2RGB matrices for dpu plane and RGB2YUV matrices
> >> for WB and DP.
> >>
> >> We can move all this to dpu_hw_util.c but lets do that in the DP series
> >> as that completes the consumer list of these matrices.
> >
> > Doing it earlier is usually better. Can we please do it as a part of
> > this series?
> >
>
> Would be strange as RGB2YUV matrix is not used by anyone other than WB
> till DP lands.
>
> If you are fine with that anomaly, no concerns.

Yes. Because it keeps all instances in a single place.

>
> >>
> >>>> +
> >>>>    /**
> >>>>     * dpu_encoder_phys_wb_is_master - report wb always as master encoder
> >>>>     * @phys_enc:  Pointer to physical encoder
> >>>> @@ -225,6 +239,112 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
> >>>>           }
> >>>>    }
> >>>>
> >>>> +/**
> >>>> + * dpu_encoder_phys_wb_setup_cdp - setup chroma down sampling block
> >>>> + * @phys_enc:Pointer to physical encoder
> >>>> + */
> >>>> +static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
> >>>> +{
> >>>> +       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;
> >>>> +       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;
> >>>> +
> >>>> +       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.disable)
> >>>> +                       hw_cdm->ops.disable(hw_cdm);
> >>>> +
> >>>> +               return;
> >>>> +       }
> >>>> +
> >>>> +       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_fmt = dpu_fmt;
> >>>> +       cdm_cfg->output_type = CDM_CDWN_OUTPUT_WB;
> >>>> +       cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
> >>>> +                       CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
> >>>> +
> >>>> +       /* 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 && hw_cdm->ops.setup_csc_data) {
> >>>> +               ret = hw_cdm->ops.setup_csc_data(hw_cdm, &dpu_encoder_phys_wb_rgb2yuv_601l);
> >>>> +               if (ret < 0) {
> >>>> +                       DPU_ERROR("[enc:%d] failed to setup CSC; ret:%d\n",
> >>>> +                                 DRMID(phys_enc->parent), ret);
> >>>> +                       return;
> >>>> +               }
> >>>> +       }
> >>>> +
> >>>> +       if (hw_cdm && hw_cdm->ops.setup_cdwn) {
> >>>
> >>> You have checked for (!hw_cdm) several lines above. We can drop this
> >>> condition here.
> >>>
> >>
> >> Ack.
> >>
> >>>> +               ret = hw_cdm->ops.setup_cdwn(hw_cdm, cdm_cfg);
> >>>> +               if (ret < 0) {
> >>>> +                       DPU_ERROR("[enc:%d] failed to setup CDWN; ret:%d\n",
> >>>> +                                 DRMID(phys_enc->parent), ret);
> >>>> +                       return;
> >>>> +               }
> >>>> +       }
> >>>> +
> >>>> +       if (hw_cdm && hw_pp && hw_cdm->ops.enable) {
> >>>
> >>> And what if !hw_pp ? Can it happen here? No, if I understand correctly.
> >>>
> >>
> >> I dont see any other protection for !hw_pp in this flow so would prefer
> >> to keep it.
> >
> > But can we end up in this function if we have no hw_pp at all?
> >
>
> Just from code flow yes,
>
> dpu_encoder_prepare_for_kickoff ---> phys->ops.prepare_for_kickoff --->
> this function
>
> None of them have !hw_pp.
>
> But, if hw_pp failed allocation, then atomic_check will fail so the
> commit will not happen.
>
> I was thinking of the former, if we are fine with the latter we can drop.

Yes, I'm fine with that, unless there is any special mode (like
ppsplit, cwb, etc.) where we can end up with no PP assigned on
purpose.

>
> >>
> >>>> +               cdm_cfg->pp_id = hw_pp->idx;
> >>>> +               ret = hw_cdm->ops.enable(hw_cdm, cdm_cfg);
> >>>
> >>> As we are calling these three ops in a row, can we merge them together
> >>> into a single callback to be called from dpu_encoder.c?
> >>>
> >>
> >> Good idea. I can add a csc_cfg entry to cdm_cfg and merge all three into
> >> the enable() op itself and drop the other two.
> >>
> >>>> +               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
> >>>> @@ -348,8 +468,9 @@ static void dpu_encoder_phys_wb_setup(
> >>>>
> >>>>           dpu_encoder_phys_wb_setup_fb(phys_enc, fb);
> >>>>
> >>>> -       dpu_encoder_phys_wb_setup_ctl(phys_enc);
> >>>> +       dpu_encoder_helper_phys_setup_cdm(phys_enc);
> >>>>
> >>>> +       dpu_encoder_phys_wb_setup_ctl(phys_enc);
> >>>>    }
> >>>>
> >>>>    static void _dpu_encoder_phys_wb_frame_done_helper(void *arg)
> >>>> --
> >>>> 2.40.1
> >>>>
> >>>
> >>>
> >
> >
> >



-- 
With best wishes
Dmitry

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

* Re: [Freedreno] [PATCH 11/16] drm/msm/dpu: add an API to setup the CDM block for writeback
@ 2023-12-01 21:15             ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-12-01 21:15 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: Sean Paul, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, Marijn Suijten, quic_jesszhan, freedreno

On Fri, 1 Dec 2023 at 21:04, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 11/30/2023 11:20 PM, Dmitry Baryshkov wrote:
> > On Fri, 1 Dec 2023 at 02:41, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >>
> >>
> >> On 8/30/2023 5:11 PM, Dmitry Baryshkov wrote:
> >>> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>>>
> >>>> Add an API dpu_encoder_helper_phys_setup_cdm() which can be used by
> >>>> the writeback encoder to setup the CDM block.
> >>>>
> >>>> Currently, this is defined and used within the writeback's physical
> >>>> encoder layer however, the function can be modified to be used to setup
> >>>> the CDM block even for non-writeback interfaces.
> >>>>
> >>>> Until those modifications are planned and made, keep it local to
> >>>> writeback.
> >>>>
> >>>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> >>>> ---
> >>>>    .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |   3 +
> >>>>    .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 123 +++++++++++++++++-
> >>>>    2 files changed, 125 insertions(+), 1 deletion(-)
> >>>>
> >>>> 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 510c1c41ddbc..93a8ae67beff 100644
> >>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> >>>> @@ -16,6 +16,7 @@
> >>>>    #include "dpu_hw_pingpong.h"
> >>>>    #include "dpu_hw_ctl.h"
> >>>>    #include "dpu_hw_top.h"
> >>>> +#include "dpu_hw_cdm.h"
> >>>>    #include "dpu_encoder.h"
> >>>>    #include "dpu_crtc.h"
> >>>>
> >>>> @@ -209,6 +210,7 @@ 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
> >>>> @@ -218,6 +220,7 @@ 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 4c2736c3ee6d..11935aac9fd5 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
> >>>> @@ -24,6 +24,20 @@
> >>>>    #define to_dpu_encoder_phys_wb(x) \
> >>>>           container_of(x, struct dpu_encoder_phys_wb, base)
> >>>>
> >>>> +#define TO_S15D16(_x_)((_x_) << 7)
> >>>> +
> >>>> +static struct dpu_csc_cfg dpu_encoder_phys_wb_rgb2yuv_601l = {
> >>>> +       {
> >>>> +               TO_S15D16(0x0083), TO_S15D16(0x0102), TO_S15D16(0x0032),
> >>>> +               TO_S15D16(0x1fb5), TO_S15D16(0x1f6c), TO_S15D16(0x00e1),
> >>>> +               TO_S15D16(0x00e1), TO_S15D16(0x1f45), TO_S15D16(0x1fdc)
> >>>> +       },
> >>>> +       { 0x00, 0x00, 0x00 },
> >>>> +       { 0x0040, 0x0200, 0x0200 },
> >>>> +       { 0x000, 0x3ff, 0x000, 0x3ff, 0x000, 0x3ff },
> >>>> +       { 0x040, 0x3ac, 0x040, 0x3c0, 0x040, 0x3c0 },
> >>>> +};
> >>>
> >>> Nit: we probably need to have a single place with all dpu_csc_cfg entries.
> >>>
> >>
> >> hmmm ... so we have YUV2RGB matrices for dpu plane and RGB2YUV matrices
> >> for WB and DP.
> >>
> >> We can move all this to dpu_hw_util.c but lets do that in the DP series
> >> as that completes the consumer list of these matrices.
> >
> > Doing it earlier is usually better. Can we please do it as a part of
> > this series?
> >
>
> Would be strange as RGB2YUV matrix is not used by anyone other than WB
> till DP lands.
>
> If you are fine with that anomaly, no concerns.

Yes. Because it keeps all instances in a single place.

>
> >>
> >>>> +
> >>>>    /**
> >>>>     * dpu_encoder_phys_wb_is_master - report wb always as master encoder
> >>>>     * @phys_enc:  Pointer to physical encoder
> >>>> @@ -225,6 +239,112 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
> >>>>           }
> >>>>    }
> >>>>
> >>>> +/**
> >>>> + * dpu_encoder_phys_wb_setup_cdp - setup chroma down sampling block
> >>>> + * @phys_enc:Pointer to physical encoder
> >>>> + */
> >>>> +static void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc)
> >>>> +{
> >>>> +       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;
> >>>> +       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;
> >>>> +
> >>>> +       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.disable)
> >>>> +                       hw_cdm->ops.disable(hw_cdm);
> >>>> +
> >>>> +               return;
> >>>> +       }
> >>>> +
> >>>> +       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_fmt = dpu_fmt;
> >>>> +       cdm_cfg->output_type = CDM_CDWN_OUTPUT_WB;
> >>>> +       cdm_cfg->output_bit_depth = DPU_FORMAT_IS_DX(dpu_fmt) ?
> >>>> +                       CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT;
> >>>> +
> >>>> +       /* 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 && hw_cdm->ops.setup_csc_data) {
> >>>> +               ret = hw_cdm->ops.setup_csc_data(hw_cdm, &dpu_encoder_phys_wb_rgb2yuv_601l);
> >>>> +               if (ret < 0) {
> >>>> +                       DPU_ERROR("[enc:%d] failed to setup CSC; ret:%d\n",
> >>>> +                                 DRMID(phys_enc->parent), ret);
> >>>> +                       return;
> >>>> +               }
> >>>> +       }
> >>>> +
> >>>> +       if (hw_cdm && hw_cdm->ops.setup_cdwn) {
> >>>
> >>> You have checked for (!hw_cdm) several lines above. We can drop this
> >>> condition here.
> >>>
> >>
> >> Ack.
> >>
> >>>> +               ret = hw_cdm->ops.setup_cdwn(hw_cdm, cdm_cfg);
> >>>> +               if (ret < 0) {
> >>>> +                       DPU_ERROR("[enc:%d] failed to setup CDWN; ret:%d\n",
> >>>> +                                 DRMID(phys_enc->parent), ret);
> >>>> +                       return;
> >>>> +               }
> >>>> +       }
> >>>> +
> >>>> +       if (hw_cdm && hw_pp && hw_cdm->ops.enable) {
> >>>
> >>> And what if !hw_pp ? Can it happen here? No, if I understand correctly.
> >>>
> >>
> >> I dont see any other protection for !hw_pp in this flow so would prefer
> >> to keep it.
> >
> > But can we end up in this function if we have no hw_pp at all?
> >
>
> Just from code flow yes,
>
> dpu_encoder_prepare_for_kickoff ---> phys->ops.prepare_for_kickoff --->
> this function
>
> None of them have !hw_pp.
>
> But, if hw_pp failed allocation, then atomic_check will fail so the
> commit will not happen.
>
> I was thinking of the former, if we are fine with the latter we can drop.

Yes, I'm fine with that, unless there is any special mode (like
ppsplit, cwb, etc.) where we can end up with no PP assigned on
purpose.

>
> >>
> >>>> +               cdm_cfg->pp_id = hw_pp->idx;
> >>>> +               ret = hw_cdm->ops.enable(hw_cdm, cdm_cfg);
> >>>
> >>> As we are calling these three ops in a row, can we merge them together
> >>> into a single callback to be called from dpu_encoder.c?
> >>>
> >>
> >> Good idea. I can add a csc_cfg entry to cdm_cfg and merge all three into
> >> the enable() op itself and drop the other two.
> >>
> >>>> +               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
> >>>> @@ -348,8 +468,9 @@ static void dpu_encoder_phys_wb_setup(
> >>>>
> >>>>           dpu_encoder_phys_wb_setup_fb(phys_enc, fb);
> >>>>
> >>>> -       dpu_encoder_phys_wb_setup_ctl(phys_enc);
> >>>> +       dpu_encoder_helper_phys_setup_cdm(phys_enc);
> >>>>
> >>>> +       dpu_encoder_phys_wb_setup_ctl(phys_enc);
> >>>>    }
> >>>>
> >>>>    static void _dpu_encoder_phys_wb_frame_done_helper(void *arg)
> >>>> --
> >>>> 2.40.1
> >>>>
> >>>
> >>>
> >
> >
> >



-- 
With best wishes
Dmitry

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

* Re: [PATCH 07/16] drm/msm/dpu: add cdm blocks to RM
  2023-11-30 23:47       ` Abhinav Kumar
@ 2023-12-06 21:02         ` Abhinav Kumar
  -1 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-12-06 21:02 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul



On 11/30/2023 3:47 PM, Abhinav Kumar wrote:
> 
> 
> On 8/30/2023 4:48 PM, Dmitry Baryshkov wrote:
>> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar 
>> <quic_abhinavk@quicinc.com> wrote:
>>>
>>> Add the RM APIs necessary to initialize and allocate CDM
>>> blocks by the rest of the DPU pipeline.
>>
>> ... to be used by the rest?
>>
> 
> Yes, thanks.
> 
> 
>>>
>>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>>> ---
>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 17 +++++++++++++++++
>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h |  2 ++
>>>   2 files changed, 19 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c 
>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>> index f9215643c71a..7b6444a3fcb1 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>> @@ -8,6 +8,7 @@
>>>   #include "dpu_kms.h"
>>>   #include "dpu_hw_lm.h"
>>>   #include "dpu_hw_ctl.h"
>>> +#include "dpu_hw_cdm.h"
>>>   #include "dpu_hw_pingpong.h"
>>>   #include "dpu_hw_sspp.h"
>>>   #include "dpu_hw_intf.h"
>>> @@ -90,6 +91,9 @@ int dpu_rm_destroy(struct dpu_rm *rm)
>>>                  }
>>>          }
>>>
>>> +       if (rm->cdm_blk)
>>> +               dpu_hw_cdm_destroy(to_dpu_hw_cdm(rm->cdm_blk));
>>> +
>>>          for (i = 0; i < ARRAY_SIZE(rm->hw_wb); i++)
>>>                  dpu_hw_wb_destroy(rm->hw_wb[i]);
>>>
>>> @@ -240,6 +244,19 @@ int dpu_rm_init(struct dpu_rm *rm,
>>>                  rm->hw_sspp[sspp->id - SSPP_NONE] = hw;
>>>          }
>>>
>>> +       if (cat->cdm) {
>>> +               struct dpu_hw_cdm *hw;
>>> +
>>> +               hw = dpu_hw_cdm_init(cat->cdm, mmio);
>>> +               /* CDM is optional so no need to bail out */
>>> +               if (IS_ERR(hw)) {
>>> +                       rc = PTR_ERR(hw);
>>> +                       DPU_DEBUG("failed cdm object creation: err 
>>> %d\n", rc);
>>
>> No. If it is a part of the catalog, we should fail here as we do in 
>> other cases.
>>
> 
> I guess, the only reason for not failing here was other hw blocks are 
> needed even for basic display to come up but cdm is only for YUV formats.
> 
> Thats the only reason to mark this a failure which is "OK" to ignore.
> 
> But I see your point that if someone is listing this in the catalog but 
> still RM fails thats an error.
> 
> Hence, ack.
> 
>>
>>> +               } else {
>>> +                       rm->cdm_blk = &hw->base;
>>> +               }
>>> +       }
>>> +
>>>          return 0;
>>>
>>>   fail:
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h 
>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>> index 2b551566cbf4..29b221491926 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>> @@ -22,6 +22,7 @@ struct dpu_global_state;
>>>    * @hw_wb: array of wb hardware resources
>>>    * @dspp_blks: array of dspp hardware resources
>>>    * @hw_sspp: array of sspp hardware resources
>>> + * @cdm_blk: cdm hardware resource
>>>    */
>>>   struct dpu_rm {
>>>          struct dpu_hw_blk *pingpong_blks[PINGPONG_MAX - PINGPONG_0];
>>> @@ -33,6 +34,7 @@ struct dpu_rm {
>>>          struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0];
>>>          struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0];
>>>          struct dpu_hw_sspp *hw_sspp[SSPP_MAX - SSPP_NONE];
>>> +       struct dpu_hw_blk *cdm_blk;
>>
>> struct dpu_hw_cdm *cdm (or cdm_blk), please.
> 
> Ack.
> 

I was going through this more. I think its better we leave this as a 
dpu_hw_blk because if you see the other blks in struct dpu_rm, all the 
blocks which are allocated dynamically / can change dynamically are of 
dpu_hw_blk type. That way the dpu_rm_get_assigned_resources() remains 
generic. Hence I would prefer to leave it this way.

>>
>>>   };
>>>
>>>   /**
>>> -- 
>>> 2.40.1
>>>
>>
>>
>> -- 
>> With best wishes
>> Dmitry

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

* Re: [PATCH 07/16] drm/msm/dpu: add cdm blocks to RM
@ 2023-12-06 21:02         ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-12-06 21:02 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Sean Paul, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, Marijn Suijten, quic_jesszhan, freedreno



On 11/30/2023 3:47 PM, Abhinav Kumar wrote:
> 
> 
> On 8/30/2023 4:48 PM, Dmitry Baryshkov wrote:
>> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar 
>> <quic_abhinavk@quicinc.com> wrote:
>>>
>>> Add the RM APIs necessary to initialize and allocate CDM
>>> blocks by the rest of the DPU pipeline.
>>
>> ... to be used by the rest?
>>
> 
> Yes, thanks.
> 
> 
>>>
>>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>>> ---
>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 17 +++++++++++++++++
>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h |  2 ++
>>>   2 files changed, 19 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c 
>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>> index f9215643c71a..7b6444a3fcb1 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>> @@ -8,6 +8,7 @@
>>>   #include "dpu_kms.h"
>>>   #include "dpu_hw_lm.h"
>>>   #include "dpu_hw_ctl.h"
>>> +#include "dpu_hw_cdm.h"
>>>   #include "dpu_hw_pingpong.h"
>>>   #include "dpu_hw_sspp.h"
>>>   #include "dpu_hw_intf.h"
>>> @@ -90,6 +91,9 @@ int dpu_rm_destroy(struct dpu_rm *rm)
>>>                  }
>>>          }
>>>
>>> +       if (rm->cdm_blk)
>>> +               dpu_hw_cdm_destroy(to_dpu_hw_cdm(rm->cdm_blk));
>>> +
>>>          for (i = 0; i < ARRAY_SIZE(rm->hw_wb); i++)
>>>                  dpu_hw_wb_destroy(rm->hw_wb[i]);
>>>
>>> @@ -240,6 +244,19 @@ int dpu_rm_init(struct dpu_rm *rm,
>>>                  rm->hw_sspp[sspp->id - SSPP_NONE] = hw;
>>>          }
>>>
>>> +       if (cat->cdm) {
>>> +               struct dpu_hw_cdm *hw;
>>> +
>>> +               hw = dpu_hw_cdm_init(cat->cdm, mmio);
>>> +               /* CDM is optional so no need to bail out */
>>> +               if (IS_ERR(hw)) {
>>> +                       rc = PTR_ERR(hw);
>>> +                       DPU_DEBUG("failed cdm object creation: err 
>>> %d\n", rc);
>>
>> No. If it is a part of the catalog, we should fail here as we do in 
>> other cases.
>>
> 
> I guess, the only reason for not failing here was other hw blocks are 
> needed even for basic display to come up but cdm is only for YUV formats.
> 
> Thats the only reason to mark this a failure which is "OK" to ignore.
> 
> But I see your point that if someone is listing this in the catalog but 
> still RM fails thats an error.
> 
> Hence, ack.
> 
>>
>>> +               } else {
>>> +                       rm->cdm_blk = &hw->base;
>>> +               }
>>> +       }
>>> +
>>>          return 0;
>>>
>>>   fail:
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h 
>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>> index 2b551566cbf4..29b221491926 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>> @@ -22,6 +22,7 @@ struct dpu_global_state;
>>>    * @hw_wb: array of wb hardware resources
>>>    * @dspp_blks: array of dspp hardware resources
>>>    * @hw_sspp: array of sspp hardware resources
>>> + * @cdm_blk: cdm hardware resource
>>>    */
>>>   struct dpu_rm {
>>>          struct dpu_hw_blk *pingpong_blks[PINGPONG_MAX - PINGPONG_0];
>>> @@ -33,6 +34,7 @@ struct dpu_rm {
>>>          struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0];
>>>          struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0];
>>>          struct dpu_hw_sspp *hw_sspp[SSPP_MAX - SSPP_NONE];
>>> +       struct dpu_hw_blk *cdm_blk;
>>
>> struct dpu_hw_cdm *cdm (or cdm_blk), please.
> 
> Ack.
> 

I was going through this more. I think its better we leave this as a 
dpu_hw_blk because if you see the other blks in struct dpu_rm, all the 
blocks which are allocated dynamically / can change dynamically are of 
dpu_hw_blk type. That way the dpu_rm_get_assigned_resources() remains 
generic. Hence I would prefer to leave it this way.

>>
>>>   };
>>>
>>>   /**
>>> -- 
>>> 2.40.1
>>>
>>
>>
>> -- 
>> With best wishes
>> Dmitry

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

* Re: [PATCH 07/16] drm/msm/dpu: add cdm blocks to RM
  2023-12-06 21:02         ` Abhinav Kumar
@ 2023-12-06 22:23           ` Dmitry Baryshkov
  -1 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-12-06 22:23 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul

On Wed, 6 Dec 2023 at 23:02, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 11/30/2023 3:47 PM, Abhinav Kumar wrote:
> >
> >
> > On 8/30/2023 4:48 PM, Dmitry Baryshkov wrote:
> >> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar
> >> <quic_abhinavk@quicinc.com> wrote:
> >>>
> >>> Add the RM APIs necessary to initialize and allocate CDM
> >>> blocks by the rest of the DPU pipeline.
> >>
> >> ... to be used by the rest?
> >>
> >
> > Yes, thanks.
> >
> >
> >>>
> >>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> >>> ---
> >>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 17 +++++++++++++++++
> >>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h |  2 ++
> >>>   2 files changed, 19 insertions(+)
> >>>
> >>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >>> index f9215643c71a..7b6444a3fcb1 100644
> >>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >>> @@ -8,6 +8,7 @@
> >>>   #include "dpu_kms.h"
> >>>   #include "dpu_hw_lm.h"
> >>>   #include "dpu_hw_ctl.h"
> >>> +#include "dpu_hw_cdm.h"
> >>>   #include "dpu_hw_pingpong.h"
> >>>   #include "dpu_hw_sspp.h"
> >>>   #include "dpu_hw_intf.h"
> >>> @@ -90,6 +91,9 @@ int dpu_rm_destroy(struct dpu_rm *rm)
> >>>                  }
> >>>          }
> >>>
> >>> +       if (rm->cdm_blk)
> >>> +               dpu_hw_cdm_destroy(to_dpu_hw_cdm(rm->cdm_blk));
> >>> +
> >>>          for (i = 0; i < ARRAY_SIZE(rm->hw_wb); i++)
> >>>                  dpu_hw_wb_destroy(rm->hw_wb[i]);
> >>>
> >>> @@ -240,6 +244,19 @@ int dpu_rm_init(struct dpu_rm *rm,
> >>>                  rm->hw_sspp[sspp->id - SSPP_NONE] = hw;
> >>>          }
> >>>
> >>> +       if (cat->cdm) {
> >>> +               struct dpu_hw_cdm *hw;
> >>> +
> >>> +               hw = dpu_hw_cdm_init(cat->cdm, mmio);
> >>> +               /* CDM is optional so no need to bail out */
> >>> +               if (IS_ERR(hw)) {
> >>> +                       rc = PTR_ERR(hw);
> >>> +                       DPU_DEBUG("failed cdm object creation: err
> >>> %d\n", rc);
> >>
> >> No. If it is a part of the catalog, we should fail here as we do in
> >> other cases.
> >>
> >
> > I guess, the only reason for not failing here was other hw blocks are
> > needed even for basic display to come up but cdm is only for YUV formats.
> >
> > Thats the only reason to mark this a failure which is "OK" to ignore.
> >
> > But I see your point that if someone is listing this in the catalog but
> > still RM fails thats an error.
> >
> > Hence, ack.
> >
> >>
> >>> +               } else {
> >>> +                       rm->cdm_blk = &hw->base;
> >>> +               }
> >>> +       }
> >>> +
> >>>          return 0;
> >>>
> >>>   fail:
> >>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> >>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> >>> index 2b551566cbf4..29b221491926 100644
> >>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> >>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> >>> @@ -22,6 +22,7 @@ struct dpu_global_state;
> >>>    * @hw_wb: array of wb hardware resources
> >>>    * @dspp_blks: array of dspp hardware resources
> >>>    * @hw_sspp: array of sspp hardware resources
> >>> + * @cdm_blk: cdm hardware resource
> >>>    */
> >>>   struct dpu_rm {
> >>>          struct dpu_hw_blk *pingpong_blks[PINGPONG_MAX - PINGPONG_0];
> >>> @@ -33,6 +34,7 @@ struct dpu_rm {
> >>>          struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0];
> >>>          struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0];
> >>>          struct dpu_hw_sspp *hw_sspp[SSPP_MAX - SSPP_NONE];
> >>> +       struct dpu_hw_blk *cdm_blk;
> >>
> >> struct dpu_hw_cdm *cdm (or cdm_blk), please.
> >
> > Ack.
> >
>
> I was going through this more. I think its better we leave this as a
> dpu_hw_blk because if you see the other blks in struct dpu_rm, all the
> blocks which are allocated dynamically / can change dynamically are of
> dpu_hw_blk type. That way the dpu_rm_get_assigned_resources() remains
> generic. Hence I would prefer to leave it this way.

Ack

>
> >>
> >>>   };
> >>>
> >>>   /**
> >>> --
> >>> 2.40.1
> >>>
> >>
> >>
> >> --
> >> With best wishes
> >> Dmitry



-- 
With best wishes
Dmitry

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

* Re: [PATCH 07/16] drm/msm/dpu: add cdm blocks to RM
@ 2023-12-06 22:23           ` Dmitry Baryshkov
  0 siblings, 0 replies; 105+ messages in thread
From: Dmitry Baryshkov @ 2023-12-06 22:23 UTC (permalink / raw)
  To: Abhinav Kumar
  Cc: Sean Paul, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, Marijn Suijten, quic_jesszhan, freedreno

On Wed, 6 Dec 2023 at 23:02, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 11/30/2023 3:47 PM, Abhinav Kumar wrote:
> >
> >
> > On 8/30/2023 4:48 PM, Dmitry Baryshkov wrote:
> >> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar
> >> <quic_abhinavk@quicinc.com> wrote:
> >>>
> >>> Add the RM APIs necessary to initialize and allocate CDM
> >>> blocks by the rest of the DPU pipeline.
> >>
> >> ... to be used by the rest?
> >>
> >
> > Yes, thanks.
> >
> >
> >>>
> >>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> >>> ---
> >>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 17 +++++++++++++++++
> >>>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h |  2 ++
> >>>   2 files changed, 19 insertions(+)
> >>>
> >>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >>> index f9215643c71a..7b6444a3fcb1 100644
> >>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >>> @@ -8,6 +8,7 @@
> >>>   #include "dpu_kms.h"
> >>>   #include "dpu_hw_lm.h"
> >>>   #include "dpu_hw_ctl.h"
> >>> +#include "dpu_hw_cdm.h"
> >>>   #include "dpu_hw_pingpong.h"
> >>>   #include "dpu_hw_sspp.h"
> >>>   #include "dpu_hw_intf.h"
> >>> @@ -90,6 +91,9 @@ int dpu_rm_destroy(struct dpu_rm *rm)
> >>>                  }
> >>>          }
> >>>
> >>> +       if (rm->cdm_blk)
> >>> +               dpu_hw_cdm_destroy(to_dpu_hw_cdm(rm->cdm_blk));
> >>> +
> >>>          for (i = 0; i < ARRAY_SIZE(rm->hw_wb); i++)
> >>>                  dpu_hw_wb_destroy(rm->hw_wb[i]);
> >>>
> >>> @@ -240,6 +244,19 @@ int dpu_rm_init(struct dpu_rm *rm,
> >>>                  rm->hw_sspp[sspp->id - SSPP_NONE] = hw;
> >>>          }
> >>>
> >>> +       if (cat->cdm) {
> >>> +               struct dpu_hw_cdm *hw;
> >>> +
> >>> +               hw = dpu_hw_cdm_init(cat->cdm, mmio);
> >>> +               /* CDM is optional so no need to bail out */
> >>> +               if (IS_ERR(hw)) {
> >>> +                       rc = PTR_ERR(hw);
> >>> +                       DPU_DEBUG("failed cdm object creation: err
> >>> %d\n", rc);
> >>
> >> No. If it is a part of the catalog, we should fail here as we do in
> >> other cases.
> >>
> >
> > I guess, the only reason for not failing here was other hw blocks are
> > needed even for basic display to come up but cdm is only for YUV formats.
> >
> > Thats the only reason to mark this a failure which is "OK" to ignore.
> >
> > But I see your point that if someone is listing this in the catalog but
> > still RM fails thats an error.
> >
> > Hence, ack.
> >
> >>
> >>> +               } else {
> >>> +                       rm->cdm_blk = &hw->base;
> >>> +               }
> >>> +       }
> >>> +
> >>>          return 0;
> >>>
> >>>   fail:
> >>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> >>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> >>> index 2b551566cbf4..29b221491926 100644
> >>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> >>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> >>> @@ -22,6 +22,7 @@ struct dpu_global_state;
> >>>    * @hw_wb: array of wb hardware resources
> >>>    * @dspp_blks: array of dspp hardware resources
> >>>    * @hw_sspp: array of sspp hardware resources
> >>> + * @cdm_blk: cdm hardware resource
> >>>    */
> >>>   struct dpu_rm {
> >>>          struct dpu_hw_blk *pingpong_blks[PINGPONG_MAX - PINGPONG_0];
> >>> @@ -33,6 +34,7 @@ struct dpu_rm {
> >>>          struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0];
> >>>          struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0];
> >>>          struct dpu_hw_sspp *hw_sspp[SSPP_MAX - SSPP_NONE];
> >>> +       struct dpu_hw_blk *cdm_blk;
> >>
> >> struct dpu_hw_cdm *cdm (or cdm_blk), please.
> >
> > Ack.
> >
>
> I was going through this more. I think its better we leave this as a
> dpu_hw_blk because if you see the other blks in struct dpu_rm, all the
> blocks which are allocated dynamically / can change dynamically are of
> dpu_hw_blk type. That way the dpu_rm_get_assigned_resources() remains
> generic. Hence I would prefer to leave it this way.

Ack

>
> >>
> >>>   };
> >>>
> >>>   /**
> >>> --
> >>> 2.40.1
> >>>
> >>
> >>
> >> --
> >> With best wishes
> >> Dmitry



-- 
With best wishes
Dmitry

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

* Re: [PATCH 15/16] drm/msm/dpu: add NV12 in the list of supported WB formats
  2023-08-31  0:26     ` Dmitry Baryshkov
@ 2023-12-07  1:09       ` Abhinav Kumar
  -1 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-12-07  1:09 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
	Daniel Vetter, dri-devel, quic_jesszhan, quic_parellan,
	quic_khsieh, linux-arm-msm, linux-kernel



On 8/30/2023 5:26 PM, Dmitry Baryshkov wrote:
> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> Since CDM block support has now been added for writeback blocks
>> add NV12 in the list of supported WB formats.
>>
>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 1 +
>>   1 file changed, 1 insertion(+)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>> index 713dfc079718..978330c6678e 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>> @@ -244,6 +244,7 @@ static const uint32_t wb2_formats[] = {
>>          DRM_FORMAT_BGRA4444,
>>          DRM_FORMAT_BGRX4444,
>>          DRM_FORMAT_XBGR4444,
>> +       DRM_FORMAT_NV12,
>>   };
> 
> No. This way the driver would announce availability of NV12 even on
> chipsets where NV12 is not supported for the writeback. Please define
> separate formats array.
> 
> BTW: does HW only support NV12 for the writeback? What about YV12 or e.g. NV21?
> 

Yes, as we discussed in the prev patch, I will split the wb2_formats 
array to RGB only and RGB+YUV to address this issue.

Regarding the full list of supported formats, here it is:

https://git.codelinaro.org/clo/la/platform/vendor/opensource/display-drivers/-/blob/clo/main/msm/sde/sde_hw_catalog_format.h?ref_type=heads#L107

But YUV420 shouldnt be here as its not supported.

I have to see if I can add some test cases in IGT to validate NV16 and 
DRM_FORMAT_YUYV. Hence I only exposed this one for now.

>>
>>   /*************************************************************
>> --
>> 2.40.1
>>
> 
> 

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

* Re: [PATCH 15/16] drm/msm/dpu: add NV12 in the list of supported WB formats
@ 2023-12-07  1:09       ` Abhinav Kumar
  0 siblings, 0 replies; 105+ messages in thread
From: Abhinav Kumar @ 2023-12-07  1:09 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: freedreno, linux-arm-msm, linux-kernel, dri-devel, quic_khsieh,
	quic_parellan, quic_jesszhan, Marijn Suijten, Sean Paul



On 8/30/2023 5:26 PM, Dmitry Baryshkov wrote:
> On Thu, 31 Aug 2023 at 01:50, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>> Since CDM block support has now been added for writeback blocks
>> add NV12 in the list of supported WB formats.
>>
>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 1 +
>>   1 file changed, 1 insertion(+)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>> index 713dfc079718..978330c6678e 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
>> @@ -244,6 +244,7 @@ static const uint32_t wb2_formats[] = {
>>          DRM_FORMAT_BGRA4444,
>>          DRM_FORMAT_BGRX4444,
>>          DRM_FORMAT_XBGR4444,
>> +       DRM_FORMAT_NV12,
>>   };
> 
> No. This way the driver would announce availability of NV12 even on
> chipsets where NV12 is not supported for the writeback. Please define
> separate formats array.
> 
> BTW: does HW only support NV12 for the writeback? What about YV12 or e.g. NV21?
> 

Yes, as we discussed in the prev patch, I will split the wb2_formats 
array to RGB only and RGB+YUV to address this issue.

Regarding the full list of supported formats, here it is:

https://git.codelinaro.org/clo/la/platform/vendor/opensource/display-drivers/-/blob/clo/main/msm/sde/sde_hw_catalog_format.h?ref_type=heads#L107

But YUV420 shouldnt be here as its not supported.

I have to see if I can add some test cases in IGT to validate NV16 and 
DRM_FORMAT_YUYV. Hence I only exposed this one for now.

>>
>>   /*************************************************************
>> --
>> 2.40.1
>>
> 
> 

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

end of thread, other threads:[~2023-12-07  1:09 UTC | newest]

Thread overview: 105+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-30 22:48 [PATCH 00/16] Add CDM support for MSM writeback Abhinav Kumar
2023-08-30 22:48 ` [PATCH 01/16] drm/msm/dpu: fix writeback programming for YUV cases Abhinav Kumar
2023-08-30 22:48   ` Abhinav Kumar
2023-08-30 23:38   ` Dmitry Baryshkov
2023-08-30 23:38     ` Dmitry Baryshkov
2023-08-30 22:48 ` [PATCH 02/16] drm/msm/dpu: add formats check for writeback encoder Abhinav Kumar
2023-08-30 22:48   ` Abhinav Kumar
2023-08-30 23:39   ` Dmitry Baryshkov
2023-08-30 23:39     ` Dmitry Baryshkov
2023-08-30 22:48 ` [PATCH 03/16] drm/msm/dpu: rename dpu_encoder_phys_wb_setup_cdp to match its functionality Abhinav Kumar
2023-08-30 22:48   ` Abhinav Kumar
2023-08-30 23:40   ` Dmitry Baryshkov
2023-08-30 23:40     ` Dmitry Baryshkov
2023-08-30 22:48 ` [PATCH 04/16] drm/msm/dpu: add cdm blocks to sc7280 dpu_hw_catalog Abhinav Kumar
2023-08-30 22:48   ` Abhinav Kumar
2023-08-30 22:57   ` Dmitry Baryshkov
2023-08-30 22:57     ` Dmitry Baryshkov
2023-11-30 22:41     ` Abhinav Kumar
2023-11-30 22:41       ` Abhinav Kumar
2023-08-30 22:48 ` [PATCH 05/16] drm/msm/dpu: add cdm blocks to sm8250 dpu_hw_catalog Abhinav Kumar
2023-08-30 22:48   ` Abhinav Kumar
2023-08-30 22:48 ` [PATCH 06/16] drm/msm/dpu: add dpu_hw_cdm abstraction for CDM block Abhinav Kumar
2023-08-30 22:48   ` Abhinav Kumar
2023-08-31  0:00   ` Dmitry Baryshkov
2023-08-31  0:00     ` Dmitry Baryshkov
2023-11-30 23:36     ` Abhinav Kumar
2023-11-30 23:36       ` Abhinav Kumar
2023-12-01  7:05       ` Dmitry Baryshkov
2023-12-01  7:05         ` Dmitry Baryshkov
2023-12-01 18:19         ` Abhinav Kumar
2023-12-01 18:19           ` Abhinav Kumar
2023-12-01 21:10           ` Dmitry Baryshkov
2023-12-01 21:10             ` Dmitry Baryshkov
2023-08-30 22:49 ` [PATCH 07/16] drm/msm/dpu: add cdm blocks to RM Abhinav Kumar
2023-08-30 22:49   ` Abhinav Kumar
2023-08-30 23:48   ` Dmitry Baryshkov
2023-08-30 23:48     ` Dmitry Baryshkov
2023-11-30 23:47     ` Abhinav Kumar
2023-11-30 23:47       ` Abhinav Kumar
2023-12-06 21:02       ` Abhinav Kumar
2023-12-06 21:02         ` Abhinav Kumar
2023-12-06 22:23         ` Dmitry Baryshkov
2023-12-06 22:23           ` Dmitry Baryshkov
2023-08-30 22:49 ` [PATCH 08/16] drm/msm/dpu: add support to allocate CDM from RM Abhinav Kumar
2023-08-30 22:49   ` Abhinav Kumar
2023-08-31  0:06   ` Dmitry Baryshkov
2023-08-31  0:06     ` Dmitry Baryshkov
2023-11-30 23:50     ` Abhinav Kumar
2023-11-30 23:50       ` Abhinav Kumar
2023-12-01  8:39       ` Dmitry Baryshkov
2023-12-01  8:39         ` Dmitry Baryshkov
2023-08-30 22:49 ` [PATCH 09/16] drm/msm/dpu: add CDM related logic to dpu_hw_ctl layer Abhinav Kumar
2023-08-30 22:49   ` Abhinav Kumar
2023-08-31  0:12   ` Dmitry Baryshkov
2023-08-31  0:12     ` Dmitry Baryshkov
2023-11-30 23:54     ` Abhinav Kumar
2023-11-30 23:54       ` Abhinav Kumar
2023-08-30 22:49 ` [PATCH 10/16] drm/msm/dpu: add support to disable CDM block during encoder cleanup Abhinav Kumar
2023-08-30 22:49   ` Abhinav Kumar
2023-08-31  0:14   ` Dmitry Baryshkov
2023-08-31  0:14     ` Dmitry Baryshkov
2023-11-30 23:58     ` Abhinav Kumar
2023-11-30 23:58       ` Abhinav Kumar
2023-12-01  8:36       ` Dmitry Baryshkov
2023-12-01  8:36         ` Dmitry Baryshkov
2023-08-30 22:49 ` [PATCH 11/16] drm/msm/dpu: add an API to setup the CDM block for writeback Abhinav Kumar
2023-08-30 22:49   ` Abhinav Kumar
2023-08-31  0:11   ` Dmitry Baryshkov
2023-08-31  0:11     ` Dmitry Baryshkov
2023-12-01  0:41     ` Abhinav Kumar
2023-12-01  0:41       ` Abhinav Kumar
2023-12-01  7:20       ` Dmitry Baryshkov
2023-12-01  7:20         ` Dmitry Baryshkov
2023-12-01 19:04         ` Abhinav Kumar
2023-12-01 19:04           ` Abhinav Kumar
2023-12-01 21:15           ` [Freedreno] " Dmitry Baryshkov
2023-12-01 21:15             ` Dmitry Baryshkov
2023-08-30 22:49 ` [PATCH 12/16] drm/msm/dpu: plug-in the cdm related bits to writeback setup Abhinav Kumar
2023-08-30 22:49   ` Abhinav Kumar
2023-08-31  0:15   ` Dmitry Baryshkov
2023-08-31  0:15     ` Dmitry Baryshkov
2023-08-30 22:49 ` [PATCH 13/16] drm/msm/dpu: reserve cdm blocks for writeback in case of YUV output Abhinav Kumar
2023-08-30 22:49   ` Abhinav Kumar
2023-08-31  0:23   ` Dmitry Baryshkov
2023-08-31  0:23     ` Dmitry Baryshkov
2023-12-01  0:45     ` Abhinav Kumar
2023-12-01  0:45       ` Abhinav Kumar
2023-08-30 22:49 ` [PATCH 14/16] drm/msm/dpu: do not allow YUV formats if no CDM block is present Abhinav Kumar
2023-08-30 22:49   ` Abhinav Kumar
2023-08-31  0:24   ` Dmitry Baryshkov
2023-08-31  0:24     ` Dmitry Baryshkov
2023-12-01  0:50     ` Abhinav Kumar
2023-12-01  0:50       ` Abhinav Kumar
2023-12-01  7:14       ` Dmitry Baryshkov
2023-12-01  7:14         ` Dmitry Baryshkov
2023-08-30 22:49 ` [PATCH 15/16] drm/msm/dpu: add NV12 in the list of supported WB formats Abhinav Kumar
2023-08-30 22:49   ` Abhinav Kumar
2023-08-31  0:26   ` Dmitry Baryshkov
2023-08-31  0:26     ` Dmitry Baryshkov
2023-12-07  1:09     ` Abhinav Kumar
2023-12-07  1:09       ` Abhinav Kumar
2023-08-30 22:49 ` [PATCH 16/16] drm/msm/dpu: add cdm blocks to dpu snapshot Abhinav Kumar
2023-08-30 22:49   ` Abhinav Kumar
2023-08-31  0:27   ` Dmitry Baryshkov
2023-08-31  0:27     ` Dmitry Baryshkov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.