All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support
@ 2021-05-21 12:49 ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, David Airlie,
	Daniel Vetter, Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar,
	linux-kernel, dri-devel, freedreno, Rob Herring, devicetree

Display Stream Compression (DSC) compresses the display stream in host which
is later decoded by panel. This series enables this for Qualcomm msm driver.
This was tested on Google Pixel3 phone which use LGE SW43408 panel.

The changes include adding DT properties for DSC then hardware blocks support
required in DPU1 driver and support in encoder. We also add support in DSI
and introduce required topology changes.

In order for panel to set the DSC parameters we add dsc in drm_panel and set
it from the msm driver.

Complete changes which enable this for Pixel3 along with panel driver (not
part of this series) and DT changes can be found at:
git.linaro.org/people/vinod.koul/kernel.git pixel/dsc_rfc

Comments welcome!

Vinod Koul (13):
  drm/dsc: Add dsc pps header init function
  dt-bindings: msm/dsi: Document Display Stream Compression (DSC)
    parameters
  drm/msm/dsi: add support for dsc data
  drm/msm/disp/dpu1: Add support for DSC
  drm/msm/disp/dpu1: Add support for DSC in pingpong block
  drm/msm/disp/dpu1: Add DSC support in RM
  drm/msm/disp/dpu1: Add DSC for SDM845 to hw_catalog
  drm/msm/disp/dpu1: Add DSC support in hw_ctl
  drm/msm/disp/dpu1: Don't use DSC with mode_3d
  drm/msm/disp/dpu1: Add support for DSC in encoder
  drm/msm/disp/dpu1: Add support for DSC in topology
  drm/msm/dsi: Add support for DSC configuration
  drm/msm/dsi: Pass DSC params to drm_panel

 .../devicetree/bindings/display/msm/dsi.txt   |  15 +
 drivers/gpu/drm/drm_dsc.c                     |  11 +
 drivers/gpu/drm/msm/Makefile                  |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 204 +++++++++++-
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  11 +
 .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c  |   2 +
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c    |  22 ++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |  26 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c    |  12 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h    |   2 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c    | 221 +++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h    |  79 +++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 +
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   |  32 ++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   |  14 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h       |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c        |  32 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h        |   1 +
 drivers/gpu/drm/msm/dsi/dsi.xml.h             |  10 +
 drivers/gpu/drm/msm/dsi/dsi_host.c            | 293 +++++++++++++++++-
 drivers/gpu/drm/msm/msm_drv.h                 |  32 ++
 include/drm/drm_dsc.h                         |  16 +
 include/drm/drm_panel.h                       |   7 +
 23 files changed, 1043 insertions(+), 14 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h

-- 
2.26.3


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

* [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support
@ 2021-05-21 12:49 ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: devicetree, Jonathan Marek, David Airlie, linux-arm-msm,
	linux-kernel, Abhinav Kumar, Bjorn Andersson, Vinod Koul,
	Rob Herring, dri-devel, Dmitry Baryshkov, freedreno

Display Stream Compression (DSC) compresses the display stream in host which
is later decoded by panel. This series enables this for Qualcomm msm driver.
This was tested on Google Pixel3 phone which use LGE SW43408 panel.

The changes include adding DT properties for DSC then hardware blocks support
required in DPU1 driver and support in encoder. We also add support in DSI
and introduce required topology changes.

In order for panel to set the DSC parameters we add dsc in drm_panel and set
it from the msm driver.

Complete changes which enable this for Pixel3 along with panel driver (not
part of this series) and DT changes can be found at:
git.linaro.org/people/vinod.koul/kernel.git pixel/dsc_rfc

Comments welcome!

Vinod Koul (13):
  drm/dsc: Add dsc pps header init function
  dt-bindings: msm/dsi: Document Display Stream Compression (DSC)
    parameters
  drm/msm/dsi: add support for dsc data
  drm/msm/disp/dpu1: Add support for DSC
  drm/msm/disp/dpu1: Add support for DSC in pingpong block
  drm/msm/disp/dpu1: Add DSC support in RM
  drm/msm/disp/dpu1: Add DSC for SDM845 to hw_catalog
  drm/msm/disp/dpu1: Add DSC support in hw_ctl
  drm/msm/disp/dpu1: Don't use DSC with mode_3d
  drm/msm/disp/dpu1: Add support for DSC in encoder
  drm/msm/disp/dpu1: Add support for DSC in topology
  drm/msm/dsi: Add support for DSC configuration
  drm/msm/dsi: Pass DSC params to drm_panel

 .../devicetree/bindings/display/msm/dsi.txt   |  15 +
 drivers/gpu/drm/drm_dsc.c                     |  11 +
 drivers/gpu/drm/msm/Makefile                  |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 204 +++++++++++-
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  11 +
 .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c  |   2 +
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c    |  22 ++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |  26 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c    |  12 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h    |   2 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c    | 221 +++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h    |  79 +++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 +
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   |  32 ++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   |  14 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h       |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c        |  32 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h        |   1 +
 drivers/gpu/drm/msm/dsi/dsi.xml.h             |  10 +
 drivers/gpu/drm/msm/dsi/dsi_host.c            | 293 +++++++++++++++++-
 drivers/gpu/drm/msm/msm_drv.h                 |  32 ++
 include/drm/drm_dsc.h                         |  16 +
 include/drm/drm_panel.h                       |   7 +
 23 files changed, 1043 insertions(+), 14 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h

-- 
2.26.3


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

* [RFC PATCH 01/13] drm/dsc: Add dsc pps header init function
  2021-05-21 12:49 ` Vinod Koul
@ 2021-05-21 12:49   ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, David Airlie,
	Daniel Vetter, Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar,
	linux-kernel, dri-devel, freedreno

We required a helper to create and set the dsc_dce_header, so add the
dsc_dce_header and API drm_dsc_dsi_pps_header_init

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/drm_dsc.c | 11 +++++++++++
 include/drm/drm_dsc.h     | 16 ++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/drivers/gpu/drm/drm_dsc.c b/drivers/gpu/drm/drm_dsc.c
index ff602f7ec65b..0c1b745090e2 100644
--- a/drivers/gpu/drm/drm_dsc.c
+++ b/drivers/gpu/drm/drm_dsc.c
@@ -49,6 +49,17 @@ void drm_dsc_dp_pps_header_init(struct dp_sdp_header *pps_header)
 }
 EXPORT_SYMBOL(drm_dsc_dp_pps_header_init);
 
+void drm_dsc_dsi_pps_header_init(struct dsc_dce_header *dsc_header)
+{
+	memset(dsc_header, 0, sizeof(*dsc_header));
+
+	dsc_header->bp0 = 0x0A;
+	dsc_header->bp1 = 1;
+	dsc_header->bp4 = 10;
+	dsc_header->bp6 = 128;
+}
+EXPORT_SYMBOL(drm_dsc_dsi_pps_header_init);
+
 /**
  * drm_dsc_dp_rc_buffer_size - get rc buffer size in bytes
  * @rc_buffer_block_size: block size code, according to DPCD offset 62h
diff --git a/include/drm/drm_dsc.h b/include/drm/drm_dsc.h
index bbe120f461e5..5a3bbeb3e12f 100644
--- a/include/drm/drm_dsc.h
+++ b/include/drm/drm_dsc.h
@@ -602,8 +602,24 @@ struct drm_dsc_pps_infoframe {
 	struct drm_dsc_picture_parameter_set pps_payload;
 } __packed;
 
+struct dsc_dce_header {
+	u8 bp0;
+	u8 bp1;
+	u8 bp2;
+	u8 bp3;
+	u8 bp4;
+	u8 bp5;
+	u8 bp6;
+} __packed;
+
+struct drm_dsi_dsc_infoframe {
+	struct dsc_dce_header dsc_header;
+	struct drm_dsc_picture_parameter_set pps_payload;
+} __packed;
+
 void drm_dsc_dp_pps_header_init(struct dp_sdp_header *pps_header);
 int drm_dsc_dp_rc_buffer_size(u8 rc_buffer_block_size, u8 rc_buffer_size);
+void drm_dsc_dsi_pps_header_init(struct dsc_dce_header *dsc_header);
 void drm_dsc_pps_payload_pack(struct drm_dsc_picture_parameter_set *pps_sdp,
 				const struct drm_dsc_config *dsc_cfg);
 int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg);
-- 
2.26.3


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

* [RFC PATCH 01/13] drm/dsc: Add dsc pps header init function
@ 2021-05-21 12:49   ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, Vinod Koul, dri-devel,
	Dmitry Baryshkov, freedreno

We required a helper to create and set the dsc_dce_header, so add the
dsc_dce_header and API drm_dsc_dsi_pps_header_init

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/drm_dsc.c | 11 +++++++++++
 include/drm/drm_dsc.h     | 16 ++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/drivers/gpu/drm/drm_dsc.c b/drivers/gpu/drm/drm_dsc.c
index ff602f7ec65b..0c1b745090e2 100644
--- a/drivers/gpu/drm/drm_dsc.c
+++ b/drivers/gpu/drm/drm_dsc.c
@@ -49,6 +49,17 @@ void drm_dsc_dp_pps_header_init(struct dp_sdp_header *pps_header)
 }
 EXPORT_SYMBOL(drm_dsc_dp_pps_header_init);
 
+void drm_dsc_dsi_pps_header_init(struct dsc_dce_header *dsc_header)
+{
+	memset(dsc_header, 0, sizeof(*dsc_header));
+
+	dsc_header->bp0 = 0x0A;
+	dsc_header->bp1 = 1;
+	dsc_header->bp4 = 10;
+	dsc_header->bp6 = 128;
+}
+EXPORT_SYMBOL(drm_dsc_dsi_pps_header_init);
+
 /**
  * drm_dsc_dp_rc_buffer_size - get rc buffer size in bytes
  * @rc_buffer_block_size: block size code, according to DPCD offset 62h
diff --git a/include/drm/drm_dsc.h b/include/drm/drm_dsc.h
index bbe120f461e5..5a3bbeb3e12f 100644
--- a/include/drm/drm_dsc.h
+++ b/include/drm/drm_dsc.h
@@ -602,8 +602,24 @@ struct drm_dsc_pps_infoframe {
 	struct drm_dsc_picture_parameter_set pps_payload;
 } __packed;
 
+struct dsc_dce_header {
+	u8 bp0;
+	u8 bp1;
+	u8 bp2;
+	u8 bp3;
+	u8 bp4;
+	u8 bp5;
+	u8 bp6;
+} __packed;
+
+struct drm_dsi_dsc_infoframe {
+	struct dsc_dce_header dsc_header;
+	struct drm_dsc_picture_parameter_set pps_payload;
+} __packed;
+
 void drm_dsc_dp_pps_header_init(struct dp_sdp_header *pps_header);
 int drm_dsc_dp_rc_buffer_size(u8 rc_buffer_block_size, u8 rc_buffer_size);
+void drm_dsc_dsi_pps_header_init(struct dsc_dce_header *dsc_header);
 void drm_dsc_pps_payload_pack(struct drm_dsc_picture_parameter_set *pps_sdp,
 				const struct drm_dsc_config *dsc_cfg);
 int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg);
-- 
2.26.3


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

* [RFC PATCH 02/13] dt-bindings: msm/dsi: Document Display Stream Compression (DSC) parameters
  2021-05-21 12:49 ` Vinod Koul
@ 2021-05-21 12:49   ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, David Airlie,
	Daniel Vetter, Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar,
	linux-kernel, dri-devel, freedreno, Rob Herring, devicetree

DSC enables streams to be compressed before we send to panel. This
requires DSC enabled encoder and a panel to be present. So we add this
information in board DTS and find if DSC can be enabled and the
parameters required to configure DSC are added to binding document along
with example

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 .../devicetree/bindings/display/msm/dsi.txt       | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/msm/dsi.txt b/Documentation/devicetree/bindings/display/msm/dsi.txt
index b9a64d3ff184..83d2fb92267e 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi.txt
+++ b/Documentation/devicetree/bindings/display/msm/dsi.txt
@@ -48,6 +48,13 @@ Optional properties:
 - pinctrl-n: the "sleep" pinctrl state
 - ports: contains DSI controller input and output ports as children, each
   containing one endpoint subnode.
+- qcom,mdss-dsc-enabled: Display Stream Compression (DSC) is enabled
+- qcom,mdss-slice-height: DSC slice height in pixels
+- qcom,mdss-slice-width: DSC slice width in pixels
+- qcom,mdss-slice-per-pkt: DSC slices per packet
+- qcom,mdss-bit-per-component: DSC bits per component
+- qcom,mdss-bit-per-pixel: DSC bits per pixel
+- qcom,mdss-block-prediction-enable: Block prediction mode of DSC enabled
 
   DSI Endpoint properties:
   - remote-endpoint: For port@0, set to phandle of the connected panel/bridge's
@@ -188,6 +195,14 @@ Example:
 		qcom,master-dsi;
 		qcom,sync-dual-dsi;
 
+		qcom,mdss-dsc-enabled;
+		qcom,mdss-slice-height = <16>;
+		qcom,mdss-slice-width = <540>;
+		qcom,mdss-slice-per-pkt = <1>;
+		qcom,mdss-bit-per-component = <8>;
+		qcom,mdss-bit-per-pixel = <8>;
+		qcom,mdss-block-prediction-enable;
+
 		qcom,mdss-mdp-transfer-time-us = <12000>;
 
 		pinctrl-names = "default", "sleep";
-- 
2.26.3


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

* [RFC PATCH 02/13] dt-bindings: msm/dsi: Document Display Stream Compression (DSC) parameters
@ 2021-05-21 12:49   ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: devicetree, Jonathan Marek, David Airlie, linux-arm-msm,
	linux-kernel, Abhinav Kumar, Bjorn Andersson, Vinod Koul,
	Rob Herring, dri-devel, Dmitry Baryshkov, freedreno

DSC enables streams to be compressed before we send to panel. This
requires DSC enabled encoder and a panel to be present. So we add this
information in board DTS and find if DSC can be enabled and the
parameters required to configure DSC are added to binding document along
with example

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 .../devicetree/bindings/display/msm/dsi.txt       | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/msm/dsi.txt b/Documentation/devicetree/bindings/display/msm/dsi.txt
index b9a64d3ff184..83d2fb92267e 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi.txt
+++ b/Documentation/devicetree/bindings/display/msm/dsi.txt
@@ -48,6 +48,13 @@ Optional properties:
 - pinctrl-n: the "sleep" pinctrl state
 - ports: contains DSI controller input and output ports as children, each
   containing one endpoint subnode.
+- qcom,mdss-dsc-enabled: Display Stream Compression (DSC) is enabled
+- qcom,mdss-slice-height: DSC slice height in pixels
+- qcom,mdss-slice-width: DSC slice width in pixels
+- qcom,mdss-slice-per-pkt: DSC slices per packet
+- qcom,mdss-bit-per-component: DSC bits per component
+- qcom,mdss-bit-per-pixel: DSC bits per pixel
+- qcom,mdss-block-prediction-enable: Block prediction mode of DSC enabled
 
   DSI Endpoint properties:
   - remote-endpoint: For port@0, set to phandle of the connected panel/bridge's
@@ -188,6 +195,14 @@ Example:
 		qcom,master-dsi;
 		qcom,sync-dual-dsi;
 
+		qcom,mdss-dsc-enabled;
+		qcom,mdss-slice-height = <16>;
+		qcom,mdss-slice-width = <540>;
+		qcom,mdss-slice-per-pkt = <1>;
+		qcom,mdss-bit-per-component = <8>;
+		qcom,mdss-bit-per-pixel = <8>;
+		qcom,mdss-block-prediction-enable;
+
 		qcom,mdss-mdp-transfer-time-us = <12000>;
 
 		pinctrl-names = "default", "sleep";
-- 
2.26.3


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

* [RFC PATCH 03/13] drm/msm/disp/dpu1: Add support for DSC
  2021-05-21 12:49 ` Vinod Koul
@ 2021-05-21 12:49   ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, David Airlie,
	Daniel Vetter, Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar,
	linux-kernel, dri-devel, freedreno

Display Stream Compression (DSC) is one of the hw blocks in dpu, so add
support by adding hw blocks for DSC

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/Makefile                  |   1 +
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |  26 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c    | 221 ++++++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h    |  79 +++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 ++
 5 files changed, 340 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 610d630326bb..fd8fc57f1f58 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -61,6 +61,7 @@ msm-y := \
 	disp/dpu1/dpu_hw_blk.o \
 	disp/dpu1/dpu_hw_catalog.o \
 	disp/dpu1/dpu_hw_ctl.o \
+	disp/dpu1/dpu_hw_dsc.o \
 	disp/dpu1/dpu_hw_interrupts.o \
 	disp/dpu1/dpu_hw_intf.o \
 	disp/dpu1/dpu_hw_lm.o \
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 4dfd8a20ad5c..a699633f7013 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -165,6 +165,7 @@ enum {
  * @DPU_PINGPONG_TE2        Additional tear check block for split pipes
  * @DPU_PINGPONG_SPLIT      PP block supports split fifo
  * @DPU_PINGPONG_SLAVE      PP block is a suitable slave for split fifo
+ * @DPU_PINGPONG_DSC        Display stream compression blocks
  * @DPU_PINGPONG_DITHER,    Dither blocks
  * @DPU_PINGPONG_MAX
  */
@@ -173,10 +174,21 @@ enum {
 	DPU_PINGPONG_TE2,
 	DPU_PINGPONG_SPLIT,
 	DPU_PINGPONG_SLAVE,
+	DPU_PINGPONG_DSC,
 	DPU_PINGPONG_DITHER,
 	DPU_PINGPONG_MAX
 };
 
+/**
+ * DSC sub-blocks
+ * @DPU_DSC		DSC sub block
+ * @DPU_DSC_MAX
+ */
+enum {
+	DPU_DSC = 0x1,
+	DPU_DSC_MAX
+};
+
 /**
  * CTL sub-blocks
  * @DPU_CTL_SPLIT_DISPLAY       CTL supports video mode split display
@@ -413,6 +425,7 @@ struct dpu_dspp_sub_blks {
 struct dpu_pingpong_sub_blks {
 	struct dpu_pp_blk te;
 	struct dpu_pp_blk te2;
+	struct dpu_pp_blk dsc;
 	struct dpu_pp_blk dither;
 };
 
@@ -547,6 +560,16 @@ struct dpu_merge_3d_cfg  {
 	const struct dpu_merge_3d_sub_blks *sblk;
 };
 
+/**
+ * struct dpu_dsc_cfg - information of DSC blocks
+ * @id                 enum identifying this block
+ * @base               register offset of this block
+ * @features           bit mask identifying sub-blocks/features
+ */
+struct dpu_dsc_cfg {
+	DPU_HW_BLK_INFO;
+};
+
 /**
  * struct dpu_intf_cfg - information of timing engine blocks
  * @id                 enum identifying this block
@@ -748,6 +771,9 @@ struct dpu_mdss_cfg {
 	u32 merge_3d_count;
 	const struct dpu_merge_3d_cfg *merge_3d;
 
+	u32 dsc_count;
+	struct dpu_dsc_cfg *dsc;
+
 	u32 intf_count;
 	const struct dpu_intf_cfg *intf;
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
new file mode 100644
index 000000000000..8b8d0553709d
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020, Linaro Limited
+ */
+
+#include "dpu_kms.h"
+#include "dpu_hw_catalog.h"
+#include "dpu_hwio.h"
+#include "dpu_hw_mdss.h"
+#include "dpu_hw_dsc.h"
+
+#define DSC_COMMON_MODE	                0x000
+#define DSC_ENC                         0X004
+#define DSC_PICTURE                     0x008
+#define DSC_SLICE                       0x00C
+#define DSC_CHUNK_SIZE                  0x010
+#define DSC_DELAY                       0x014
+#define DSC_SCALE_INITIAL               0x018
+#define DSC_SCALE_DEC_INTERVAL          0x01C
+#define DSC_SCALE_INC_INTERVAL          0x020
+#define DSC_FIRST_LINE_BPG_OFFSET       0x024
+#define DSC_BPG_OFFSET                  0x028
+#define DSC_DSC_OFFSET                  0x02C
+#define DSC_FLATNESS                    0x030
+#define DSC_RC_MODEL_SIZE               0x034
+#define DSC_RC                          0x038
+#define DSC_RC_BUF_THRESH               0x03C
+#define DSC_RANGE_MIN_QP                0x074
+#define DSC_RANGE_MAX_QP                0x0B0
+#define DSC_RANGE_BPG_OFFSET            0x0EC
+
+static void dpu_hw_dsc_disable(struct dpu_hw_dsc *dsc)
+{
+	struct dpu_hw_blk_reg_map *c = &dsc->hw;
+
+	DPU_REG_WRITE(c, DSC_COMMON_MODE, 0);
+}
+
+static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
+			      struct msm_display_dsc_config *dsc,
+			      u32 mode, bool ich_reset_override)
+{
+	struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
+	u32 data;
+	u32 initial_lines = dsc->initial_lines;
+	bool is_cmd_mode = !(mode & BIT(2));
+
+	DPU_REG_WRITE(c, DSC_COMMON_MODE, mode);
+
+	data = 0;
+	if (ich_reset_override)
+		data = 3 << 28;
+
+	if (is_cmd_mode)
+		initial_lines += 1;
+
+	data |= (initial_lines << 20);
+	data |= ((dsc->slice_last_group_size) << 18);
+	/* bpp is 6.4 format, 4 LSBs bits are for fractional part */
+	data |= dsc->drm.bits_per_pixel << 12;
+	data |= (dsc->drm.block_pred_enable << 7);
+	data |= (dsc->drm.line_buf_depth << 3);
+	data |= (dsc->drm.simple_422 << 2);
+	data |= (dsc->drm.convert_rgb << 1);
+	if (dsc->drm.bits_per_component  == 10)
+		data |= BIT(0);
+
+	DPU_REG_WRITE(c, DSC_ENC, data);
+
+	data = dsc->drm.pic_width << 16;
+	data |= dsc->drm.pic_height;
+	DPU_REG_WRITE(c, DSC_PICTURE, data);
+
+	data = dsc->drm.slice_width << 16;
+	data |= dsc->drm.slice_height;
+	DPU_REG_WRITE(c, DSC_SLICE, data);
+
+	data = DIV_ROUND_UP(dsc->drm.slice_width * dsc->drm.bits_per_pixel, 8) << 16;
+
+	DPU_REG_WRITE(c, DSC_CHUNK_SIZE, data);
+
+	data = dsc->drm.initial_dec_delay << 16;
+	data |= dsc->drm.initial_xmit_delay;
+	DPU_REG_WRITE(c, DSC_DELAY, data);
+
+	data = dsc->drm.initial_scale_value;
+	DPU_REG_WRITE(c, DSC_SCALE_INITIAL, data);
+
+	data = dsc->drm.scale_decrement_interval;
+	DPU_REG_WRITE(c, DSC_SCALE_DEC_INTERVAL, data);
+
+	data = 0x00000184; /* only this value works */
+	DPU_REG_WRITE(c, DSC_SCALE_INC_INTERVAL, data);
+
+	data = dsc->drm.first_line_bpg_offset;
+	DPU_REG_WRITE(c, DSC_FIRST_LINE_BPG_OFFSET, data);
+
+	data = dsc->drm.nfl_bpg_offset << 16;
+	data |= dsc->drm.slice_bpg_offset;
+	DPU_REG_WRITE(c, DSC_BPG_OFFSET, data);
+
+	data = dsc->drm.initial_offset << 16;
+	data |= dsc->drm.final_offset;
+	DPU_REG_WRITE(c, DSC_DSC_OFFSET, data);
+
+	data = dsc->det_thresh_flatness << 10;
+	data |= dsc->drm.flatness_max_qp << 5;
+	data |= dsc->drm.flatness_min_qp;
+	DPU_REG_WRITE(c, DSC_FLATNESS, data);
+
+	data = dsc->drm.rc_model_size;
+	DPU_REG_WRITE(c, DSC_RC_MODEL_SIZE, data);
+
+	data = dsc->drm.rc_tgt_offset_low << 18;
+	data |= dsc->drm.rc_tgt_offset_high << 14;
+	data |= dsc->drm.rc_quant_incr_limit1 << 9;
+	data |= dsc->drm.rc_quant_incr_limit0 << 4;
+	data |= dsc->drm.rc_edge_factor;
+	DPU_REG_WRITE(c, DSC_RC, data);
+}
+
+static void dpu_hw_dsc_config_thresh(struct dpu_hw_dsc *hw_dsc,
+				     struct msm_display_dsc_config *dsc)
+{
+	struct drm_dsc_rc_range_parameters *rc = dsc->drm.rc_range_params;
+	struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
+	u32 off = 0x0;
+	u16 *lp;
+	int i;
+
+	lp = dsc->drm.rc_buf_thresh;
+	off = DSC_RC_BUF_THRESH;
+	for (i = 0; i < DSC_NUM_BUF_RANGES - 1 ; i++) {
+		DPU_REG_WRITE(c, off, *lp++);
+		off += 4;
+	}
+
+	off = DSC_RANGE_MIN_QP;
+	for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
+		DPU_REG_WRITE(c, off, rc[i].range_min_qp);
+		off += 4;
+	}
+
+	off = DSC_RANGE_MAX_QP;
+	for (i = 0; i < 15; i++) {
+		DPU_REG_WRITE(c, off, rc[i].range_max_qp);
+		off += 4;
+	}
+
+	off = DSC_RANGE_BPG_OFFSET;
+	for (i = 0; i < 15; i++) {
+		DPU_REG_WRITE(c, off, rc[i].range_bpg_offset);
+		off += 4;
+	}
+}
+
+static struct dpu_dsc_cfg *_dsc_offset(enum dpu_dsc dsc,
+				       struct dpu_mdss_cfg *m,
+				       void __iomem *addr,
+				       struct dpu_hw_blk_reg_map *b)
+{
+	int i;
+
+	for (i = 0; i < m->dsc_count; i++) {
+		if (dsc == m->dsc[i].id) {
+			b->base_off = addr;
+			b->blk_off = m->dsc[i].base;
+			b->length = m->dsc[i].len;
+			b->hwversion = m->hwversion;
+			b->log_mask = DPU_DBG_MASK_DSC;
+			return &m->dsc[i];
+		}
+	}
+
+	return NULL;
+}
+
+static void _setup_dsc_ops(struct dpu_hw_dsc_ops *ops,
+			   unsigned long cap)
+{
+	ops->dsc_disable = dpu_hw_dsc_disable;
+	ops->dsc_config = dpu_hw_dsc_config;
+	ops->dsc_config_thresh = dpu_hw_dsc_config_thresh;
+};
+
+static struct dpu_hw_blk_ops dpu_hw_ops = {
+	.start = NULL,
+	.stop = NULL,
+};
+
+struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr,
+				   struct dpu_mdss_cfg *m)
+{
+	struct dpu_hw_dsc *c;
+	struct dpu_dsc_cfg *cfg;
+
+	c = kzalloc(sizeof(*c), GFP_KERNEL);
+	if (!c)
+		return ERR_PTR(-ENOMEM);
+
+	cfg = _dsc_offset(idx, m, addr, &c->hw);
+	if (IS_ERR_OR_NULL(cfg)) {
+		kfree(c);
+		return ERR_PTR(-EINVAL);
+	}
+
+	c->idx = idx;
+	c->caps = cfg;
+	_setup_dsc_ops(&c->ops, c->caps->features);
+
+	dpu_hw_blk_init(&c->base, DPU_HW_BLK_DSC, idx, &dpu_hw_ops);
+
+	return c;
+}
+
+void dpu_hw_dsc_destroy(struct dpu_hw_dsc *dsc)
+{
+	if (dsc)
+		dpu_hw_blk_destroy(&dsc->base);
+	kfree(dsc);
+}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
new file mode 100644
index 000000000000..c680fd948865
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2020, Linaro Limited */
+
+#ifndef _DPU_HW_DSC_H
+#define _DPU_HW_DSC_H
+
+#include <drm/drm_dsc.h>
+
+#define DSC_MODE_SPLIT_PANEL            BIT(0)
+#define DSC_MODE_MULTIPLEX              BIT(1)
+#define DSC_MODE_VIDEO                  BIT(2)
+
+struct dpu_hw_dsc;
+
+/**
+ * struct dpu_hw_dsc_ops - interface to the dsc hardware driver functions
+ * Assumption is these functions will be called after clocks are enabled
+ */
+struct dpu_hw_dsc_ops {
+	/**
+	 * dsc_disable - disable dsc
+	 * @hw_dsc: Pointer to dsc context
+	 */
+	void (*dsc_disable)(struct dpu_hw_dsc *hw_dsc);
+
+	/**
+	 * dsc_config - configures dsc encoder
+	 * @hw_dsc: Pointer to dsc context
+	 * @dsc: panel dsc parameters
+	 * @mode: dsc topology mode to be set
+	 * @ich_reset_override: option to reset ich
+	 */
+	void (*dsc_config)(struct dpu_hw_dsc *hw_dsc,
+			   struct msm_display_dsc_config *dsc,
+			   u32 mode, bool ich_reset_override);
+
+	/**
+	 * dsc_config_thresh - programs panel thresholds
+	 * @hw_dsc: Pointer to dsc context
+	 * @dsc: panel dsc parameters
+	 */
+	void (*dsc_config_thresh)(struct dpu_hw_dsc *hw_dsc,
+				  struct msm_display_dsc_config *dsc);
+};
+
+struct dpu_hw_dsc {
+	struct dpu_hw_blk base;
+	struct dpu_hw_blk_reg_map hw;
+
+	/* dsc */
+	enum dpu_dsc idx;
+	const struct dpu_dsc_cfg *caps;
+
+	/* ops */
+	struct dpu_hw_dsc_ops ops;
+};
+
+/**
+ * dpu_hw_dsc_init - initializes the dsc block for the passed dsc idx.
+ * @idx:  DSC index for which driver object is required
+ * @addr: Mapped register io address of MDP
+ * @m:    Pointer to mdss catalog data
+ * Returns: Error code or allocated dpu_hw_dsc context
+ */
+struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr,
+				   struct dpu_mdss_cfg *m);
+
+/**
+ * dpu_hw_dsc_destroy - destroys dsc driver context
+ * @dsc:   Pointer to dsc driver context returned by dpu_hw_dsc_init
+ */
+void dpu_hw_dsc_destroy(struct dpu_hw_dsc *dsc);
+
+static inline struct dpu_hw_dsc *to_dpu_hw_dsc(struct dpu_hw_blk *hw)
+{
+	return container_of(hw, struct dpu_hw_dsc, base);
+}
+
+#endif /* _DPU_HW_DSC_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 09a3fb3e89f5..1b72c11090ee 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -97,6 +97,7 @@ enum dpu_hw_blk_type {
 	DPU_HW_BLK_WB,
 	DPU_HW_BLK_DSPP,
 	DPU_HW_BLK_MERGE_3D,
+	DPU_HW_BLK_DSC,
 	DPU_HW_BLK_MAX,
 };
 
@@ -176,6 +177,17 @@ enum dpu_ctl {
 	CTL_MAX
 };
 
+enum dpu_dsc {
+	DSC_NONE = 0,
+	DSC_0,
+	DSC_1,
+	DSC_2,
+	DSC_3,
+	DSC_4,
+	DSC_5,
+	DSC_MAX
+};
+
 enum dpu_pingpong {
 	PINGPONG_0 = 1,
 	PINGPONG_1,
@@ -437,5 +449,6 @@ struct dpu_mdss_color {
 #define DPU_DBG_MASK_VBIF     (1 << 8)
 #define DPU_DBG_MASK_ROT      (1 << 9)
 #define DPU_DBG_MASK_DSPP     (1 << 10)
+#define DPU_DBG_MASK_DSC      (1 << 11)
 
 #endif  /* _DPU_HW_MDSS_H */
-- 
2.26.3


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

* [RFC PATCH 03/13] drm/msm/disp/dpu1: Add support for DSC
@ 2021-05-21 12:49   ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, Vinod Koul, dri-devel,
	Dmitry Baryshkov, freedreno

Display Stream Compression (DSC) is one of the hw blocks in dpu, so add
support by adding hw blocks for DSC

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/Makefile                  |   1 +
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |  26 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c    | 221 ++++++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h    |  79 +++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 ++
 5 files changed, 340 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 610d630326bb..fd8fc57f1f58 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -61,6 +61,7 @@ msm-y := \
 	disp/dpu1/dpu_hw_blk.o \
 	disp/dpu1/dpu_hw_catalog.o \
 	disp/dpu1/dpu_hw_ctl.o \
+	disp/dpu1/dpu_hw_dsc.o \
 	disp/dpu1/dpu_hw_interrupts.o \
 	disp/dpu1/dpu_hw_intf.o \
 	disp/dpu1/dpu_hw_lm.o \
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 4dfd8a20ad5c..a699633f7013 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -165,6 +165,7 @@ enum {
  * @DPU_PINGPONG_TE2        Additional tear check block for split pipes
  * @DPU_PINGPONG_SPLIT      PP block supports split fifo
  * @DPU_PINGPONG_SLAVE      PP block is a suitable slave for split fifo
+ * @DPU_PINGPONG_DSC        Display stream compression blocks
  * @DPU_PINGPONG_DITHER,    Dither blocks
  * @DPU_PINGPONG_MAX
  */
@@ -173,10 +174,21 @@ enum {
 	DPU_PINGPONG_TE2,
 	DPU_PINGPONG_SPLIT,
 	DPU_PINGPONG_SLAVE,
+	DPU_PINGPONG_DSC,
 	DPU_PINGPONG_DITHER,
 	DPU_PINGPONG_MAX
 };
 
+/**
+ * DSC sub-blocks
+ * @DPU_DSC		DSC sub block
+ * @DPU_DSC_MAX
+ */
+enum {
+	DPU_DSC = 0x1,
+	DPU_DSC_MAX
+};
+
 /**
  * CTL sub-blocks
  * @DPU_CTL_SPLIT_DISPLAY       CTL supports video mode split display
@@ -413,6 +425,7 @@ struct dpu_dspp_sub_blks {
 struct dpu_pingpong_sub_blks {
 	struct dpu_pp_blk te;
 	struct dpu_pp_blk te2;
+	struct dpu_pp_blk dsc;
 	struct dpu_pp_blk dither;
 };
 
@@ -547,6 +560,16 @@ struct dpu_merge_3d_cfg  {
 	const struct dpu_merge_3d_sub_blks *sblk;
 };
 
+/**
+ * struct dpu_dsc_cfg - information of DSC blocks
+ * @id                 enum identifying this block
+ * @base               register offset of this block
+ * @features           bit mask identifying sub-blocks/features
+ */
+struct dpu_dsc_cfg {
+	DPU_HW_BLK_INFO;
+};
+
 /**
  * struct dpu_intf_cfg - information of timing engine blocks
  * @id                 enum identifying this block
@@ -748,6 +771,9 @@ struct dpu_mdss_cfg {
 	u32 merge_3d_count;
 	const struct dpu_merge_3d_cfg *merge_3d;
 
+	u32 dsc_count;
+	struct dpu_dsc_cfg *dsc;
+
 	u32 intf_count;
 	const struct dpu_intf_cfg *intf;
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
new file mode 100644
index 000000000000..8b8d0553709d
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020, Linaro Limited
+ */
+
+#include "dpu_kms.h"
+#include "dpu_hw_catalog.h"
+#include "dpu_hwio.h"
+#include "dpu_hw_mdss.h"
+#include "dpu_hw_dsc.h"
+
+#define DSC_COMMON_MODE	                0x000
+#define DSC_ENC                         0X004
+#define DSC_PICTURE                     0x008
+#define DSC_SLICE                       0x00C
+#define DSC_CHUNK_SIZE                  0x010
+#define DSC_DELAY                       0x014
+#define DSC_SCALE_INITIAL               0x018
+#define DSC_SCALE_DEC_INTERVAL          0x01C
+#define DSC_SCALE_INC_INTERVAL          0x020
+#define DSC_FIRST_LINE_BPG_OFFSET       0x024
+#define DSC_BPG_OFFSET                  0x028
+#define DSC_DSC_OFFSET                  0x02C
+#define DSC_FLATNESS                    0x030
+#define DSC_RC_MODEL_SIZE               0x034
+#define DSC_RC                          0x038
+#define DSC_RC_BUF_THRESH               0x03C
+#define DSC_RANGE_MIN_QP                0x074
+#define DSC_RANGE_MAX_QP                0x0B0
+#define DSC_RANGE_BPG_OFFSET            0x0EC
+
+static void dpu_hw_dsc_disable(struct dpu_hw_dsc *dsc)
+{
+	struct dpu_hw_blk_reg_map *c = &dsc->hw;
+
+	DPU_REG_WRITE(c, DSC_COMMON_MODE, 0);
+}
+
+static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
+			      struct msm_display_dsc_config *dsc,
+			      u32 mode, bool ich_reset_override)
+{
+	struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
+	u32 data;
+	u32 initial_lines = dsc->initial_lines;
+	bool is_cmd_mode = !(mode & BIT(2));
+
+	DPU_REG_WRITE(c, DSC_COMMON_MODE, mode);
+
+	data = 0;
+	if (ich_reset_override)
+		data = 3 << 28;
+
+	if (is_cmd_mode)
+		initial_lines += 1;
+
+	data |= (initial_lines << 20);
+	data |= ((dsc->slice_last_group_size) << 18);
+	/* bpp is 6.4 format, 4 LSBs bits are for fractional part */
+	data |= dsc->drm.bits_per_pixel << 12;
+	data |= (dsc->drm.block_pred_enable << 7);
+	data |= (dsc->drm.line_buf_depth << 3);
+	data |= (dsc->drm.simple_422 << 2);
+	data |= (dsc->drm.convert_rgb << 1);
+	if (dsc->drm.bits_per_component  == 10)
+		data |= BIT(0);
+
+	DPU_REG_WRITE(c, DSC_ENC, data);
+
+	data = dsc->drm.pic_width << 16;
+	data |= dsc->drm.pic_height;
+	DPU_REG_WRITE(c, DSC_PICTURE, data);
+
+	data = dsc->drm.slice_width << 16;
+	data |= dsc->drm.slice_height;
+	DPU_REG_WRITE(c, DSC_SLICE, data);
+
+	data = DIV_ROUND_UP(dsc->drm.slice_width * dsc->drm.bits_per_pixel, 8) << 16;
+
+	DPU_REG_WRITE(c, DSC_CHUNK_SIZE, data);
+
+	data = dsc->drm.initial_dec_delay << 16;
+	data |= dsc->drm.initial_xmit_delay;
+	DPU_REG_WRITE(c, DSC_DELAY, data);
+
+	data = dsc->drm.initial_scale_value;
+	DPU_REG_WRITE(c, DSC_SCALE_INITIAL, data);
+
+	data = dsc->drm.scale_decrement_interval;
+	DPU_REG_WRITE(c, DSC_SCALE_DEC_INTERVAL, data);
+
+	data = 0x00000184; /* only this value works */
+	DPU_REG_WRITE(c, DSC_SCALE_INC_INTERVAL, data);
+
+	data = dsc->drm.first_line_bpg_offset;
+	DPU_REG_WRITE(c, DSC_FIRST_LINE_BPG_OFFSET, data);
+
+	data = dsc->drm.nfl_bpg_offset << 16;
+	data |= dsc->drm.slice_bpg_offset;
+	DPU_REG_WRITE(c, DSC_BPG_OFFSET, data);
+
+	data = dsc->drm.initial_offset << 16;
+	data |= dsc->drm.final_offset;
+	DPU_REG_WRITE(c, DSC_DSC_OFFSET, data);
+
+	data = dsc->det_thresh_flatness << 10;
+	data |= dsc->drm.flatness_max_qp << 5;
+	data |= dsc->drm.flatness_min_qp;
+	DPU_REG_WRITE(c, DSC_FLATNESS, data);
+
+	data = dsc->drm.rc_model_size;
+	DPU_REG_WRITE(c, DSC_RC_MODEL_SIZE, data);
+
+	data = dsc->drm.rc_tgt_offset_low << 18;
+	data |= dsc->drm.rc_tgt_offset_high << 14;
+	data |= dsc->drm.rc_quant_incr_limit1 << 9;
+	data |= dsc->drm.rc_quant_incr_limit0 << 4;
+	data |= dsc->drm.rc_edge_factor;
+	DPU_REG_WRITE(c, DSC_RC, data);
+}
+
+static void dpu_hw_dsc_config_thresh(struct dpu_hw_dsc *hw_dsc,
+				     struct msm_display_dsc_config *dsc)
+{
+	struct drm_dsc_rc_range_parameters *rc = dsc->drm.rc_range_params;
+	struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
+	u32 off = 0x0;
+	u16 *lp;
+	int i;
+
+	lp = dsc->drm.rc_buf_thresh;
+	off = DSC_RC_BUF_THRESH;
+	for (i = 0; i < DSC_NUM_BUF_RANGES - 1 ; i++) {
+		DPU_REG_WRITE(c, off, *lp++);
+		off += 4;
+	}
+
+	off = DSC_RANGE_MIN_QP;
+	for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
+		DPU_REG_WRITE(c, off, rc[i].range_min_qp);
+		off += 4;
+	}
+
+	off = DSC_RANGE_MAX_QP;
+	for (i = 0; i < 15; i++) {
+		DPU_REG_WRITE(c, off, rc[i].range_max_qp);
+		off += 4;
+	}
+
+	off = DSC_RANGE_BPG_OFFSET;
+	for (i = 0; i < 15; i++) {
+		DPU_REG_WRITE(c, off, rc[i].range_bpg_offset);
+		off += 4;
+	}
+}
+
+static struct dpu_dsc_cfg *_dsc_offset(enum dpu_dsc dsc,
+				       struct dpu_mdss_cfg *m,
+				       void __iomem *addr,
+				       struct dpu_hw_blk_reg_map *b)
+{
+	int i;
+
+	for (i = 0; i < m->dsc_count; i++) {
+		if (dsc == m->dsc[i].id) {
+			b->base_off = addr;
+			b->blk_off = m->dsc[i].base;
+			b->length = m->dsc[i].len;
+			b->hwversion = m->hwversion;
+			b->log_mask = DPU_DBG_MASK_DSC;
+			return &m->dsc[i];
+		}
+	}
+
+	return NULL;
+}
+
+static void _setup_dsc_ops(struct dpu_hw_dsc_ops *ops,
+			   unsigned long cap)
+{
+	ops->dsc_disable = dpu_hw_dsc_disable;
+	ops->dsc_config = dpu_hw_dsc_config;
+	ops->dsc_config_thresh = dpu_hw_dsc_config_thresh;
+};
+
+static struct dpu_hw_blk_ops dpu_hw_ops = {
+	.start = NULL,
+	.stop = NULL,
+};
+
+struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr,
+				   struct dpu_mdss_cfg *m)
+{
+	struct dpu_hw_dsc *c;
+	struct dpu_dsc_cfg *cfg;
+
+	c = kzalloc(sizeof(*c), GFP_KERNEL);
+	if (!c)
+		return ERR_PTR(-ENOMEM);
+
+	cfg = _dsc_offset(idx, m, addr, &c->hw);
+	if (IS_ERR_OR_NULL(cfg)) {
+		kfree(c);
+		return ERR_PTR(-EINVAL);
+	}
+
+	c->idx = idx;
+	c->caps = cfg;
+	_setup_dsc_ops(&c->ops, c->caps->features);
+
+	dpu_hw_blk_init(&c->base, DPU_HW_BLK_DSC, idx, &dpu_hw_ops);
+
+	return c;
+}
+
+void dpu_hw_dsc_destroy(struct dpu_hw_dsc *dsc)
+{
+	if (dsc)
+		dpu_hw_blk_destroy(&dsc->base);
+	kfree(dsc);
+}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
new file mode 100644
index 000000000000..c680fd948865
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2020, Linaro Limited */
+
+#ifndef _DPU_HW_DSC_H
+#define _DPU_HW_DSC_H
+
+#include <drm/drm_dsc.h>
+
+#define DSC_MODE_SPLIT_PANEL            BIT(0)
+#define DSC_MODE_MULTIPLEX              BIT(1)
+#define DSC_MODE_VIDEO                  BIT(2)
+
+struct dpu_hw_dsc;
+
+/**
+ * struct dpu_hw_dsc_ops - interface to the dsc hardware driver functions
+ * Assumption is these functions will be called after clocks are enabled
+ */
+struct dpu_hw_dsc_ops {
+	/**
+	 * dsc_disable - disable dsc
+	 * @hw_dsc: Pointer to dsc context
+	 */
+	void (*dsc_disable)(struct dpu_hw_dsc *hw_dsc);
+
+	/**
+	 * dsc_config - configures dsc encoder
+	 * @hw_dsc: Pointer to dsc context
+	 * @dsc: panel dsc parameters
+	 * @mode: dsc topology mode to be set
+	 * @ich_reset_override: option to reset ich
+	 */
+	void (*dsc_config)(struct dpu_hw_dsc *hw_dsc,
+			   struct msm_display_dsc_config *dsc,
+			   u32 mode, bool ich_reset_override);
+
+	/**
+	 * dsc_config_thresh - programs panel thresholds
+	 * @hw_dsc: Pointer to dsc context
+	 * @dsc: panel dsc parameters
+	 */
+	void (*dsc_config_thresh)(struct dpu_hw_dsc *hw_dsc,
+				  struct msm_display_dsc_config *dsc);
+};
+
+struct dpu_hw_dsc {
+	struct dpu_hw_blk base;
+	struct dpu_hw_blk_reg_map hw;
+
+	/* dsc */
+	enum dpu_dsc idx;
+	const struct dpu_dsc_cfg *caps;
+
+	/* ops */
+	struct dpu_hw_dsc_ops ops;
+};
+
+/**
+ * dpu_hw_dsc_init - initializes the dsc block for the passed dsc idx.
+ * @idx:  DSC index for which driver object is required
+ * @addr: Mapped register io address of MDP
+ * @m:    Pointer to mdss catalog data
+ * Returns: Error code or allocated dpu_hw_dsc context
+ */
+struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr,
+				   struct dpu_mdss_cfg *m);
+
+/**
+ * dpu_hw_dsc_destroy - destroys dsc driver context
+ * @dsc:   Pointer to dsc driver context returned by dpu_hw_dsc_init
+ */
+void dpu_hw_dsc_destroy(struct dpu_hw_dsc *dsc);
+
+static inline struct dpu_hw_dsc *to_dpu_hw_dsc(struct dpu_hw_blk *hw)
+{
+	return container_of(hw, struct dpu_hw_dsc, base);
+}
+
+#endif /* _DPU_HW_DSC_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 09a3fb3e89f5..1b72c11090ee 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -97,6 +97,7 @@ enum dpu_hw_blk_type {
 	DPU_HW_BLK_WB,
 	DPU_HW_BLK_DSPP,
 	DPU_HW_BLK_MERGE_3D,
+	DPU_HW_BLK_DSC,
 	DPU_HW_BLK_MAX,
 };
 
@@ -176,6 +177,17 @@ enum dpu_ctl {
 	CTL_MAX
 };
 
+enum dpu_dsc {
+	DSC_NONE = 0,
+	DSC_0,
+	DSC_1,
+	DSC_2,
+	DSC_3,
+	DSC_4,
+	DSC_5,
+	DSC_MAX
+};
+
 enum dpu_pingpong {
 	PINGPONG_0 = 1,
 	PINGPONG_1,
@@ -437,5 +449,6 @@ struct dpu_mdss_color {
 #define DPU_DBG_MASK_VBIF     (1 << 8)
 #define DPU_DBG_MASK_ROT      (1 << 9)
 #define DPU_DBG_MASK_DSPP     (1 << 10)
+#define DPU_DBG_MASK_DSC      (1 << 11)
 
 #endif  /* _DPU_HW_MDSS_H */
-- 
2.26.3


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

* [RFC PATCH 03/13] drm/msm/dsi: add support for dsc data
  2021-05-21 12:49 ` Vinod Koul
@ 2021-05-21 12:49   ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, David Airlie,
	Daniel Vetter, Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar,
	linux-kernel, dri-devel, freedreno

DSC needs some configuration from device tree, add support to read and
store these params and add DSC structures in msm_drv

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 170 +++++++++++++++++++++++++++++
 drivers/gpu/drm/msm/msm_drv.h      |  32 ++++++
 2 files changed, 202 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 8a10e4343281..864d3c655e73 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -156,6 +156,7 @@ struct msm_dsi_host {
 	struct regmap *sfpb;
 
 	struct drm_display_mode *mode;
+	struct msm_display_dsc_config *dsc;
 
 	/* connected device info */
 	struct device_node *device_node;
@@ -1744,6 +1745,168 @@ static int dsi_host_parse_lane_data(struct msm_dsi_host *msm_host,
 	return -EINVAL;
 }
 
+static u32 dsi_dsc_rc_buf_thresh[DSC_NUM_BUF_RANGES - 1] = {
+	0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, 0x62,
+	0x69, 0x70, 0x77, 0x79, 0x7b, 0x7d, 0x7e
+};
+
+/* only 8bpc, 8bpp added */
+static char min_qp[DSC_NUM_BUF_RANGES] = {
+	0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 13
+};
+
+static char max_qp[DSC_NUM_BUF_RANGES] = {
+	4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 11, 12, 13, 13, 15
+};
+
+static char bpg_offset[DSC_NUM_BUF_RANGES] = {
+	2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12
+};
+
+static int dsi_populate_dsc_params(struct msm_display_dsc_config *dsc)
+{
+	int i;
+
+	dsc->drm.rc_model_size = 8192;
+	dsc->drm.first_line_bpg_offset = 15;
+	dsc->drm.rc_edge_factor = 6;
+	dsc->drm.rc_tgt_offset_high = 3;
+	dsc->drm.rc_tgt_offset_low = 3;
+	dsc->drm.simple_422 = 0;
+	dsc->drm.convert_rgb = 1;
+	dsc->drm.vbr_enable = 0;
+
+	/* handle only bpp = bpc = 8 */
+	for (i = 0; i < DSC_NUM_BUF_RANGES - 1 ; i++)
+		dsc->drm.rc_buf_thresh[i] = dsi_dsc_rc_buf_thresh[i];
+
+	for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
+		dsc->drm.rc_range_params[i].range_min_qp = min_qp[i];
+		dsc->drm.rc_range_params[i].range_max_qp = max_qp[i];
+		dsc->drm.rc_range_params[i].range_bpg_offset = bpg_offset[i];
+	}
+
+	dsc->drm.initial_offset = 6144;
+	dsc->drm.initial_xmit_delay = 512;
+	dsc->drm.initial_scale_value = 32;
+	dsc->drm.first_line_bpg_offset = 12;
+	dsc->drm.line_buf_depth = dsc->drm.bits_per_component + 1;
+
+	/* bpc 8 */
+	dsc->drm.flatness_min_qp = 3;
+	dsc->drm.flatness_max_qp = 12;
+	dsc->det_thresh_flatness = 7;
+	dsc->drm.rc_quant_incr_limit0 = 11;
+	dsc->drm.rc_quant_incr_limit1 = 11;
+	dsc->drm.mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC;
+
+	/* FIXME: need to call drm_dsc_compute_rc_parameters() so that rest of
+	 * params are calculated
+	 */
+
+	i = dsc->drm.slice_width % 3;
+	switch (i) {
+	case 0:
+		dsc->slice_last_group_size = 2;
+		break;
+
+	case 1:
+		dsc->slice_last_group_size = 0;
+		break;
+
+	case 2:
+		dsc->slice_last_group_size = 0;
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int dsi_host_parse_dsc(struct msm_dsi_host *msm_host,
+			      struct device_node *np)
+{
+	struct device *dev = &msm_host->pdev->dev;
+	struct msm_display_dsc_config *dsc;
+	bool is_dsc_enabled;
+	u32 data;
+	int ret;
+
+	is_dsc_enabled = of_property_read_bool(np, "qcom,mdss-dsc-enabled");
+
+	if (!is_dsc_enabled)
+		return 0;
+
+	dsc = kzalloc(sizeof(*dsc), GFP_KERNEL);
+	if (!dsc)
+		return -ENOMEM;
+
+	ret = of_property_read_u32(np, "qcom,mdss-dsc-version", &data);
+	if (ret) {
+		dsc->drm.dsc_version_major = 0x1;
+		dsc->drm.dsc_version_minor = 0x1;
+	} else {
+		dsc->drm.dsc_version_major = (data >> 4) & 0xf;
+		dsc->drm.dsc_version_minor = data & 0xf;
+	}
+
+	ret = of_property_read_u32(np, "qcom,mdss-scr-version", &data);
+	if (ret)
+		dsc->scr_rev = 0;
+	else
+		dsc->scr_rev = data & 0xff;
+
+	ret = of_property_read_u32(np, "qcom,mdss-slice-height", &data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to read dsc slice height\n");
+		goto err;
+	}
+	dsc->drm.slice_height = data;
+
+	ret = of_property_read_u32(np, "qcom,mdss-slice-width", &data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to read dsc slice width\n");
+		goto err;
+	}
+	dsc->drm.slice_width = data;
+
+	ret = of_property_read_u32(np, "qcom,mdss-slice-per-pkt", &data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to read mdss-slice-per-pkt\n");
+		goto err;
+	}
+	dsc->slice_per_pkt = data;
+
+	ret = of_property_read_u32(np, "qcom,mdss-bit-per-component", &data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to read mdss-bit-per-component\n");
+		goto err;
+	}
+	dsc->drm.bits_per_component = data;
+
+	ret = of_property_read_u32(np, "qcom,mdss-bit-per-pixel", &data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to read bit-per-pixel\n");
+		goto err;
+	}
+	dsc->drm.bits_per_pixel = data;
+
+	dsc->drm.block_pred_enable = of_property_read_bool(np,
+			 "qcom,mdss-block-prediction-enable");
+
+	dsi_populate_dsc_params(dsc);
+
+	msm_host->dsc = dsc;
+
+	return 0;
+
+err:
+	kfree(dsc);
+	return ret;
+}
+
 static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 {
 	struct device *dev = &msm_host->pdev->dev;
@@ -1763,6 +1926,13 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 		return 0;
 	}
 
+	ret = dsi_host_parse_dsc(msm_host, np);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "%s: invalid dsc configuration %d\n", __func__, ret);
+		ret = -EINVAL;
+		goto err;
+	}
+
 	ret = dsi_host_parse_lane_data(msm_host, endpoint);
 	if (ret) {
 		DRM_DEV_ERROR(dev, "%s: invalid lane configuration %d\n",
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 2668941df529..26661dd43936 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -30,6 +30,7 @@
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_dsc.h>
 #include <drm/msm_drm.h>
 #include <drm/drm_gem.h>
 
@@ -70,6 +71,16 @@ enum msm_mdp_plane_property {
 #define MSM_GPU_MAX_RINGS 4
 #define MAX_H_TILES_PER_DISPLAY 2
 
+/**
+ * enum msm_display_compression_type - compression method used for pixel stream
+ * @MSM_DISPLAY_COMPRESSION_NONE:	Pixel data is not compressed
+ * @MSM_DISPLAY_COMPRESSION_DSC:	DSC compresison is used
+ */
+enum msm_display_compression_type {
+	MSM_DISPLAY_COMPRESSION_NONE,
+	MSM_DISPLAY_COMPRESSION_DSC,
+};
+
 /**
  * enum msm_display_caps - features/capabilities supported by displays
  * @MSM_DISPLAY_CAP_VID_MODE:           Video or "active" mode supported
@@ -134,6 +145,24 @@ struct msm_drm_thread {
 	struct kthread_worker *worker;
 };
 
+/* DSC config */
+struct msm_display_dsc_config {
+	struct drm_dsc_config drm;
+	u8 scr_rev;
+
+	u32 initial_lines;
+	u32 pkt_per_line;
+	u32 bytes_in_slice;
+	u32 bytes_per_pkt;
+	u32 eol_byte_num;
+	u32 pclk_per_line;
+	u32 slice_last_group_size;
+	u32 slice_per_pkt;
+	u32 det_thresh_flatness;
+	u32 extra_width;
+	u32 pps_delay_ms;
+};
+
 struct msm_drm_private {
 
 	struct drm_device *dev;
@@ -227,6 +256,9 @@ struct msm_drm_private {
 	/* Properties */
 	struct drm_property *plane_property[PLANE_PROP_MAX_NUM];
 
+	/* DSC configuration */
+	struct msm_display_dsc_config *dsc;
+
 	/* VRAM carveout, used when no IOMMU: */
 	struct {
 		unsigned long size;
-- 
2.26.3


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

* [RFC PATCH 03/13] drm/msm/dsi: add support for dsc data
@ 2021-05-21 12:49   ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, Vinod Koul, dri-devel,
	Dmitry Baryshkov, freedreno

DSC needs some configuration from device tree, add support to read and
store these params and add DSC structures in msm_drv

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 170 +++++++++++++++++++++++++++++
 drivers/gpu/drm/msm/msm_drv.h      |  32 ++++++
 2 files changed, 202 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 8a10e4343281..864d3c655e73 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -156,6 +156,7 @@ struct msm_dsi_host {
 	struct regmap *sfpb;
 
 	struct drm_display_mode *mode;
+	struct msm_display_dsc_config *dsc;
 
 	/* connected device info */
 	struct device_node *device_node;
@@ -1744,6 +1745,168 @@ static int dsi_host_parse_lane_data(struct msm_dsi_host *msm_host,
 	return -EINVAL;
 }
 
+static u32 dsi_dsc_rc_buf_thresh[DSC_NUM_BUF_RANGES - 1] = {
+	0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, 0x62,
+	0x69, 0x70, 0x77, 0x79, 0x7b, 0x7d, 0x7e
+};
+
+/* only 8bpc, 8bpp added */
+static char min_qp[DSC_NUM_BUF_RANGES] = {
+	0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 13
+};
+
+static char max_qp[DSC_NUM_BUF_RANGES] = {
+	4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 11, 12, 13, 13, 15
+};
+
+static char bpg_offset[DSC_NUM_BUF_RANGES] = {
+	2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12
+};
+
+static int dsi_populate_dsc_params(struct msm_display_dsc_config *dsc)
+{
+	int i;
+
+	dsc->drm.rc_model_size = 8192;
+	dsc->drm.first_line_bpg_offset = 15;
+	dsc->drm.rc_edge_factor = 6;
+	dsc->drm.rc_tgt_offset_high = 3;
+	dsc->drm.rc_tgt_offset_low = 3;
+	dsc->drm.simple_422 = 0;
+	dsc->drm.convert_rgb = 1;
+	dsc->drm.vbr_enable = 0;
+
+	/* handle only bpp = bpc = 8 */
+	for (i = 0; i < DSC_NUM_BUF_RANGES - 1 ; i++)
+		dsc->drm.rc_buf_thresh[i] = dsi_dsc_rc_buf_thresh[i];
+
+	for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
+		dsc->drm.rc_range_params[i].range_min_qp = min_qp[i];
+		dsc->drm.rc_range_params[i].range_max_qp = max_qp[i];
+		dsc->drm.rc_range_params[i].range_bpg_offset = bpg_offset[i];
+	}
+
+	dsc->drm.initial_offset = 6144;
+	dsc->drm.initial_xmit_delay = 512;
+	dsc->drm.initial_scale_value = 32;
+	dsc->drm.first_line_bpg_offset = 12;
+	dsc->drm.line_buf_depth = dsc->drm.bits_per_component + 1;
+
+	/* bpc 8 */
+	dsc->drm.flatness_min_qp = 3;
+	dsc->drm.flatness_max_qp = 12;
+	dsc->det_thresh_flatness = 7;
+	dsc->drm.rc_quant_incr_limit0 = 11;
+	dsc->drm.rc_quant_incr_limit1 = 11;
+	dsc->drm.mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC;
+
+	/* FIXME: need to call drm_dsc_compute_rc_parameters() so that rest of
+	 * params are calculated
+	 */
+
+	i = dsc->drm.slice_width % 3;
+	switch (i) {
+	case 0:
+		dsc->slice_last_group_size = 2;
+		break;
+
+	case 1:
+		dsc->slice_last_group_size = 0;
+		break;
+
+	case 2:
+		dsc->slice_last_group_size = 0;
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int dsi_host_parse_dsc(struct msm_dsi_host *msm_host,
+			      struct device_node *np)
+{
+	struct device *dev = &msm_host->pdev->dev;
+	struct msm_display_dsc_config *dsc;
+	bool is_dsc_enabled;
+	u32 data;
+	int ret;
+
+	is_dsc_enabled = of_property_read_bool(np, "qcom,mdss-dsc-enabled");
+
+	if (!is_dsc_enabled)
+		return 0;
+
+	dsc = kzalloc(sizeof(*dsc), GFP_KERNEL);
+	if (!dsc)
+		return -ENOMEM;
+
+	ret = of_property_read_u32(np, "qcom,mdss-dsc-version", &data);
+	if (ret) {
+		dsc->drm.dsc_version_major = 0x1;
+		dsc->drm.dsc_version_minor = 0x1;
+	} else {
+		dsc->drm.dsc_version_major = (data >> 4) & 0xf;
+		dsc->drm.dsc_version_minor = data & 0xf;
+	}
+
+	ret = of_property_read_u32(np, "qcom,mdss-scr-version", &data);
+	if (ret)
+		dsc->scr_rev = 0;
+	else
+		dsc->scr_rev = data & 0xff;
+
+	ret = of_property_read_u32(np, "qcom,mdss-slice-height", &data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to read dsc slice height\n");
+		goto err;
+	}
+	dsc->drm.slice_height = data;
+
+	ret = of_property_read_u32(np, "qcom,mdss-slice-width", &data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to read dsc slice width\n");
+		goto err;
+	}
+	dsc->drm.slice_width = data;
+
+	ret = of_property_read_u32(np, "qcom,mdss-slice-per-pkt", &data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to read mdss-slice-per-pkt\n");
+		goto err;
+	}
+	dsc->slice_per_pkt = data;
+
+	ret = of_property_read_u32(np, "qcom,mdss-bit-per-component", &data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to read mdss-bit-per-component\n");
+		goto err;
+	}
+	dsc->drm.bits_per_component = data;
+
+	ret = of_property_read_u32(np, "qcom,mdss-bit-per-pixel", &data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to read bit-per-pixel\n");
+		goto err;
+	}
+	dsc->drm.bits_per_pixel = data;
+
+	dsc->drm.block_pred_enable = of_property_read_bool(np,
+			 "qcom,mdss-block-prediction-enable");
+
+	dsi_populate_dsc_params(dsc);
+
+	msm_host->dsc = dsc;
+
+	return 0;
+
+err:
+	kfree(dsc);
+	return ret;
+}
+
 static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 {
 	struct device *dev = &msm_host->pdev->dev;
@@ -1763,6 +1926,13 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 		return 0;
 	}
 
+	ret = dsi_host_parse_dsc(msm_host, np);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "%s: invalid dsc configuration %d\n", __func__, ret);
+		ret = -EINVAL;
+		goto err;
+	}
+
 	ret = dsi_host_parse_lane_data(msm_host, endpoint);
 	if (ret) {
 		DRM_DEV_ERROR(dev, "%s: invalid lane configuration %d\n",
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 2668941df529..26661dd43936 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -30,6 +30,7 @@
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_dsc.h>
 #include <drm/msm_drm.h>
 #include <drm/drm_gem.h>
 
@@ -70,6 +71,16 @@ enum msm_mdp_plane_property {
 #define MSM_GPU_MAX_RINGS 4
 #define MAX_H_TILES_PER_DISPLAY 2
 
+/**
+ * enum msm_display_compression_type - compression method used for pixel stream
+ * @MSM_DISPLAY_COMPRESSION_NONE:	Pixel data is not compressed
+ * @MSM_DISPLAY_COMPRESSION_DSC:	DSC compresison is used
+ */
+enum msm_display_compression_type {
+	MSM_DISPLAY_COMPRESSION_NONE,
+	MSM_DISPLAY_COMPRESSION_DSC,
+};
+
 /**
  * enum msm_display_caps - features/capabilities supported by displays
  * @MSM_DISPLAY_CAP_VID_MODE:           Video or "active" mode supported
@@ -134,6 +145,24 @@ struct msm_drm_thread {
 	struct kthread_worker *worker;
 };
 
+/* DSC config */
+struct msm_display_dsc_config {
+	struct drm_dsc_config drm;
+	u8 scr_rev;
+
+	u32 initial_lines;
+	u32 pkt_per_line;
+	u32 bytes_in_slice;
+	u32 bytes_per_pkt;
+	u32 eol_byte_num;
+	u32 pclk_per_line;
+	u32 slice_last_group_size;
+	u32 slice_per_pkt;
+	u32 det_thresh_flatness;
+	u32 extra_width;
+	u32 pps_delay_ms;
+};
+
 struct msm_drm_private {
 
 	struct drm_device *dev;
@@ -227,6 +256,9 @@ struct msm_drm_private {
 	/* Properties */
 	struct drm_property *plane_property[PLANE_PROP_MAX_NUM];
 
+	/* DSC configuration */
+	struct msm_display_dsc_config *dsc;
+
 	/* VRAM carveout, used when no IOMMU: */
 	struct {
 		unsigned long size;
-- 
2.26.3


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

* [RFC PATCH 04/13] drm/msm/disp/dpu1: Add support for DSC in pingpong block
  2021-05-21 12:49 ` Vinod Koul
@ 2021-05-21 12:49   ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, David Airlie,
	Daniel Vetter, Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar,
	linux-kernel, dri-devel, freedreno

In SDM845, DSC can be enabled by writing to pingpong block registers, so
add support for DSC in hw_pp

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   | 32 +++++++++++++++++++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   | 14 ++++++++
 2 files changed, 46 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
index 245a7a62b5c6..07fc131ca9aa 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
@@ -28,6 +28,9 @@
 #define PP_FBC_MODE                     0x034
 #define PP_FBC_BUDGET_CTL               0x038
 #define PP_FBC_LOSSY_MODE               0x03C
+#define PP_DSC_MODE                     0x0a0
+#define PP_DCE_DATA_IN_SWAP             0x0ac
+#define PP_DCE_DATA_OUT_SWAP            0x0c8
 
 #define PP_DITHER_EN			0x000
 #define PP_DITHER_BITDEPTH		0x004
@@ -245,6 +248,32 @@ static u32 dpu_hw_pp_get_line_count(struct dpu_hw_pingpong *pp)
 	return line;
 }
 
+static int dpu_hw_pp_dsc_enable(struct dpu_hw_pingpong *pp)
+{
+	struct dpu_hw_blk_reg_map *c = &pp->hw;
+
+	DPU_REG_WRITE(c, PP_DSC_MODE, 1);
+	return 0;
+}
+
+static void dpu_hw_pp_dsc_disable(struct dpu_hw_pingpong *pp)
+{
+	struct dpu_hw_blk_reg_map *c = &pp->hw;
+
+	DPU_REG_WRITE(c, PP_DSC_MODE, 0);
+}
+
+static int dpu_hw_pp_setup_dsc(struct dpu_hw_pingpong *pp)
+{
+	struct dpu_hw_blk_reg_map *pp_c = &pp->hw;
+	int data;
+
+	data = DPU_REG_READ(pp_c, PP_DCE_DATA_OUT_SWAP);
+	data |= BIT(18); /* endian flip */
+	DPU_REG_WRITE(pp_c, PP_DCE_DATA_OUT_SWAP, data);
+	return 0;
+}
+
 static void _setup_pingpong_ops(struct dpu_hw_pingpong *c,
 				unsigned long features)
 {
@@ -256,6 +285,9 @@ static void _setup_pingpong_ops(struct dpu_hw_pingpong *c,
 	c->ops.get_autorefresh = dpu_hw_pp_get_autorefresh_config;
 	c->ops.poll_timeout_wr_ptr = dpu_hw_pp_poll_timeout_wr_ptr;
 	c->ops.get_line_count = dpu_hw_pp_get_line_count;
+	c->ops.setup_dsc = dpu_hw_pp_setup_dsc;
+	c->ops.enable_dsc = dpu_hw_pp_dsc_enable;
+	c->ops.disable_dsc = dpu_hw_pp_dsc_disable;
 
 	if (test_bit(DPU_PINGPONG_DITHER, &features))
 		c->ops.setup_dither = dpu_hw_pp_setup_dither;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
index 845b9ce80e31..5058e41ffbc0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
@@ -124,6 +124,20 @@ struct dpu_hw_pingpong_ops {
 	 */
 	void (*setup_dither)(struct dpu_hw_pingpong *pp,
 			struct dpu_hw_dither_cfg *cfg);
+	/**
+	 * Enable DSC
+	 */
+	int (*enable_dsc)(struct dpu_hw_pingpong *pp);
+
+	/**
+	 * Disable DSC
+	 */
+	void (*disable_dsc)(struct dpu_hw_pingpong *pp);
+
+	/**
+	 * Setup DSC
+	 */
+	int (*setup_dsc)(struct dpu_hw_pingpong *pp);
 };
 
 struct dpu_hw_pingpong {
-- 
2.26.3


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

* [RFC PATCH 04/13] drm/msm/disp/dpu1: Add support for DSC in pingpong block
@ 2021-05-21 12:49   ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, Vinod Koul, dri-devel,
	Dmitry Baryshkov, freedreno

In SDM845, DSC can be enabled by writing to pingpong block registers, so
add support for DSC in hw_pp

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   | 32 +++++++++++++++++++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   | 14 ++++++++
 2 files changed, 46 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
index 245a7a62b5c6..07fc131ca9aa 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
@@ -28,6 +28,9 @@
 #define PP_FBC_MODE                     0x034
 #define PP_FBC_BUDGET_CTL               0x038
 #define PP_FBC_LOSSY_MODE               0x03C
+#define PP_DSC_MODE                     0x0a0
+#define PP_DCE_DATA_IN_SWAP             0x0ac
+#define PP_DCE_DATA_OUT_SWAP            0x0c8
 
 #define PP_DITHER_EN			0x000
 #define PP_DITHER_BITDEPTH		0x004
@@ -245,6 +248,32 @@ static u32 dpu_hw_pp_get_line_count(struct dpu_hw_pingpong *pp)
 	return line;
 }
 
+static int dpu_hw_pp_dsc_enable(struct dpu_hw_pingpong *pp)
+{
+	struct dpu_hw_blk_reg_map *c = &pp->hw;
+
+	DPU_REG_WRITE(c, PP_DSC_MODE, 1);
+	return 0;
+}
+
+static void dpu_hw_pp_dsc_disable(struct dpu_hw_pingpong *pp)
+{
+	struct dpu_hw_blk_reg_map *c = &pp->hw;
+
+	DPU_REG_WRITE(c, PP_DSC_MODE, 0);
+}
+
+static int dpu_hw_pp_setup_dsc(struct dpu_hw_pingpong *pp)
+{
+	struct dpu_hw_blk_reg_map *pp_c = &pp->hw;
+	int data;
+
+	data = DPU_REG_READ(pp_c, PP_DCE_DATA_OUT_SWAP);
+	data |= BIT(18); /* endian flip */
+	DPU_REG_WRITE(pp_c, PP_DCE_DATA_OUT_SWAP, data);
+	return 0;
+}
+
 static void _setup_pingpong_ops(struct dpu_hw_pingpong *c,
 				unsigned long features)
 {
@@ -256,6 +285,9 @@ static void _setup_pingpong_ops(struct dpu_hw_pingpong *c,
 	c->ops.get_autorefresh = dpu_hw_pp_get_autorefresh_config;
 	c->ops.poll_timeout_wr_ptr = dpu_hw_pp_poll_timeout_wr_ptr;
 	c->ops.get_line_count = dpu_hw_pp_get_line_count;
+	c->ops.setup_dsc = dpu_hw_pp_setup_dsc;
+	c->ops.enable_dsc = dpu_hw_pp_dsc_enable;
+	c->ops.disable_dsc = dpu_hw_pp_dsc_disable;
 
 	if (test_bit(DPU_PINGPONG_DITHER, &features))
 		c->ops.setup_dither = dpu_hw_pp_setup_dither;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
index 845b9ce80e31..5058e41ffbc0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
@@ -124,6 +124,20 @@ struct dpu_hw_pingpong_ops {
 	 */
 	void (*setup_dither)(struct dpu_hw_pingpong *pp,
 			struct dpu_hw_dither_cfg *cfg);
+	/**
+	 * Enable DSC
+	 */
+	int (*enable_dsc)(struct dpu_hw_pingpong *pp);
+
+	/**
+	 * Disable DSC
+	 */
+	void (*disable_dsc)(struct dpu_hw_pingpong *pp);
+
+	/**
+	 * Setup DSC
+	 */
+	int (*setup_dsc)(struct dpu_hw_pingpong *pp);
 };
 
 struct dpu_hw_pingpong {
-- 
2.26.3


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

* [RFC PATCH 04/13] drm/msm/disp/dpu1: Add support for DSC
  2021-05-21 12:49 ` Vinod Koul
@ 2021-05-21 12:49   ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, David Airlie,
	Daniel Vetter, Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar,
	linux-kernel, dri-devel, freedreno

Display Stream Compression (DSC) is one of the hw blocks in dpu, so add
support by adding hw blocks for DSC

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/Makefile                  |   1 +
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |  26 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c    | 221 ++++++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h    |  79 +++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 ++
 5 files changed, 340 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 610d630326bb..fd8fc57f1f58 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -61,6 +61,7 @@ msm-y := \
 	disp/dpu1/dpu_hw_blk.o \
 	disp/dpu1/dpu_hw_catalog.o \
 	disp/dpu1/dpu_hw_ctl.o \
+	disp/dpu1/dpu_hw_dsc.o \
 	disp/dpu1/dpu_hw_interrupts.o \
 	disp/dpu1/dpu_hw_intf.o \
 	disp/dpu1/dpu_hw_lm.o \
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 4dfd8a20ad5c..a699633f7013 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -165,6 +165,7 @@ enum {
  * @DPU_PINGPONG_TE2        Additional tear check block for split pipes
  * @DPU_PINGPONG_SPLIT      PP block supports split fifo
  * @DPU_PINGPONG_SLAVE      PP block is a suitable slave for split fifo
+ * @DPU_PINGPONG_DSC        Display stream compression blocks
  * @DPU_PINGPONG_DITHER,    Dither blocks
  * @DPU_PINGPONG_MAX
  */
@@ -173,10 +174,21 @@ enum {
 	DPU_PINGPONG_TE2,
 	DPU_PINGPONG_SPLIT,
 	DPU_PINGPONG_SLAVE,
+	DPU_PINGPONG_DSC,
 	DPU_PINGPONG_DITHER,
 	DPU_PINGPONG_MAX
 };
 
+/**
+ * DSC sub-blocks
+ * @DPU_DSC		DSC sub block
+ * @DPU_DSC_MAX
+ */
+enum {
+	DPU_DSC = 0x1,
+	DPU_DSC_MAX
+};
+
 /**
  * CTL sub-blocks
  * @DPU_CTL_SPLIT_DISPLAY       CTL supports video mode split display
@@ -413,6 +425,7 @@ struct dpu_dspp_sub_blks {
 struct dpu_pingpong_sub_blks {
 	struct dpu_pp_blk te;
 	struct dpu_pp_blk te2;
+	struct dpu_pp_blk dsc;
 	struct dpu_pp_blk dither;
 };
 
@@ -547,6 +560,16 @@ struct dpu_merge_3d_cfg  {
 	const struct dpu_merge_3d_sub_blks *sblk;
 };
 
+/**
+ * struct dpu_dsc_cfg - information of DSC blocks
+ * @id                 enum identifying this block
+ * @base               register offset of this block
+ * @features           bit mask identifying sub-blocks/features
+ */
+struct dpu_dsc_cfg {
+	DPU_HW_BLK_INFO;
+};
+
 /**
  * struct dpu_intf_cfg - information of timing engine blocks
  * @id                 enum identifying this block
@@ -748,6 +771,9 @@ struct dpu_mdss_cfg {
 	u32 merge_3d_count;
 	const struct dpu_merge_3d_cfg *merge_3d;
 
+	u32 dsc_count;
+	struct dpu_dsc_cfg *dsc;
+
 	u32 intf_count;
 	const struct dpu_intf_cfg *intf;
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
new file mode 100644
index 000000000000..8b8d0553709d
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020, Linaro Limited
+ */
+
+#include "dpu_kms.h"
+#include "dpu_hw_catalog.h"
+#include "dpu_hwio.h"
+#include "dpu_hw_mdss.h"
+#include "dpu_hw_dsc.h"
+
+#define DSC_COMMON_MODE	                0x000
+#define DSC_ENC                         0X004
+#define DSC_PICTURE                     0x008
+#define DSC_SLICE                       0x00C
+#define DSC_CHUNK_SIZE                  0x010
+#define DSC_DELAY                       0x014
+#define DSC_SCALE_INITIAL               0x018
+#define DSC_SCALE_DEC_INTERVAL          0x01C
+#define DSC_SCALE_INC_INTERVAL          0x020
+#define DSC_FIRST_LINE_BPG_OFFSET       0x024
+#define DSC_BPG_OFFSET                  0x028
+#define DSC_DSC_OFFSET                  0x02C
+#define DSC_FLATNESS                    0x030
+#define DSC_RC_MODEL_SIZE               0x034
+#define DSC_RC                          0x038
+#define DSC_RC_BUF_THRESH               0x03C
+#define DSC_RANGE_MIN_QP                0x074
+#define DSC_RANGE_MAX_QP                0x0B0
+#define DSC_RANGE_BPG_OFFSET            0x0EC
+
+static void dpu_hw_dsc_disable(struct dpu_hw_dsc *dsc)
+{
+	struct dpu_hw_blk_reg_map *c = &dsc->hw;
+
+	DPU_REG_WRITE(c, DSC_COMMON_MODE, 0);
+}
+
+static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
+			      struct msm_display_dsc_config *dsc,
+			      u32 mode, bool ich_reset_override)
+{
+	struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
+	u32 data;
+	u32 initial_lines = dsc->initial_lines;
+	bool is_cmd_mode = !(mode & BIT(2));
+
+	DPU_REG_WRITE(c, DSC_COMMON_MODE, mode);
+
+	data = 0;
+	if (ich_reset_override)
+		data = 3 << 28;
+
+	if (is_cmd_mode)
+		initial_lines += 1;
+
+	data |= (initial_lines << 20);
+	data |= ((dsc->slice_last_group_size) << 18);
+	/* bpp is 6.4 format, 4 LSBs bits are for fractional part */
+	data |= dsc->drm.bits_per_pixel << 12;
+	data |= (dsc->drm.block_pred_enable << 7);
+	data |= (dsc->drm.line_buf_depth << 3);
+	data |= (dsc->drm.simple_422 << 2);
+	data |= (dsc->drm.convert_rgb << 1);
+	if (dsc->drm.bits_per_component  == 10)
+		data |= BIT(0);
+
+	DPU_REG_WRITE(c, DSC_ENC, data);
+
+	data = dsc->drm.pic_width << 16;
+	data |= dsc->drm.pic_height;
+	DPU_REG_WRITE(c, DSC_PICTURE, data);
+
+	data = dsc->drm.slice_width << 16;
+	data |= dsc->drm.slice_height;
+	DPU_REG_WRITE(c, DSC_SLICE, data);
+
+	data = DIV_ROUND_UP(dsc->drm.slice_width * dsc->drm.bits_per_pixel, 8) << 16;
+
+	DPU_REG_WRITE(c, DSC_CHUNK_SIZE, data);
+
+	data = dsc->drm.initial_dec_delay << 16;
+	data |= dsc->drm.initial_xmit_delay;
+	DPU_REG_WRITE(c, DSC_DELAY, data);
+
+	data = dsc->drm.initial_scale_value;
+	DPU_REG_WRITE(c, DSC_SCALE_INITIAL, data);
+
+	data = dsc->drm.scale_decrement_interval;
+	DPU_REG_WRITE(c, DSC_SCALE_DEC_INTERVAL, data);
+
+	data = 0x00000184; /* only this value works */
+	DPU_REG_WRITE(c, DSC_SCALE_INC_INTERVAL, data);
+
+	data = dsc->drm.first_line_bpg_offset;
+	DPU_REG_WRITE(c, DSC_FIRST_LINE_BPG_OFFSET, data);
+
+	data = dsc->drm.nfl_bpg_offset << 16;
+	data |= dsc->drm.slice_bpg_offset;
+	DPU_REG_WRITE(c, DSC_BPG_OFFSET, data);
+
+	data = dsc->drm.initial_offset << 16;
+	data |= dsc->drm.final_offset;
+	DPU_REG_WRITE(c, DSC_DSC_OFFSET, data);
+
+	data = dsc->det_thresh_flatness << 10;
+	data |= dsc->drm.flatness_max_qp << 5;
+	data |= dsc->drm.flatness_min_qp;
+	DPU_REG_WRITE(c, DSC_FLATNESS, data);
+
+	data = dsc->drm.rc_model_size;
+	DPU_REG_WRITE(c, DSC_RC_MODEL_SIZE, data);
+
+	data = dsc->drm.rc_tgt_offset_low << 18;
+	data |= dsc->drm.rc_tgt_offset_high << 14;
+	data |= dsc->drm.rc_quant_incr_limit1 << 9;
+	data |= dsc->drm.rc_quant_incr_limit0 << 4;
+	data |= dsc->drm.rc_edge_factor;
+	DPU_REG_WRITE(c, DSC_RC, data);
+}
+
+static void dpu_hw_dsc_config_thresh(struct dpu_hw_dsc *hw_dsc,
+				     struct msm_display_dsc_config *dsc)
+{
+	struct drm_dsc_rc_range_parameters *rc = dsc->drm.rc_range_params;
+	struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
+	u32 off = 0x0;
+	u16 *lp;
+	int i;
+
+	lp = dsc->drm.rc_buf_thresh;
+	off = DSC_RC_BUF_THRESH;
+	for (i = 0; i < DSC_NUM_BUF_RANGES - 1 ; i++) {
+		DPU_REG_WRITE(c, off, *lp++);
+		off += 4;
+	}
+
+	off = DSC_RANGE_MIN_QP;
+	for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
+		DPU_REG_WRITE(c, off, rc[i].range_min_qp);
+		off += 4;
+	}
+
+	off = DSC_RANGE_MAX_QP;
+	for (i = 0; i < 15; i++) {
+		DPU_REG_WRITE(c, off, rc[i].range_max_qp);
+		off += 4;
+	}
+
+	off = DSC_RANGE_BPG_OFFSET;
+	for (i = 0; i < 15; i++) {
+		DPU_REG_WRITE(c, off, rc[i].range_bpg_offset);
+		off += 4;
+	}
+}
+
+static struct dpu_dsc_cfg *_dsc_offset(enum dpu_dsc dsc,
+				       struct dpu_mdss_cfg *m,
+				       void __iomem *addr,
+				       struct dpu_hw_blk_reg_map *b)
+{
+	int i;
+
+	for (i = 0; i < m->dsc_count; i++) {
+		if (dsc == m->dsc[i].id) {
+			b->base_off = addr;
+			b->blk_off = m->dsc[i].base;
+			b->length = m->dsc[i].len;
+			b->hwversion = m->hwversion;
+			b->log_mask = DPU_DBG_MASK_DSC;
+			return &m->dsc[i];
+		}
+	}
+
+	return NULL;
+}
+
+static void _setup_dsc_ops(struct dpu_hw_dsc_ops *ops,
+			   unsigned long cap)
+{
+	ops->dsc_disable = dpu_hw_dsc_disable;
+	ops->dsc_config = dpu_hw_dsc_config;
+	ops->dsc_config_thresh = dpu_hw_dsc_config_thresh;
+};
+
+static struct dpu_hw_blk_ops dpu_hw_ops = {
+	.start = NULL,
+	.stop = NULL,
+};
+
+struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr,
+				   struct dpu_mdss_cfg *m)
+{
+	struct dpu_hw_dsc *c;
+	struct dpu_dsc_cfg *cfg;
+
+	c = kzalloc(sizeof(*c), GFP_KERNEL);
+	if (!c)
+		return ERR_PTR(-ENOMEM);
+
+	cfg = _dsc_offset(idx, m, addr, &c->hw);
+	if (IS_ERR_OR_NULL(cfg)) {
+		kfree(c);
+		return ERR_PTR(-EINVAL);
+	}
+
+	c->idx = idx;
+	c->caps = cfg;
+	_setup_dsc_ops(&c->ops, c->caps->features);
+
+	dpu_hw_blk_init(&c->base, DPU_HW_BLK_DSC, idx, &dpu_hw_ops);
+
+	return c;
+}
+
+void dpu_hw_dsc_destroy(struct dpu_hw_dsc *dsc)
+{
+	if (dsc)
+		dpu_hw_blk_destroy(&dsc->base);
+	kfree(dsc);
+}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
new file mode 100644
index 000000000000..c680fd948865
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2020, Linaro Limited */
+
+#ifndef _DPU_HW_DSC_H
+#define _DPU_HW_DSC_H
+
+#include <drm/drm_dsc.h>
+
+#define DSC_MODE_SPLIT_PANEL            BIT(0)
+#define DSC_MODE_MULTIPLEX              BIT(1)
+#define DSC_MODE_VIDEO                  BIT(2)
+
+struct dpu_hw_dsc;
+
+/**
+ * struct dpu_hw_dsc_ops - interface to the dsc hardware driver functions
+ * Assumption is these functions will be called after clocks are enabled
+ */
+struct dpu_hw_dsc_ops {
+	/**
+	 * dsc_disable - disable dsc
+	 * @hw_dsc: Pointer to dsc context
+	 */
+	void (*dsc_disable)(struct dpu_hw_dsc *hw_dsc);
+
+	/**
+	 * dsc_config - configures dsc encoder
+	 * @hw_dsc: Pointer to dsc context
+	 * @dsc: panel dsc parameters
+	 * @mode: dsc topology mode to be set
+	 * @ich_reset_override: option to reset ich
+	 */
+	void (*dsc_config)(struct dpu_hw_dsc *hw_dsc,
+			   struct msm_display_dsc_config *dsc,
+			   u32 mode, bool ich_reset_override);
+
+	/**
+	 * dsc_config_thresh - programs panel thresholds
+	 * @hw_dsc: Pointer to dsc context
+	 * @dsc: panel dsc parameters
+	 */
+	void (*dsc_config_thresh)(struct dpu_hw_dsc *hw_dsc,
+				  struct msm_display_dsc_config *dsc);
+};
+
+struct dpu_hw_dsc {
+	struct dpu_hw_blk base;
+	struct dpu_hw_blk_reg_map hw;
+
+	/* dsc */
+	enum dpu_dsc idx;
+	const struct dpu_dsc_cfg *caps;
+
+	/* ops */
+	struct dpu_hw_dsc_ops ops;
+};
+
+/**
+ * dpu_hw_dsc_init - initializes the dsc block for the passed dsc idx.
+ * @idx:  DSC index for which driver object is required
+ * @addr: Mapped register io address of MDP
+ * @m:    Pointer to mdss catalog data
+ * Returns: Error code or allocated dpu_hw_dsc context
+ */
+struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr,
+				   struct dpu_mdss_cfg *m);
+
+/**
+ * dpu_hw_dsc_destroy - destroys dsc driver context
+ * @dsc:   Pointer to dsc driver context returned by dpu_hw_dsc_init
+ */
+void dpu_hw_dsc_destroy(struct dpu_hw_dsc *dsc);
+
+static inline struct dpu_hw_dsc *to_dpu_hw_dsc(struct dpu_hw_blk *hw)
+{
+	return container_of(hw, struct dpu_hw_dsc, base);
+}
+
+#endif /* _DPU_HW_DSC_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 09a3fb3e89f5..1b72c11090ee 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -97,6 +97,7 @@ enum dpu_hw_blk_type {
 	DPU_HW_BLK_WB,
 	DPU_HW_BLK_DSPP,
 	DPU_HW_BLK_MERGE_3D,
+	DPU_HW_BLK_DSC,
 	DPU_HW_BLK_MAX,
 };
 
@@ -176,6 +177,17 @@ enum dpu_ctl {
 	CTL_MAX
 };
 
+enum dpu_dsc {
+	DSC_NONE = 0,
+	DSC_0,
+	DSC_1,
+	DSC_2,
+	DSC_3,
+	DSC_4,
+	DSC_5,
+	DSC_MAX
+};
+
 enum dpu_pingpong {
 	PINGPONG_0 = 1,
 	PINGPONG_1,
@@ -437,5 +449,6 @@ struct dpu_mdss_color {
 #define DPU_DBG_MASK_VBIF     (1 << 8)
 #define DPU_DBG_MASK_ROT      (1 << 9)
 #define DPU_DBG_MASK_DSPP     (1 << 10)
+#define DPU_DBG_MASK_DSC      (1 << 11)
 
 #endif  /* _DPU_HW_MDSS_H */
-- 
2.26.3


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

* [RFC PATCH 04/13] drm/msm/disp/dpu1: Add support for DSC
@ 2021-05-21 12:49   ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, Vinod Koul, dri-devel,
	Dmitry Baryshkov, freedreno

Display Stream Compression (DSC) is one of the hw blocks in dpu, so add
support by adding hw blocks for DSC

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/Makefile                  |   1 +
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |  26 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c    | 221 ++++++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h    |  79 +++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 ++
 5 files changed, 340 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 610d630326bb..fd8fc57f1f58 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -61,6 +61,7 @@ msm-y := \
 	disp/dpu1/dpu_hw_blk.o \
 	disp/dpu1/dpu_hw_catalog.o \
 	disp/dpu1/dpu_hw_ctl.o \
+	disp/dpu1/dpu_hw_dsc.o \
 	disp/dpu1/dpu_hw_interrupts.o \
 	disp/dpu1/dpu_hw_intf.o \
 	disp/dpu1/dpu_hw_lm.o \
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 4dfd8a20ad5c..a699633f7013 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -165,6 +165,7 @@ enum {
  * @DPU_PINGPONG_TE2        Additional tear check block for split pipes
  * @DPU_PINGPONG_SPLIT      PP block supports split fifo
  * @DPU_PINGPONG_SLAVE      PP block is a suitable slave for split fifo
+ * @DPU_PINGPONG_DSC        Display stream compression blocks
  * @DPU_PINGPONG_DITHER,    Dither blocks
  * @DPU_PINGPONG_MAX
  */
@@ -173,10 +174,21 @@ enum {
 	DPU_PINGPONG_TE2,
 	DPU_PINGPONG_SPLIT,
 	DPU_PINGPONG_SLAVE,
+	DPU_PINGPONG_DSC,
 	DPU_PINGPONG_DITHER,
 	DPU_PINGPONG_MAX
 };
 
+/**
+ * DSC sub-blocks
+ * @DPU_DSC		DSC sub block
+ * @DPU_DSC_MAX
+ */
+enum {
+	DPU_DSC = 0x1,
+	DPU_DSC_MAX
+};
+
 /**
  * CTL sub-blocks
  * @DPU_CTL_SPLIT_DISPLAY       CTL supports video mode split display
@@ -413,6 +425,7 @@ struct dpu_dspp_sub_blks {
 struct dpu_pingpong_sub_blks {
 	struct dpu_pp_blk te;
 	struct dpu_pp_blk te2;
+	struct dpu_pp_blk dsc;
 	struct dpu_pp_blk dither;
 };
 
@@ -547,6 +560,16 @@ struct dpu_merge_3d_cfg  {
 	const struct dpu_merge_3d_sub_blks *sblk;
 };
 
+/**
+ * struct dpu_dsc_cfg - information of DSC blocks
+ * @id                 enum identifying this block
+ * @base               register offset of this block
+ * @features           bit mask identifying sub-blocks/features
+ */
+struct dpu_dsc_cfg {
+	DPU_HW_BLK_INFO;
+};
+
 /**
  * struct dpu_intf_cfg - information of timing engine blocks
  * @id                 enum identifying this block
@@ -748,6 +771,9 @@ struct dpu_mdss_cfg {
 	u32 merge_3d_count;
 	const struct dpu_merge_3d_cfg *merge_3d;
 
+	u32 dsc_count;
+	struct dpu_dsc_cfg *dsc;
+
 	u32 intf_count;
 	const struct dpu_intf_cfg *intf;
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
new file mode 100644
index 000000000000..8b8d0553709d
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020, Linaro Limited
+ */
+
+#include "dpu_kms.h"
+#include "dpu_hw_catalog.h"
+#include "dpu_hwio.h"
+#include "dpu_hw_mdss.h"
+#include "dpu_hw_dsc.h"
+
+#define DSC_COMMON_MODE	                0x000
+#define DSC_ENC                         0X004
+#define DSC_PICTURE                     0x008
+#define DSC_SLICE                       0x00C
+#define DSC_CHUNK_SIZE                  0x010
+#define DSC_DELAY                       0x014
+#define DSC_SCALE_INITIAL               0x018
+#define DSC_SCALE_DEC_INTERVAL          0x01C
+#define DSC_SCALE_INC_INTERVAL          0x020
+#define DSC_FIRST_LINE_BPG_OFFSET       0x024
+#define DSC_BPG_OFFSET                  0x028
+#define DSC_DSC_OFFSET                  0x02C
+#define DSC_FLATNESS                    0x030
+#define DSC_RC_MODEL_SIZE               0x034
+#define DSC_RC                          0x038
+#define DSC_RC_BUF_THRESH               0x03C
+#define DSC_RANGE_MIN_QP                0x074
+#define DSC_RANGE_MAX_QP                0x0B0
+#define DSC_RANGE_BPG_OFFSET            0x0EC
+
+static void dpu_hw_dsc_disable(struct dpu_hw_dsc *dsc)
+{
+	struct dpu_hw_blk_reg_map *c = &dsc->hw;
+
+	DPU_REG_WRITE(c, DSC_COMMON_MODE, 0);
+}
+
+static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
+			      struct msm_display_dsc_config *dsc,
+			      u32 mode, bool ich_reset_override)
+{
+	struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
+	u32 data;
+	u32 initial_lines = dsc->initial_lines;
+	bool is_cmd_mode = !(mode & BIT(2));
+
+	DPU_REG_WRITE(c, DSC_COMMON_MODE, mode);
+
+	data = 0;
+	if (ich_reset_override)
+		data = 3 << 28;
+
+	if (is_cmd_mode)
+		initial_lines += 1;
+
+	data |= (initial_lines << 20);
+	data |= ((dsc->slice_last_group_size) << 18);
+	/* bpp is 6.4 format, 4 LSBs bits are for fractional part */
+	data |= dsc->drm.bits_per_pixel << 12;
+	data |= (dsc->drm.block_pred_enable << 7);
+	data |= (dsc->drm.line_buf_depth << 3);
+	data |= (dsc->drm.simple_422 << 2);
+	data |= (dsc->drm.convert_rgb << 1);
+	if (dsc->drm.bits_per_component  == 10)
+		data |= BIT(0);
+
+	DPU_REG_WRITE(c, DSC_ENC, data);
+
+	data = dsc->drm.pic_width << 16;
+	data |= dsc->drm.pic_height;
+	DPU_REG_WRITE(c, DSC_PICTURE, data);
+
+	data = dsc->drm.slice_width << 16;
+	data |= dsc->drm.slice_height;
+	DPU_REG_WRITE(c, DSC_SLICE, data);
+
+	data = DIV_ROUND_UP(dsc->drm.slice_width * dsc->drm.bits_per_pixel, 8) << 16;
+
+	DPU_REG_WRITE(c, DSC_CHUNK_SIZE, data);
+
+	data = dsc->drm.initial_dec_delay << 16;
+	data |= dsc->drm.initial_xmit_delay;
+	DPU_REG_WRITE(c, DSC_DELAY, data);
+
+	data = dsc->drm.initial_scale_value;
+	DPU_REG_WRITE(c, DSC_SCALE_INITIAL, data);
+
+	data = dsc->drm.scale_decrement_interval;
+	DPU_REG_WRITE(c, DSC_SCALE_DEC_INTERVAL, data);
+
+	data = 0x00000184; /* only this value works */
+	DPU_REG_WRITE(c, DSC_SCALE_INC_INTERVAL, data);
+
+	data = dsc->drm.first_line_bpg_offset;
+	DPU_REG_WRITE(c, DSC_FIRST_LINE_BPG_OFFSET, data);
+
+	data = dsc->drm.nfl_bpg_offset << 16;
+	data |= dsc->drm.slice_bpg_offset;
+	DPU_REG_WRITE(c, DSC_BPG_OFFSET, data);
+
+	data = dsc->drm.initial_offset << 16;
+	data |= dsc->drm.final_offset;
+	DPU_REG_WRITE(c, DSC_DSC_OFFSET, data);
+
+	data = dsc->det_thresh_flatness << 10;
+	data |= dsc->drm.flatness_max_qp << 5;
+	data |= dsc->drm.flatness_min_qp;
+	DPU_REG_WRITE(c, DSC_FLATNESS, data);
+
+	data = dsc->drm.rc_model_size;
+	DPU_REG_WRITE(c, DSC_RC_MODEL_SIZE, data);
+
+	data = dsc->drm.rc_tgt_offset_low << 18;
+	data |= dsc->drm.rc_tgt_offset_high << 14;
+	data |= dsc->drm.rc_quant_incr_limit1 << 9;
+	data |= dsc->drm.rc_quant_incr_limit0 << 4;
+	data |= dsc->drm.rc_edge_factor;
+	DPU_REG_WRITE(c, DSC_RC, data);
+}
+
+static void dpu_hw_dsc_config_thresh(struct dpu_hw_dsc *hw_dsc,
+				     struct msm_display_dsc_config *dsc)
+{
+	struct drm_dsc_rc_range_parameters *rc = dsc->drm.rc_range_params;
+	struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
+	u32 off = 0x0;
+	u16 *lp;
+	int i;
+
+	lp = dsc->drm.rc_buf_thresh;
+	off = DSC_RC_BUF_THRESH;
+	for (i = 0; i < DSC_NUM_BUF_RANGES - 1 ; i++) {
+		DPU_REG_WRITE(c, off, *lp++);
+		off += 4;
+	}
+
+	off = DSC_RANGE_MIN_QP;
+	for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
+		DPU_REG_WRITE(c, off, rc[i].range_min_qp);
+		off += 4;
+	}
+
+	off = DSC_RANGE_MAX_QP;
+	for (i = 0; i < 15; i++) {
+		DPU_REG_WRITE(c, off, rc[i].range_max_qp);
+		off += 4;
+	}
+
+	off = DSC_RANGE_BPG_OFFSET;
+	for (i = 0; i < 15; i++) {
+		DPU_REG_WRITE(c, off, rc[i].range_bpg_offset);
+		off += 4;
+	}
+}
+
+static struct dpu_dsc_cfg *_dsc_offset(enum dpu_dsc dsc,
+				       struct dpu_mdss_cfg *m,
+				       void __iomem *addr,
+				       struct dpu_hw_blk_reg_map *b)
+{
+	int i;
+
+	for (i = 0; i < m->dsc_count; i++) {
+		if (dsc == m->dsc[i].id) {
+			b->base_off = addr;
+			b->blk_off = m->dsc[i].base;
+			b->length = m->dsc[i].len;
+			b->hwversion = m->hwversion;
+			b->log_mask = DPU_DBG_MASK_DSC;
+			return &m->dsc[i];
+		}
+	}
+
+	return NULL;
+}
+
+static void _setup_dsc_ops(struct dpu_hw_dsc_ops *ops,
+			   unsigned long cap)
+{
+	ops->dsc_disable = dpu_hw_dsc_disable;
+	ops->dsc_config = dpu_hw_dsc_config;
+	ops->dsc_config_thresh = dpu_hw_dsc_config_thresh;
+};
+
+static struct dpu_hw_blk_ops dpu_hw_ops = {
+	.start = NULL,
+	.stop = NULL,
+};
+
+struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr,
+				   struct dpu_mdss_cfg *m)
+{
+	struct dpu_hw_dsc *c;
+	struct dpu_dsc_cfg *cfg;
+
+	c = kzalloc(sizeof(*c), GFP_KERNEL);
+	if (!c)
+		return ERR_PTR(-ENOMEM);
+
+	cfg = _dsc_offset(idx, m, addr, &c->hw);
+	if (IS_ERR_OR_NULL(cfg)) {
+		kfree(c);
+		return ERR_PTR(-EINVAL);
+	}
+
+	c->idx = idx;
+	c->caps = cfg;
+	_setup_dsc_ops(&c->ops, c->caps->features);
+
+	dpu_hw_blk_init(&c->base, DPU_HW_BLK_DSC, idx, &dpu_hw_ops);
+
+	return c;
+}
+
+void dpu_hw_dsc_destroy(struct dpu_hw_dsc *dsc)
+{
+	if (dsc)
+		dpu_hw_blk_destroy(&dsc->base);
+	kfree(dsc);
+}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
new file mode 100644
index 000000000000..c680fd948865
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2020, Linaro Limited */
+
+#ifndef _DPU_HW_DSC_H
+#define _DPU_HW_DSC_H
+
+#include <drm/drm_dsc.h>
+
+#define DSC_MODE_SPLIT_PANEL            BIT(0)
+#define DSC_MODE_MULTIPLEX              BIT(1)
+#define DSC_MODE_VIDEO                  BIT(2)
+
+struct dpu_hw_dsc;
+
+/**
+ * struct dpu_hw_dsc_ops - interface to the dsc hardware driver functions
+ * Assumption is these functions will be called after clocks are enabled
+ */
+struct dpu_hw_dsc_ops {
+	/**
+	 * dsc_disable - disable dsc
+	 * @hw_dsc: Pointer to dsc context
+	 */
+	void (*dsc_disable)(struct dpu_hw_dsc *hw_dsc);
+
+	/**
+	 * dsc_config - configures dsc encoder
+	 * @hw_dsc: Pointer to dsc context
+	 * @dsc: panel dsc parameters
+	 * @mode: dsc topology mode to be set
+	 * @ich_reset_override: option to reset ich
+	 */
+	void (*dsc_config)(struct dpu_hw_dsc *hw_dsc,
+			   struct msm_display_dsc_config *dsc,
+			   u32 mode, bool ich_reset_override);
+
+	/**
+	 * dsc_config_thresh - programs panel thresholds
+	 * @hw_dsc: Pointer to dsc context
+	 * @dsc: panel dsc parameters
+	 */
+	void (*dsc_config_thresh)(struct dpu_hw_dsc *hw_dsc,
+				  struct msm_display_dsc_config *dsc);
+};
+
+struct dpu_hw_dsc {
+	struct dpu_hw_blk base;
+	struct dpu_hw_blk_reg_map hw;
+
+	/* dsc */
+	enum dpu_dsc idx;
+	const struct dpu_dsc_cfg *caps;
+
+	/* ops */
+	struct dpu_hw_dsc_ops ops;
+};
+
+/**
+ * dpu_hw_dsc_init - initializes the dsc block for the passed dsc idx.
+ * @idx:  DSC index for which driver object is required
+ * @addr: Mapped register io address of MDP
+ * @m:    Pointer to mdss catalog data
+ * Returns: Error code or allocated dpu_hw_dsc context
+ */
+struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr,
+				   struct dpu_mdss_cfg *m);
+
+/**
+ * dpu_hw_dsc_destroy - destroys dsc driver context
+ * @dsc:   Pointer to dsc driver context returned by dpu_hw_dsc_init
+ */
+void dpu_hw_dsc_destroy(struct dpu_hw_dsc *dsc);
+
+static inline struct dpu_hw_dsc *to_dpu_hw_dsc(struct dpu_hw_blk *hw)
+{
+	return container_of(hw, struct dpu_hw_dsc, base);
+}
+
+#endif /* _DPU_HW_DSC_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 09a3fb3e89f5..1b72c11090ee 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -97,6 +97,7 @@ enum dpu_hw_blk_type {
 	DPU_HW_BLK_WB,
 	DPU_HW_BLK_DSPP,
 	DPU_HW_BLK_MERGE_3D,
+	DPU_HW_BLK_DSC,
 	DPU_HW_BLK_MAX,
 };
 
@@ -176,6 +177,17 @@ enum dpu_ctl {
 	CTL_MAX
 };
 
+enum dpu_dsc {
+	DSC_NONE = 0,
+	DSC_0,
+	DSC_1,
+	DSC_2,
+	DSC_3,
+	DSC_4,
+	DSC_5,
+	DSC_MAX
+};
+
 enum dpu_pingpong {
 	PINGPONG_0 = 1,
 	PINGPONG_1,
@@ -437,5 +449,6 @@ struct dpu_mdss_color {
 #define DPU_DBG_MASK_VBIF     (1 << 8)
 #define DPU_DBG_MASK_ROT      (1 << 9)
 #define DPU_DBG_MASK_DSPP     (1 << 10)
+#define DPU_DBG_MASK_DSC      (1 << 11)
 
 #endif  /* _DPU_HW_MDSS_H */
-- 
2.26.3


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

* [RFC PATCH 05/13] drm/msm/disp/dpu1: Add support for DSC in pingpong block
  2021-05-21 12:49 ` Vinod Koul
@ 2021-05-21 12:49   ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, David Airlie,
	Daniel Vetter, Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar,
	linux-kernel, dri-devel, freedreno

In SDM845, DSC can be enabled by writing to pingpong block registers, so
add support for DSC in hw_pp

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   | 32 +++++++++++++++++++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   | 14 ++++++++
 2 files changed, 46 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
index 245a7a62b5c6..07fc131ca9aa 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
@@ -28,6 +28,9 @@
 #define PP_FBC_MODE                     0x034
 #define PP_FBC_BUDGET_CTL               0x038
 #define PP_FBC_LOSSY_MODE               0x03C
+#define PP_DSC_MODE                     0x0a0
+#define PP_DCE_DATA_IN_SWAP             0x0ac
+#define PP_DCE_DATA_OUT_SWAP            0x0c8
 
 #define PP_DITHER_EN			0x000
 #define PP_DITHER_BITDEPTH		0x004
@@ -245,6 +248,32 @@ static u32 dpu_hw_pp_get_line_count(struct dpu_hw_pingpong *pp)
 	return line;
 }
 
+static int dpu_hw_pp_dsc_enable(struct dpu_hw_pingpong *pp)
+{
+	struct dpu_hw_blk_reg_map *c = &pp->hw;
+
+	DPU_REG_WRITE(c, PP_DSC_MODE, 1);
+	return 0;
+}
+
+static void dpu_hw_pp_dsc_disable(struct dpu_hw_pingpong *pp)
+{
+	struct dpu_hw_blk_reg_map *c = &pp->hw;
+
+	DPU_REG_WRITE(c, PP_DSC_MODE, 0);
+}
+
+static int dpu_hw_pp_setup_dsc(struct dpu_hw_pingpong *pp)
+{
+	struct dpu_hw_blk_reg_map *pp_c = &pp->hw;
+	int data;
+
+	data = DPU_REG_READ(pp_c, PP_DCE_DATA_OUT_SWAP);
+	data |= BIT(18); /* endian flip */
+	DPU_REG_WRITE(pp_c, PP_DCE_DATA_OUT_SWAP, data);
+	return 0;
+}
+
 static void _setup_pingpong_ops(struct dpu_hw_pingpong *c,
 				unsigned long features)
 {
@@ -256,6 +285,9 @@ static void _setup_pingpong_ops(struct dpu_hw_pingpong *c,
 	c->ops.get_autorefresh = dpu_hw_pp_get_autorefresh_config;
 	c->ops.poll_timeout_wr_ptr = dpu_hw_pp_poll_timeout_wr_ptr;
 	c->ops.get_line_count = dpu_hw_pp_get_line_count;
+	c->ops.setup_dsc = dpu_hw_pp_setup_dsc;
+	c->ops.enable_dsc = dpu_hw_pp_dsc_enable;
+	c->ops.disable_dsc = dpu_hw_pp_dsc_disable;
 
 	if (test_bit(DPU_PINGPONG_DITHER, &features))
 		c->ops.setup_dither = dpu_hw_pp_setup_dither;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
index 845b9ce80e31..5058e41ffbc0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
@@ -124,6 +124,20 @@ struct dpu_hw_pingpong_ops {
 	 */
 	void (*setup_dither)(struct dpu_hw_pingpong *pp,
 			struct dpu_hw_dither_cfg *cfg);
+	/**
+	 * Enable DSC
+	 */
+	int (*enable_dsc)(struct dpu_hw_pingpong *pp);
+
+	/**
+	 * Disable DSC
+	 */
+	void (*disable_dsc)(struct dpu_hw_pingpong *pp);
+
+	/**
+	 * Setup DSC
+	 */
+	int (*setup_dsc)(struct dpu_hw_pingpong *pp);
 };
 
 struct dpu_hw_pingpong {
-- 
2.26.3


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

* [RFC PATCH 05/13] drm/msm/disp/dpu1: Add support for DSC in pingpong block
@ 2021-05-21 12:49   ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, Vinod Koul, dri-devel,
	Dmitry Baryshkov, freedreno

In SDM845, DSC can be enabled by writing to pingpong block registers, so
add support for DSC in hw_pp

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   | 32 +++++++++++++++++++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   | 14 ++++++++
 2 files changed, 46 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
index 245a7a62b5c6..07fc131ca9aa 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
@@ -28,6 +28,9 @@
 #define PP_FBC_MODE                     0x034
 #define PP_FBC_BUDGET_CTL               0x038
 #define PP_FBC_LOSSY_MODE               0x03C
+#define PP_DSC_MODE                     0x0a0
+#define PP_DCE_DATA_IN_SWAP             0x0ac
+#define PP_DCE_DATA_OUT_SWAP            0x0c8
 
 #define PP_DITHER_EN			0x000
 #define PP_DITHER_BITDEPTH		0x004
@@ -245,6 +248,32 @@ static u32 dpu_hw_pp_get_line_count(struct dpu_hw_pingpong *pp)
 	return line;
 }
 
+static int dpu_hw_pp_dsc_enable(struct dpu_hw_pingpong *pp)
+{
+	struct dpu_hw_blk_reg_map *c = &pp->hw;
+
+	DPU_REG_WRITE(c, PP_DSC_MODE, 1);
+	return 0;
+}
+
+static void dpu_hw_pp_dsc_disable(struct dpu_hw_pingpong *pp)
+{
+	struct dpu_hw_blk_reg_map *c = &pp->hw;
+
+	DPU_REG_WRITE(c, PP_DSC_MODE, 0);
+}
+
+static int dpu_hw_pp_setup_dsc(struct dpu_hw_pingpong *pp)
+{
+	struct dpu_hw_blk_reg_map *pp_c = &pp->hw;
+	int data;
+
+	data = DPU_REG_READ(pp_c, PP_DCE_DATA_OUT_SWAP);
+	data |= BIT(18); /* endian flip */
+	DPU_REG_WRITE(pp_c, PP_DCE_DATA_OUT_SWAP, data);
+	return 0;
+}
+
 static void _setup_pingpong_ops(struct dpu_hw_pingpong *c,
 				unsigned long features)
 {
@@ -256,6 +285,9 @@ static void _setup_pingpong_ops(struct dpu_hw_pingpong *c,
 	c->ops.get_autorefresh = dpu_hw_pp_get_autorefresh_config;
 	c->ops.poll_timeout_wr_ptr = dpu_hw_pp_poll_timeout_wr_ptr;
 	c->ops.get_line_count = dpu_hw_pp_get_line_count;
+	c->ops.setup_dsc = dpu_hw_pp_setup_dsc;
+	c->ops.enable_dsc = dpu_hw_pp_dsc_enable;
+	c->ops.disable_dsc = dpu_hw_pp_dsc_disable;
 
 	if (test_bit(DPU_PINGPONG_DITHER, &features))
 		c->ops.setup_dither = dpu_hw_pp_setup_dither;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
index 845b9ce80e31..5058e41ffbc0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
@@ -124,6 +124,20 @@ struct dpu_hw_pingpong_ops {
 	 */
 	void (*setup_dither)(struct dpu_hw_pingpong *pp,
 			struct dpu_hw_dither_cfg *cfg);
+	/**
+	 * Enable DSC
+	 */
+	int (*enable_dsc)(struct dpu_hw_pingpong *pp);
+
+	/**
+	 * Disable DSC
+	 */
+	void (*disable_dsc)(struct dpu_hw_pingpong *pp);
+
+	/**
+	 * Setup DSC
+	 */
+	int (*setup_dsc)(struct dpu_hw_pingpong *pp);
 };
 
 struct dpu_hw_pingpong {
-- 
2.26.3


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

* [RFC PATCH 05/13] drm/msm/dsi: add support for dsc data
  2021-05-21 12:49 ` Vinod Koul
@ 2021-05-21 12:49   ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, David Airlie,
	Daniel Vetter, Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar,
	linux-kernel, dri-devel, freedreno

DSC needs some configuration from device tree, add support to read and
store these params and add DSC structures in msm_drv

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 171 +++++++++++++++++++++++++++++
 drivers/gpu/drm/msm/msm_drv.h      |  32 ++++++
 2 files changed, 203 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 8a10e4343281..e0c0f627d15e 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -156,6 +156,7 @@ struct msm_dsi_host {
 	struct regmap *sfpb;
 
 	struct drm_display_mode *mode;
+	struct msm_display_dsc_config *dsc;
 
 	/* connected device info */
 	struct device_node *device_node;
@@ -1744,6 +1745,168 @@ static int dsi_host_parse_lane_data(struct msm_dsi_host *msm_host,
 	return -EINVAL;
 }
 
+static u32 dsi_dsc_rc_buf_thresh[DSC_NUM_BUF_RANGES - 1] = {
+	0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, 0x62,
+	0x69, 0x70, 0x77, 0x79, 0x7b, 0x7d, 0x7e
+};
+
+/* only 8bpc, 8bpp added */
+static char min_qp[DSC_NUM_BUF_RANGES] = {
+	0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 13
+};
+
+static char max_qp[DSC_NUM_BUF_RANGES] = {
+	4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 11, 12, 13, 13, 15
+};
+
+static char bpg_offset[DSC_NUM_BUF_RANGES] = {
+	2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12
+};
+
+static int dsi_populate_dsc_params(struct msm_display_dsc_config *dsc)
+{
+	int i;
+
+	dsc->drm.rc_model_size = 8192;
+	dsc->drm.first_line_bpg_offset = 15;
+	dsc->drm.rc_edge_factor = 6;
+	dsc->drm.rc_tgt_offset_high = 3;
+	dsc->drm.rc_tgt_offset_low = 3;
+	dsc->drm.simple_422 = 0;
+	dsc->drm.convert_rgb = 1;
+	dsc->drm.vbr_enable = 0;
+
+	/* handle only bpp = bpc = 8 */
+	for (i = 0; i < DSC_NUM_BUF_RANGES - 1 ; i++)
+		dsc->drm.rc_buf_thresh[i] = dsi_dsc_rc_buf_thresh[i];
+
+	for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
+		dsc->drm.rc_range_params[i].range_min_qp = min_qp[i];
+		dsc->drm.rc_range_params[i].range_max_qp = max_qp[i];
+		dsc->drm.rc_range_params[i].range_bpg_offset = bpg_offset[i];
+	}
+
+	dsc->drm.initial_offset = 6144;
+	dsc->drm.initial_xmit_delay = 512;
+	dsc->drm.initial_scale_value = 32;
+	dsc->drm.first_line_bpg_offset = 12;
+	dsc->drm.line_buf_depth = dsc->drm.bits_per_component + 1;
+
+	/* bpc 8 */
+	dsc->drm.flatness_min_qp = 3;
+	dsc->drm.flatness_max_qp = 12;
+	dsc->det_thresh_flatness = 7;
+	dsc->drm.rc_quant_incr_limit0 = 11;
+	dsc->drm.rc_quant_incr_limit1 = 11;
+	dsc->drm.mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC;
+
+	/* FIXME: need to call drm_dsc_compute_rc_parameters() so that rest of
+	 * params are calculated
+	 */
+
+	i = dsc->drm.slice_width % 3;
+	switch (i) {
+	case 0:
+		dsc->slice_last_group_size = 2;
+		break;
+
+	case 1:
+		dsc->slice_last_group_size = 0;
+		break;
+
+	case 2:
+		dsc->slice_last_group_size = 0;
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int dsi_host_parse_dsc(struct msm_dsi_host *msm_host,
+			      struct device_node *np)
+{
+	struct device *dev = &msm_host->pdev->dev;
+	struct msm_display_dsc_config *dsc;
+	bool is_dsc_enabled;
+	u32 data;
+	int ret;
+
+	is_dsc_enabled = of_property_read_bool(np, "qcom,mdss-dsc-enabled");
+
+	if (!is_dsc_enabled)
+		return 0;
+
+	dsc = kzalloc(sizeof(*dsc), GFP_KERNEL);
+	if (!dsc)
+		return -ENOMEM;
+
+	ret = of_property_read_u32(np, "qcom,mdss-dsc-version", &data);
+	if (ret) {
+		dsc->drm.dsc_version_major = 0x1;
+		dsc->drm.dsc_version_minor = 0x1;
+	} else {
+		dsc->drm.dsc_version_major = (data >> 4) & 0xf;
+		dsc->drm.dsc_version_minor = data & 0xf;
+	}
+
+	ret = of_property_read_u32(np, "qcom,mdss-scr-version", &data);
+	if (ret)
+		dsc->scr_rev = 0;
+	else
+		dsc->scr_rev = data & 0xff;
+
+	ret = of_property_read_u32(np, "qcom,mdss-slice-height", &data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to read dsc slice height\n");
+		goto err;
+	}
+	dsc->drm.slice_height = data;
+
+	ret = of_property_read_u32(np, "qcom,mdss-slice-width", &data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to read dsc slice width\n");
+		goto err;
+	}
+	dsc->drm.slice_width = data;
+
+	ret = of_property_read_u32(np, "qcom,mdss-slice-per-pkt", &data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to read mdss-slice-per-pkt\n");
+		goto err;
+	}
+	dsc->slice_per_pkt = data;
+
+	ret = of_property_read_u32(np, "qcom,mdss-bit-per-component", &data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to read mdss-bit-per-component\n");
+		goto err;
+	}
+	dsc->drm.bits_per_component = data;
+
+	ret = of_property_read_u32(np, "qcom,mdss-bit-per-pixel", &data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to read bit-per-pixel\n");
+		goto err;
+	}
+	dsc->drm.bits_per_pixel = data;
+
+	dsc->drm.block_pred_enable = of_property_read_bool(np,
+			 "qcom,mdss-block-prediction-enable");
+
+	dsi_populate_dsc_params(dsc);
+
+	msm_host->dsc = dsc;
+
+	return 0;
+
+err:
+	kfree(dsc);
+	return ret;
+}
+
 static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 {
 	struct device *dev = &msm_host->pdev->dev;
@@ -1763,6 +1926,14 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 		return 0;
 	}
 
+	ret = dsi_host_parse_dsc(msm_host, np);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "%s: invalid dsc configuration %d\n",
+			__func__, ret);
+		ret = -EINVAL;
+		goto err;
+	}
+
 	ret = dsi_host_parse_lane_data(msm_host, endpoint);
 	if (ret) {
 		DRM_DEV_ERROR(dev, "%s: invalid lane configuration %d\n",
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 2668941df529..26661dd43936 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -30,6 +30,7 @@
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_dsc.h>
 #include <drm/msm_drm.h>
 #include <drm/drm_gem.h>
 
@@ -70,6 +71,16 @@ enum msm_mdp_plane_property {
 #define MSM_GPU_MAX_RINGS 4
 #define MAX_H_TILES_PER_DISPLAY 2
 
+/**
+ * enum msm_display_compression_type - compression method used for pixel stream
+ * @MSM_DISPLAY_COMPRESSION_NONE:	Pixel data is not compressed
+ * @MSM_DISPLAY_COMPRESSION_DSC:	DSC compresison is used
+ */
+enum msm_display_compression_type {
+	MSM_DISPLAY_COMPRESSION_NONE,
+	MSM_DISPLAY_COMPRESSION_DSC,
+};
+
 /**
  * enum msm_display_caps - features/capabilities supported by displays
  * @MSM_DISPLAY_CAP_VID_MODE:           Video or "active" mode supported
@@ -134,6 +145,24 @@ struct msm_drm_thread {
 	struct kthread_worker *worker;
 };
 
+/* DSC config */
+struct msm_display_dsc_config {
+	struct drm_dsc_config drm;
+	u8 scr_rev;
+
+	u32 initial_lines;
+	u32 pkt_per_line;
+	u32 bytes_in_slice;
+	u32 bytes_per_pkt;
+	u32 eol_byte_num;
+	u32 pclk_per_line;
+	u32 slice_last_group_size;
+	u32 slice_per_pkt;
+	u32 det_thresh_flatness;
+	u32 extra_width;
+	u32 pps_delay_ms;
+};
+
 struct msm_drm_private {
 
 	struct drm_device *dev;
@@ -227,6 +256,9 @@ struct msm_drm_private {
 	/* Properties */
 	struct drm_property *plane_property[PLANE_PROP_MAX_NUM];
 
+	/* DSC configuration */
+	struct msm_display_dsc_config *dsc;
+
 	/* VRAM carveout, used when no IOMMU: */
 	struct {
 		unsigned long size;
-- 
2.26.3


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

* [RFC PATCH 05/13] drm/msm/dsi: add support for dsc data
@ 2021-05-21 12:49   ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, Vinod Koul, dri-devel,
	Dmitry Baryshkov, freedreno

DSC needs some configuration from device tree, add support to read and
store these params and add DSC structures in msm_drv

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 171 +++++++++++++++++++++++++++++
 drivers/gpu/drm/msm/msm_drv.h      |  32 ++++++
 2 files changed, 203 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 8a10e4343281..e0c0f627d15e 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -156,6 +156,7 @@ struct msm_dsi_host {
 	struct regmap *sfpb;
 
 	struct drm_display_mode *mode;
+	struct msm_display_dsc_config *dsc;
 
 	/* connected device info */
 	struct device_node *device_node;
@@ -1744,6 +1745,168 @@ static int dsi_host_parse_lane_data(struct msm_dsi_host *msm_host,
 	return -EINVAL;
 }
 
+static u32 dsi_dsc_rc_buf_thresh[DSC_NUM_BUF_RANGES - 1] = {
+	0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, 0x62,
+	0x69, 0x70, 0x77, 0x79, 0x7b, 0x7d, 0x7e
+};
+
+/* only 8bpc, 8bpp added */
+static char min_qp[DSC_NUM_BUF_RANGES] = {
+	0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 13
+};
+
+static char max_qp[DSC_NUM_BUF_RANGES] = {
+	4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 11, 12, 13, 13, 15
+};
+
+static char bpg_offset[DSC_NUM_BUF_RANGES] = {
+	2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12
+};
+
+static int dsi_populate_dsc_params(struct msm_display_dsc_config *dsc)
+{
+	int i;
+
+	dsc->drm.rc_model_size = 8192;
+	dsc->drm.first_line_bpg_offset = 15;
+	dsc->drm.rc_edge_factor = 6;
+	dsc->drm.rc_tgt_offset_high = 3;
+	dsc->drm.rc_tgt_offset_low = 3;
+	dsc->drm.simple_422 = 0;
+	dsc->drm.convert_rgb = 1;
+	dsc->drm.vbr_enable = 0;
+
+	/* handle only bpp = bpc = 8 */
+	for (i = 0; i < DSC_NUM_BUF_RANGES - 1 ; i++)
+		dsc->drm.rc_buf_thresh[i] = dsi_dsc_rc_buf_thresh[i];
+
+	for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
+		dsc->drm.rc_range_params[i].range_min_qp = min_qp[i];
+		dsc->drm.rc_range_params[i].range_max_qp = max_qp[i];
+		dsc->drm.rc_range_params[i].range_bpg_offset = bpg_offset[i];
+	}
+
+	dsc->drm.initial_offset = 6144;
+	dsc->drm.initial_xmit_delay = 512;
+	dsc->drm.initial_scale_value = 32;
+	dsc->drm.first_line_bpg_offset = 12;
+	dsc->drm.line_buf_depth = dsc->drm.bits_per_component + 1;
+
+	/* bpc 8 */
+	dsc->drm.flatness_min_qp = 3;
+	dsc->drm.flatness_max_qp = 12;
+	dsc->det_thresh_flatness = 7;
+	dsc->drm.rc_quant_incr_limit0 = 11;
+	dsc->drm.rc_quant_incr_limit1 = 11;
+	dsc->drm.mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC;
+
+	/* FIXME: need to call drm_dsc_compute_rc_parameters() so that rest of
+	 * params are calculated
+	 */
+
+	i = dsc->drm.slice_width % 3;
+	switch (i) {
+	case 0:
+		dsc->slice_last_group_size = 2;
+		break;
+
+	case 1:
+		dsc->slice_last_group_size = 0;
+		break;
+
+	case 2:
+		dsc->slice_last_group_size = 0;
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int dsi_host_parse_dsc(struct msm_dsi_host *msm_host,
+			      struct device_node *np)
+{
+	struct device *dev = &msm_host->pdev->dev;
+	struct msm_display_dsc_config *dsc;
+	bool is_dsc_enabled;
+	u32 data;
+	int ret;
+
+	is_dsc_enabled = of_property_read_bool(np, "qcom,mdss-dsc-enabled");
+
+	if (!is_dsc_enabled)
+		return 0;
+
+	dsc = kzalloc(sizeof(*dsc), GFP_KERNEL);
+	if (!dsc)
+		return -ENOMEM;
+
+	ret = of_property_read_u32(np, "qcom,mdss-dsc-version", &data);
+	if (ret) {
+		dsc->drm.dsc_version_major = 0x1;
+		dsc->drm.dsc_version_minor = 0x1;
+	} else {
+		dsc->drm.dsc_version_major = (data >> 4) & 0xf;
+		dsc->drm.dsc_version_minor = data & 0xf;
+	}
+
+	ret = of_property_read_u32(np, "qcom,mdss-scr-version", &data);
+	if (ret)
+		dsc->scr_rev = 0;
+	else
+		dsc->scr_rev = data & 0xff;
+
+	ret = of_property_read_u32(np, "qcom,mdss-slice-height", &data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to read dsc slice height\n");
+		goto err;
+	}
+	dsc->drm.slice_height = data;
+
+	ret = of_property_read_u32(np, "qcom,mdss-slice-width", &data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to read dsc slice width\n");
+		goto err;
+	}
+	dsc->drm.slice_width = data;
+
+	ret = of_property_read_u32(np, "qcom,mdss-slice-per-pkt", &data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to read mdss-slice-per-pkt\n");
+		goto err;
+	}
+	dsc->slice_per_pkt = data;
+
+	ret = of_property_read_u32(np, "qcom,mdss-bit-per-component", &data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to read mdss-bit-per-component\n");
+		goto err;
+	}
+	dsc->drm.bits_per_component = data;
+
+	ret = of_property_read_u32(np, "qcom,mdss-bit-per-pixel", &data);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "failed to read bit-per-pixel\n");
+		goto err;
+	}
+	dsc->drm.bits_per_pixel = data;
+
+	dsc->drm.block_pred_enable = of_property_read_bool(np,
+			 "qcom,mdss-block-prediction-enable");
+
+	dsi_populate_dsc_params(dsc);
+
+	msm_host->dsc = dsc;
+
+	return 0;
+
+err:
+	kfree(dsc);
+	return ret;
+}
+
 static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 {
 	struct device *dev = &msm_host->pdev->dev;
@@ -1763,6 +1926,14 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 		return 0;
 	}
 
+	ret = dsi_host_parse_dsc(msm_host, np);
+	if (ret) {
+		DRM_DEV_ERROR(dev, "%s: invalid dsc configuration %d\n",
+			__func__, ret);
+		ret = -EINVAL;
+		goto err;
+	}
+
 	ret = dsi_host_parse_lane_data(msm_host, endpoint);
 	if (ret) {
 		DRM_DEV_ERROR(dev, "%s: invalid lane configuration %d\n",
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 2668941df529..26661dd43936 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -30,6 +30,7 @@
 #include <drm/drm_plane_helper.h>
 #include <drm/drm_probe_helper.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_dsc.h>
 #include <drm/msm_drm.h>
 #include <drm/drm_gem.h>
 
@@ -70,6 +71,16 @@ enum msm_mdp_plane_property {
 #define MSM_GPU_MAX_RINGS 4
 #define MAX_H_TILES_PER_DISPLAY 2
 
+/**
+ * enum msm_display_compression_type - compression method used for pixel stream
+ * @MSM_DISPLAY_COMPRESSION_NONE:	Pixel data is not compressed
+ * @MSM_DISPLAY_COMPRESSION_DSC:	DSC compresison is used
+ */
+enum msm_display_compression_type {
+	MSM_DISPLAY_COMPRESSION_NONE,
+	MSM_DISPLAY_COMPRESSION_DSC,
+};
+
 /**
  * enum msm_display_caps - features/capabilities supported by displays
  * @MSM_DISPLAY_CAP_VID_MODE:           Video or "active" mode supported
@@ -134,6 +145,24 @@ struct msm_drm_thread {
 	struct kthread_worker *worker;
 };
 
+/* DSC config */
+struct msm_display_dsc_config {
+	struct drm_dsc_config drm;
+	u8 scr_rev;
+
+	u32 initial_lines;
+	u32 pkt_per_line;
+	u32 bytes_in_slice;
+	u32 bytes_per_pkt;
+	u32 eol_byte_num;
+	u32 pclk_per_line;
+	u32 slice_last_group_size;
+	u32 slice_per_pkt;
+	u32 det_thresh_flatness;
+	u32 extra_width;
+	u32 pps_delay_ms;
+};
+
 struct msm_drm_private {
 
 	struct drm_device *dev;
@@ -227,6 +256,9 @@ struct msm_drm_private {
 	/* Properties */
 	struct drm_property *plane_property[PLANE_PROP_MAX_NUM];
 
+	/* DSC configuration */
+	struct msm_display_dsc_config *dsc;
+
 	/* VRAM carveout, used when no IOMMU: */
 	struct {
 		unsigned long size;
-- 
2.26.3


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

* [RFC PATCH 06/13] drm/msm/disp/dpu1: Add DSC support in RM
  2021-05-21 12:49 ` Vinod Koul
@ 2021-05-21 12:49   ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, David Airlie,
	Daniel Vetter, Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar,
	linux-kernel, dri-devel, freedreno

This add the bits in RM to enable the DSC blocks

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |  1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c  | 32 +++++++++++++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h  |  1 +
 3 files changed, 34 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index d6717d6672f7..d56c05146dfe 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -165,6 +165,7 @@ struct dpu_global_state {
 	uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
 	uint32_t intf_to_enc_id[INTF_MAX - INTF_0];
 	uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
+	uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
 };
 
 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 fd2d104f0a91..4da6d72b7996 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -11,6 +11,7 @@
 #include "dpu_hw_intf.h"
 #include "dpu_hw_dspp.h"
 #include "dpu_hw_merge3d.h"
+#include "dpu_hw_dsc.h"
 #include "dpu_encoder.h"
 #include "dpu_trace.h"
 
@@ -75,6 +76,14 @@ int dpu_rm_destroy(struct dpu_rm *rm)
 			dpu_hw_intf_destroy(hw);
 		}
 	}
+	for (i = 0; i < ARRAY_SIZE(rm->dsc_blks); i++) {
+		struct dpu_hw_dsc *hw;
+
+		if (rm->intf_blks[i]) {
+			hw = to_dpu_hw_dsc(rm->dsc_blks[i]);
+			dpu_hw_dsc_destroy(hw);
+		}
+	}
 
 	return 0;
 }
@@ -221,6 +230,19 @@ int dpu_rm_init(struct dpu_rm *rm,
 		rm->dspp_blks[dspp->id - DSPP_0] = &hw->base;
 	}
 
+	for (i = 0; i < cat->dsc_count; i++) {
+		struct dpu_hw_dsc *hw;
+		const struct dpu_dsc_cfg *dsc = &cat->dsc[i];
+
+		hw = dpu_hw_dsc_init(dsc->id, mmio, cat);
+		if (IS_ERR_OR_NULL(hw)) {
+			rc = PTR_ERR(hw);
+			DPU_ERROR("failed dsc object creation: err %d\n", rc);
+			goto fail;
+		}
+		rm->dsc_blks[dsc->id - DSC_0] = &hw->base;
+	}
+
 	return 0;
 
 fail:
@@ -476,6 +498,9 @@ static int _dpu_rm_reserve_intf(
 	}
 
 	global_state->intf_to_enc_id[idx] = enc_id;
+
+	global_state->dsc_to_enc_id[0] = enc_id;
+	global_state->dsc_to_enc_id[1] = enc_id;
 	return 0;
 }
 
@@ -567,6 +592,8 @@ void dpu_rm_release(struct dpu_global_state *global_state,
 		ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);
 	_dpu_rm_clear_mapping(global_state->intf_to_enc_id,
 		ARRAY_SIZE(global_state->intf_to_enc_id), enc->base.id);
+	_dpu_rm_clear_mapping(global_state->dsc_to_enc_id,
+		ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
 }
 
 int dpu_rm_reserve(
@@ -640,6 +667,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
 		hw_to_enc_id = global_state->dspp_to_enc_id;
 		max_blks = ARRAY_SIZE(rm->dspp_blks);
 		break;
+	case DPU_HW_BLK_DSC:
+		hw_blks = rm->dsc_blks;
+		hw_to_enc_id = global_state->dsc_to_enc_id;
+		max_blks = ARRAY_SIZE(rm->dsc_blks);
+		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 1f12c8d5b8aa..278d2a510b80 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -30,6 +30,7 @@ struct dpu_rm {
 	struct dpu_hw_blk *intf_blks[INTF_MAX - INTF_0];
 	struct dpu_hw_blk *dspp_blks[DSPP_MAX - DSPP_0];
 	struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0];
+	struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0];
 
 	uint32_t lm_max_width;
 };
-- 
2.26.3


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

* [RFC PATCH 06/13] drm/msm/disp/dpu1: Add DSC support in RM
@ 2021-05-21 12:49   ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, Vinod Koul, dri-devel,
	Dmitry Baryshkov, freedreno

This add the bits in RM to enable the DSC blocks

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |  1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c  | 32 +++++++++++++++++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h  |  1 +
 3 files changed, 34 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index d6717d6672f7..d56c05146dfe 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -165,6 +165,7 @@ struct dpu_global_state {
 	uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
 	uint32_t intf_to_enc_id[INTF_MAX - INTF_0];
 	uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
+	uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
 };
 
 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 fd2d104f0a91..4da6d72b7996 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -11,6 +11,7 @@
 #include "dpu_hw_intf.h"
 #include "dpu_hw_dspp.h"
 #include "dpu_hw_merge3d.h"
+#include "dpu_hw_dsc.h"
 #include "dpu_encoder.h"
 #include "dpu_trace.h"
 
@@ -75,6 +76,14 @@ int dpu_rm_destroy(struct dpu_rm *rm)
 			dpu_hw_intf_destroy(hw);
 		}
 	}
+	for (i = 0; i < ARRAY_SIZE(rm->dsc_blks); i++) {
+		struct dpu_hw_dsc *hw;
+
+		if (rm->intf_blks[i]) {
+			hw = to_dpu_hw_dsc(rm->dsc_blks[i]);
+			dpu_hw_dsc_destroy(hw);
+		}
+	}
 
 	return 0;
 }
@@ -221,6 +230,19 @@ int dpu_rm_init(struct dpu_rm *rm,
 		rm->dspp_blks[dspp->id - DSPP_0] = &hw->base;
 	}
 
+	for (i = 0; i < cat->dsc_count; i++) {
+		struct dpu_hw_dsc *hw;
+		const struct dpu_dsc_cfg *dsc = &cat->dsc[i];
+
+		hw = dpu_hw_dsc_init(dsc->id, mmio, cat);
+		if (IS_ERR_OR_NULL(hw)) {
+			rc = PTR_ERR(hw);
+			DPU_ERROR("failed dsc object creation: err %d\n", rc);
+			goto fail;
+		}
+		rm->dsc_blks[dsc->id - DSC_0] = &hw->base;
+	}
+
 	return 0;
 
 fail:
@@ -476,6 +498,9 @@ static int _dpu_rm_reserve_intf(
 	}
 
 	global_state->intf_to_enc_id[idx] = enc_id;
+
+	global_state->dsc_to_enc_id[0] = enc_id;
+	global_state->dsc_to_enc_id[1] = enc_id;
 	return 0;
 }
 
@@ -567,6 +592,8 @@ void dpu_rm_release(struct dpu_global_state *global_state,
 		ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);
 	_dpu_rm_clear_mapping(global_state->intf_to_enc_id,
 		ARRAY_SIZE(global_state->intf_to_enc_id), enc->base.id);
+	_dpu_rm_clear_mapping(global_state->dsc_to_enc_id,
+		ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
 }
 
 int dpu_rm_reserve(
@@ -640,6 +667,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
 		hw_to_enc_id = global_state->dspp_to_enc_id;
 		max_blks = ARRAY_SIZE(rm->dspp_blks);
 		break;
+	case DPU_HW_BLK_DSC:
+		hw_blks = rm->dsc_blks;
+		hw_to_enc_id = global_state->dsc_to_enc_id;
+		max_blks = ARRAY_SIZE(rm->dsc_blks);
+		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 1f12c8d5b8aa..278d2a510b80 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -30,6 +30,7 @@ struct dpu_rm {
 	struct dpu_hw_blk *intf_blks[INTF_MAX - INTF_0];
 	struct dpu_hw_blk *dspp_blks[DSPP_MAX - DSPP_0];
 	struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0];
+	struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0];
 
 	uint32_t lm_max_width;
 };
-- 
2.26.3


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

* [RFC PATCH 07/13] drm/msm/disp/dpu1: Add DSC for SDM845 to hw_catalog
  2021-05-21 12:49 ` Vinod Koul
@ 2021-05-21 12:49   ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, David Airlie,
	Daniel Vetter, Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar,
	linux-kernel, dri-devel, freedreno

This add SDM845 DSC blocks into hw_catalog

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c    | 22 +++++++++++++++++++
 1 file changed, 22 insertions(+)

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 b569030a0847..1bf599e8ffe0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -40,6 +40,8 @@
 
 #define PINGPONG_SDM845_MASK BIT(DPU_PINGPONG_DITHER)
 
+#define DSC_SDM845_MASK BIT(DPU_DSC)
+
 #define PINGPONG_SDM845_SPLIT_MASK \
 	(PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2))
 
@@ -751,6 +753,24 @@ static const struct dpu_pingpong_cfg sc7280_pp[] = {
 	PP_BLK("pingpong_2", PINGPONG_2, 0x6b000, 0, sc7280_pp_sblk),
 	PP_BLK("pingpong_3", PINGPONG_3, 0x6c000, 0, sc7280_pp_sblk),
 };
+
+/*************************************************************
+ * DSC sub blocks config
+ *************************************************************/
+#define DSC_BLK(_name, _id, _base) \
+	{\
+	.name = _name, .id = _id, \
+	.base = _base, .len = 0x140, \
+	.features = DSC_SDM845_MASK, \
+	}
+
+static struct dpu_dsc_cfg sdm845_dsc[] = {
+	DSC_BLK("dsc_0", DSC_0, 0x80000),
+	DSC_BLK("dsc_1", DSC_1, 0x80400),
+	DSC_BLK("dsc_2", DSC_2, 0x80800),
+	DSC_BLK("dsc_3", DSC_3, 0x80c00),
+};
+
 /*************************************************************
  * INTF sub blocks config
  *************************************************************/
@@ -1053,6 +1073,8 @@ static void sdm845_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
 		.mixer = sdm845_lm,
 		.pingpong_count = ARRAY_SIZE(sdm845_pp),
 		.pingpong = sdm845_pp,
+		.dsc_count = ARRAY_SIZE(sdm845_dsc),
+		.dsc = sdm845_dsc,
 		.intf_count = ARRAY_SIZE(sdm845_intf),
 		.intf = sdm845_intf,
 		.vbif_count = ARRAY_SIZE(sdm845_vbif),
-- 
2.26.3


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

* [RFC PATCH 07/13] drm/msm/disp/dpu1: Add DSC for SDM845 to hw_catalog
@ 2021-05-21 12:49   ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, Vinod Koul, dri-devel,
	Dmitry Baryshkov, freedreno

This add SDM845 DSC blocks into hw_catalog

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c    | 22 +++++++++++++++++++
 1 file changed, 22 insertions(+)

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 b569030a0847..1bf599e8ffe0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -40,6 +40,8 @@
 
 #define PINGPONG_SDM845_MASK BIT(DPU_PINGPONG_DITHER)
 
+#define DSC_SDM845_MASK BIT(DPU_DSC)
+
 #define PINGPONG_SDM845_SPLIT_MASK \
 	(PINGPONG_SDM845_MASK | BIT(DPU_PINGPONG_TE2))
 
@@ -751,6 +753,24 @@ static const struct dpu_pingpong_cfg sc7280_pp[] = {
 	PP_BLK("pingpong_2", PINGPONG_2, 0x6b000, 0, sc7280_pp_sblk),
 	PP_BLK("pingpong_3", PINGPONG_3, 0x6c000, 0, sc7280_pp_sblk),
 };
+
+/*************************************************************
+ * DSC sub blocks config
+ *************************************************************/
+#define DSC_BLK(_name, _id, _base) \
+	{\
+	.name = _name, .id = _id, \
+	.base = _base, .len = 0x140, \
+	.features = DSC_SDM845_MASK, \
+	}
+
+static struct dpu_dsc_cfg sdm845_dsc[] = {
+	DSC_BLK("dsc_0", DSC_0, 0x80000),
+	DSC_BLK("dsc_1", DSC_1, 0x80400),
+	DSC_BLK("dsc_2", DSC_2, 0x80800),
+	DSC_BLK("dsc_3", DSC_3, 0x80c00),
+};
+
 /*************************************************************
  * INTF sub blocks config
  *************************************************************/
@@ -1053,6 +1073,8 @@ static void sdm845_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
 		.mixer = sdm845_lm,
 		.pingpong_count = ARRAY_SIZE(sdm845_pp),
 		.pingpong = sdm845_pp,
+		.dsc_count = ARRAY_SIZE(sdm845_dsc),
+		.dsc = sdm845_dsc,
 		.intf_count = ARRAY_SIZE(sdm845_intf),
 		.intf = sdm845_intf,
 		.vbif_count = ARRAY_SIZE(sdm845_vbif),
-- 
2.26.3


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

* [RFC PATCH 08/13] drm/msm/disp/dpu1: Add DSC support in hw_ctl
  2021-05-21 12:49 ` Vinod Koul
@ 2021-05-21 12:49   ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, David Airlie,
	Daniel Vetter, Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar,
	linux-kernel, dri-devel, freedreno

Later gens of hardware have DSC bits moved to hw_ctl, so configure these
bits so that DSC would work there as well

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

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 2d4645e01ebf..aeea6add61ee 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -25,6 +25,8 @@
 #define   CTL_MERGE_3D_ACTIVE           0x0E4
 #define   CTL_INTF_ACTIVE               0x0F4
 #define   CTL_MERGE_3D_FLUSH            0x100
+#define   CTL_DSC_ACTIVE                0x0E8
+#define   CTL_DSC_FLUSH                0x104
 #define   CTL_INTF_FLUSH                0x110
 #define   CTL_INTF_MASTER               0x134
 #define   CTL_FETCH_PIPE_ACTIVE         0x0FC
@@ -34,6 +36,7 @@
 
 #define DPU_REG_RESET_TIMEOUT_US        2000
 #define  MERGE_3D_IDX   23
+#define  DSC_IDX        22
 #define  INTF_IDX       31
 #define CTL_INVALID_BIT                 0xffff
 
@@ -120,6 +123,7 @@ static u32 dpu_hw_ctl_get_pending_flush(struct dpu_hw_ctl *ctx)
 
 static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
 {
+	DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH, BIT(0) | BIT(1) | BIT(2) | BIT(3));
 
 	if (ctx->pending_flush_mask & BIT(MERGE_3D_IDX))
 		DPU_REG_WRITE(&ctx->hw, CTL_MERGE_3D_FLUSH,
@@ -128,7 +132,7 @@ static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
 		DPU_REG_WRITE(&ctx->hw, CTL_INTF_FLUSH,
 				ctx->pending_intf_flush_mask);
 
-	DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask);
+	DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask |  BIT(DSC_IDX));
 }
 
 static inline void dpu_hw_ctl_trigger_flush(struct dpu_hw_ctl *ctx)
@@ -507,6 +511,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
 	if (cfg->merge_3d)
 		DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE,
 			      BIT(cfg->merge_3d - MERGE_3D_0));
+	DPU_REG_WRITE(c, CTL_DSC_ACTIVE, BIT(0) | BIT(1) | BIT(2) | BIT(3));
 }
 
 static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
-- 
2.26.3


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

* [RFC PATCH 08/13] drm/msm/disp/dpu1: Add DSC support in hw_ctl
@ 2021-05-21 12:49   ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, Vinod Koul, dri-devel,
	Dmitry Baryshkov, freedreno

Later gens of hardware have DSC bits moved to hw_ctl, so configure these
bits so that DSC would work there as well

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

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 2d4645e01ebf..aeea6add61ee 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -25,6 +25,8 @@
 #define   CTL_MERGE_3D_ACTIVE           0x0E4
 #define   CTL_INTF_ACTIVE               0x0F4
 #define   CTL_MERGE_3D_FLUSH            0x100
+#define   CTL_DSC_ACTIVE                0x0E8
+#define   CTL_DSC_FLUSH                0x104
 #define   CTL_INTF_FLUSH                0x110
 #define   CTL_INTF_MASTER               0x134
 #define   CTL_FETCH_PIPE_ACTIVE         0x0FC
@@ -34,6 +36,7 @@
 
 #define DPU_REG_RESET_TIMEOUT_US        2000
 #define  MERGE_3D_IDX   23
+#define  DSC_IDX        22
 #define  INTF_IDX       31
 #define CTL_INVALID_BIT                 0xffff
 
@@ -120,6 +123,7 @@ static u32 dpu_hw_ctl_get_pending_flush(struct dpu_hw_ctl *ctx)
 
 static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
 {
+	DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH, BIT(0) | BIT(1) | BIT(2) | BIT(3));
 
 	if (ctx->pending_flush_mask & BIT(MERGE_3D_IDX))
 		DPU_REG_WRITE(&ctx->hw, CTL_MERGE_3D_FLUSH,
@@ -128,7 +132,7 @@ static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
 		DPU_REG_WRITE(&ctx->hw, CTL_INTF_FLUSH,
 				ctx->pending_intf_flush_mask);
 
-	DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask);
+	DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, ctx->pending_flush_mask |  BIT(DSC_IDX));
 }
 
 static inline void dpu_hw_ctl_trigger_flush(struct dpu_hw_ctl *ctx)
@@ -507,6 +511,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
 	if (cfg->merge_3d)
 		DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE,
 			      BIT(cfg->merge_3d - MERGE_3D_0));
+	DPU_REG_WRITE(c, CTL_DSC_ACTIVE, BIT(0) | BIT(1) | BIT(2) | BIT(3));
 }
 
 static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
-- 
2.26.3


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

* [RFC PATCH 09/13] drm/msm/disp/dpu1: Don't use DSC with mode_3d
  2021-05-21 12:49 ` Vinod Koul
@ 2021-05-21 12:49   ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, David Airlie,
	Daniel Vetter, Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar,
	linux-kernel, dri-devel, freedreno

We cannot enable mode_3d when we are using the DSC. So pass
configuration to detect DSC is enabled and not enable mode_3d
when we are using DSC

We add a helper dpu_encoder_helper_get_dsc_mode() to detect dsc
enabled and pass this to .setup_intf_cfg()

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h     | 11 +++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c |  2 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c           |  5 +++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h           |  2 ++
 4 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index ecbc4be98980..d43b804528eb 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -336,6 +336,17 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
 	return BLEND_3D_NONE;
 }
 
+static inline bool dpu_encoder_helper_get_dsc_mode(struct dpu_encoder_phys *phys_enc)
+{
+	struct drm_encoder *drm_enc = phys_enc->parent;
+	struct msm_drm_private *priv = drm_enc->dev->dev_private;
+
+	if (priv->dsc)
+		return true;
+
+	return false;
+}
+
 /**
  * dpu_encoder_helper_split_config - split display configuration helper function
  *	This helper function may be used by physical encoders to configure
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
index b2be39b9144e..5fe87881c30c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
@@ -69,6 +69,8 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg(
 	intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD;
 	intf_cfg.stream_sel = cmd_enc->stream_sel;
 	intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc);
+	intf_cfg.dsc = dpu_encoder_helper_get_dsc_mode(phys_enc);
+
 	ctl->ops.setup_intf_cfg(ctl, &intf_cfg);
 }
 
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 aeea6add61ee..f059416311ee 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -121,7 +121,7 @@ static u32 dpu_hw_ctl_get_pending_flush(struct dpu_hw_ctl *ctx)
 	return ctx->pending_flush_mask;
 }
 
-static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
+static void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
 {
 	DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH, BIT(0) | BIT(1) | BIT(2) | BIT(3));
 
@@ -522,7 +522,8 @@ static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
 
 	intf_cfg |= (cfg->intf & 0xF) << 4;
 
-	if (cfg->mode_3d) {
+	/* In DSC we can't set merge, so check for dsc too */
+	if (cfg->mode_3d && !cfg->dsc) {
 		intf_cfg |= BIT(19);
 		intf_cfg |= (cfg->mode_3d - 0x1) << 20;
 	}
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 806c171e5df2..347a653c1e01 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
+ * @dsc:                   DSC is enabled
  * @stream_sel:            Stream selection for multi-stream interfaces
  */
 struct dpu_hw_intf_cfg {
@@ -46,6 +47,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;
+	bool dsc;
 	int stream_sel;
 };
 
-- 
2.26.3


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

* [RFC PATCH 09/13] drm/msm/disp/dpu1: Don't use DSC with mode_3d
@ 2021-05-21 12:49   ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, Vinod Koul, dri-devel,
	Dmitry Baryshkov, freedreno

We cannot enable mode_3d when we are using the DSC. So pass
configuration to detect DSC is enabled and not enable mode_3d
when we are using DSC

We add a helper dpu_encoder_helper_get_dsc_mode() to detect dsc
enabled and pass this to .setup_intf_cfg()

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h     | 11 +++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c |  2 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c           |  5 +++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h           |  2 ++
 4 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index ecbc4be98980..d43b804528eb 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -336,6 +336,17 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
 	return BLEND_3D_NONE;
 }
 
+static inline bool dpu_encoder_helper_get_dsc_mode(struct dpu_encoder_phys *phys_enc)
+{
+	struct drm_encoder *drm_enc = phys_enc->parent;
+	struct msm_drm_private *priv = drm_enc->dev->dev_private;
+
+	if (priv->dsc)
+		return true;
+
+	return false;
+}
+
 /**
  * dpu_encoder_helper_split_config - split display configuration helper function
  *	This helper function may be used by physical encoders to configure
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
index b2be39b9144e..5fe87881c30c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
@@ -69,6 +69,8 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg(
 	intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD;
 	intf_cfg.stream_sel = cmd_enc->stream_sel;
 	intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc);
+	intf_cfg.dsc = dpu_encoder_helper_get_dsc_mode(phys_enc);
+
 	ctl->ops.setup_intf_cfg(ctl, &intf_cfg);
 }
 
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 aeea6add61ee..f059416311ee 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -121,7 +121,7 @@ static u32 dpu_hw_ctl_get_pending_flush(struct dpu_hw_ctl *ctx)
 	return ctx->pending_flush_mask;
 }
 
-static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
+static void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
 {
 	DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH, BIT(0) | BIT(1) | BIT(2) | BIT(3));
 
@@ -522,7 +522,8 @@ static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
 
 	intf_cfg |= (cfg->intf & 0xF) << 4;
 
-	if (cfg->mode_3d) {
+	/* In DSC we can't set merge, so check for dsc too */
+	if (cfg->mode_3d && !cfg->dsc) {
 		intf_cfg |= BIT(19);
 		intf_cfg |= (cfg->mode_3d - 0x1) << 20;
 	}
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 806c171e5df2..347a653c1e01 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
+ * @dsc:                   DSC is enabled
  * @stream_sel:            Stream selection for multi-stream interfaces
  */
 struct dpu_hw_intf_cfg {
@@ -46,6 +47,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;
+	bool dsc;
 	int stream_sel;
 };
 
-- 
2.26.3


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

* [RFC PATCH 09/13] drm/msm/disp/dpu1: Dont use DSC with mode_3d
  2021-05-21 12:49 ` Vinod Koul
@ 2021-05-21 12:49   ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, David Airlie,
	Daniel Vetter, Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar,
	linux-kernel, dri-devel, freedreno

We cannot enable mode_3d when we are using the DSC. So pass
configuration to detect DSC is enabled and not enable mode_3d
when we are using DSC

We add a helper dpu_encoder_helper_get_dsc_mode() to detect dsc
enabled and pass this to .setup_intf_cfg()

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h     | 11 +++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c |  2 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c           |  5 +++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h           |  2 ++
 4 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index ecbc4be98980..d43b804528eb 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -336,6 +336,17 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
 	return BLEND_3D_NONE;
 }
 
+static inline bool dpu_encoder_helper_get_dsc_mode(struct dpu_encoder_phys *phys_enc)
+{
+	struct drm_encoder *drm_enc = phys_enc->parent;
+	struct msm_drm_private *priv = drm_enc->dev->dev_private;
+
+	if (priv->dsc)
+		return true;
+
+	return false;
+}
+
 /**
  * dpu_encoder_helper_split_config - split display configuration helper function
  *	This helper function may be used by physical encoders to configure
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
index b2be39b9144e..5fe87881c30c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
@@ -69,6 +69,8 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg(
 	intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD;
 	intf_cfg.stream_sel = cmd_enc->stream_sel;
 	intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc);
+	intf_cfg.dsc = dpu_encoder_helper_get_dsc_mode(phys_enc);
+
 	ctl->ops.setup_intf_cfg(ctl, &intf_cfg);
 }
 
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 aeea6add61ee..f059416311ee 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -121,7 +121,7 @@ static u32 dpu_hw_ctl_get_pending_flush(struct dpu_hw_ctl *ctx)
 	return ctx->pending_flush_mask;
 }
 
-static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
+static void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
 {
 	DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH, BIT(0) | BIT(1) | BIT(2) | BIT(3));
 
@@ -522,7 +522,8 @@ static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
 
 	intf_cfg |= (cfg->intf & 0xF) << 4;
 
-	if (cfg->mode_3d) {
+	/* In DSC we can't set merge, so check for dsc too */
+	if (cfg->mode_3d && !cfg->dsc) {
 		intf_cfg |= BIT(19);
 		intf_cfg |= (cfg->mode_3d - 0x1) << 20;
 	}
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 806c171e5df2..347a653c1e01 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
+ * @dsc:                   DSC is enabled
  * @stream_sel:            Stream selection for multi-stream interfaces
  */
 struct dpu_hw_intf_cfg {
@@ -46,6 +47,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;
+	bool dsc;
 	int stream_sel;
 };
 
-- 
2.26.3


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

* [RFC PATCH 09/13] drm/msm/disp/dpu1: Dont use DSC with mode_3d
@ 2021-05-21 12:49   ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, Vinod Koul, dri-devel,
	Dmitry Baryshkov, freedreno

We cannot enable mode_3d when we are using the DSC. So pass
configuration to detect DSC is enabled and not enable mode_3d
when we are using DSC

We add a helper dpu_encoder_helper_get_dsc_mode() to detect dsc
enabled and pass this to .setup_intf_cfg()

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h     | 11 +++++++++++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c |  2 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c           |  5 +++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h           |  2 ++
 4 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index ecbc4be98980..d43b804528eb 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -336,6 +336,17 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
 	return BLEND_3D_NONE;
 }
 
+static inline bool dpu_encoder_helper_get_dsc_mode(struct dpu_encoder_phys *phys_enc)
+{
+	struct drm_encoder *drm_enc = phys_enc->parent;
+	struct msm_drm_private *priv = drm_enc->dev->dev_private;
+
+	if (priv->dsc)
+		return true;
+
+	return false;
+}
+
 /**
  * dpu_encoder_helper_split_config - split display configuration helper function
  *	This helper function may be used by physical encoders to configure
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
index b2be39b9144e..5fe87881c30c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
@@ -69,6 +69,8 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg(
 	intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD;
 	intf_cfg.stream_sel = cmd_enc->stream_sel;
 	intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc);
+	intf_cfg.dsc = dpu_encoder_helper_get_dsc_mode(phys_enc);
+
 	ctl->ops.setup_intf_cfg(ctl, &intf_cfg);
 }
 
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 aeea6add61ee..f059416311ee 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -121,7 +121,7 @@ static u32 dpu_hw_ctl_get_pending_flush(struct dpu_hw_ctl *ctx)
 	return ctx->pending_flush_mask;
 }
 
-static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
+static void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
 {
 	DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH, BIT(0) | BIT(1) | BIT(2) | BIT(3));
 
@@ -522,7 +522,8 @@ static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
 
 	intf_cfg |= (cfg->intf & 0xF) << 4;
 
-	if (cfg->mode_3d) {
+	/* In DSC we can't set merge, so check for dsc too */
+	if (cfg->mode_3d && !cfg->dsc) {
 		intf_cfg |= BIT(19);
 		intf_cfg |= (cfg->mode_3d - 0x1) << 20;
 	}
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 806c171e5df2..347a653c1e01 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
+ * @dsc:                   DSC is enabled
  * @stream_sel:            Stream selection for multi-stream interfaces
  */
 struct dpu_hw_intf_cfg {
@@ -46,6 +47,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;
+	bool dsc;
 	int stream_sel;
 };
 
-- 
2.26.3


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

* [RFC PATCH 10/13] drm/msm/disp/dpu1: Add support for DSC in encoder
  2021-05-21 12:49 ` Vinod Koul
@ 2021-05-21 12:49   ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, David Airlie,
	Daniel Vetter, Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar,
	linux-kernel, dri-devel, freedreno

When DSC is enabled in DT, we need to configure the encoder for DSC
configuration, calculate DSC parameters for the given timing.

This patch adds that support by adding dpu_encoder_prep_dsc() which is
invoked when DSC is enabled in DT

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 190 +++++++++++++++++++-
 1 file changed, 189 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 8d942052db8a..18cb1274a8bb 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -21,12 +21,17 @@
 #include "dpu_hw_intf.h"
 #include "dpu_hw_ctl.h"
 #include "dpu_hw_dspp.h"
+#include "dpu_hw_dsc.h"
 #include "dpu_formats.h"
 #include "dpu_encoder_phys.h"
 #include "dpu_crtc.h"
 #include "dpu_trace.h"
 #include "dpu_core_irq.h"
 
+#define DSC_MODE_SPLIT_PANEL		BIT(0)
+#define DSC_MODE_MULTIPLEX		BIT(1)
+#define DSC_MODE_VIDEO			BIT(2)
+
 #define DPU_DEBUG_ENC(e, fmt, ...) DPU_DEBUG("enc%d " fmt,\
 		(e) ? (e)->base.base.id : -1, ##__VA_ARGS__)
 
@@ -135,6 +140,7 @@ enum dpu_enc_rc_states {
  * @cur_slave:		As above but for the slave encoder.
  * @hw_pp:		Handle to the pingpong blocks used for the display. No.
  *			pingpong blocks can be different than num_phys_encs.
+ * @hw_dsc		Handle to the DSC blocks used for the display.
  * @intfs_swapped:	Whether or not the phys_enc interfaces have been swapped
  *			for partial update right-only cases, such as pingpong
  *			split where virtual pingpong does not generate IRQs
@@ -180,6 +186,7 @@ struct dpu_encoder_virt {
 	struct dpu_encoder_phys *cur_master;
 	struct dpu_encoder_phys *cur_slave;
 	struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
+	struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
 
 	bool intfs_swapped;
 
@@ -566,6 +573,8 @@ static struct msm_display_topology dpu_encoder_get_topology(
 			struct drm_display_mode *mode)
 {
 	struct msm_display_topology topology = {0};
+	struct drm_encoder *drm_enc;
+	struct msm_drm_private *priv;
 	int i, intf_count = 0;
 
 	for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
@@ -1008,7 +1017,8 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 	struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
 	struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
 	struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL };
-	int num_lm, num_ctl, num_pp;
+	struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC];
+	int num_lm, num_ctl, num_pp, num_dsc;
 	int i, j;
 
 	if (!drm_enc) {
@@ -1061,11 +1071,16 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 	dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
 		drm_enc->base.id, DPU_HW_BLK_DSPP, hw_dspp,
 		ARRAY_SIZE(hw_dspp));
+	num_dsc = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
+		drm_enc->base.id, DPU_HW_BLK_DSC, hw_dsc, ARRAY_SIZE(hw_dsc));
 
 	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
 		dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
 						: NULL;
 
+	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
+		dpu_enc->hw_dsc[i] = i < num_dsc ? to_dpu_hw_dsc(hw_dsc[i]) : NULL;
+
 	cstate = to_dpu_crtc_state(drm_crtc->state);
 
 	for (i = 0; i < num_lm; i++) {
@@ -1810,10 +1825,179 @@ static void dpu_encoder_vsync_event_work_handler(struct kthread_work *work)
 			nsecs_to_jiffies(ktime_to_ns(wakeup_time)));
 }
 
+static int dpu_encoder_dsc_update_pic_dim(struct msm_display_dsc_config *dsc,
+					  int pic_width, int pic_height)
+{
+	if (!dsc || !pic_width || !pic_height) {
+		DPU_ERROR("invalid input: pic_width=%d pic_height=%d\n",
+			  pic_width, pic_height);
+		return -EINVAL;
+	}
+
+	if ((pic_width % dsc->drm.slice_width) || (pic_height % dsc->drm.slice_height)) {
+		DPU_ERROR("pic_dim=%dx%d has to be multiple of slice=%dx%d\n",
+			  pic_width, pic_height, dsc->drm.slice_width, dsc->drm.slice_height);
+		return -EINVAL;
+	}
+
+	dsc->drm.pic_width = pic_width;
+	dsc->drm.pic_height = pic_height;
+
+	return 0;
+}
+
+static void
+dpu_encoder_dsc_pclk_param_calc(struct msm_display_dsc_config *dsc, u32 width)
+{
+	int slice_per_pkt, slice_per_intf;
+	int bytes_in_slice, total_bytes_per_intf;
+
+	if (!dsc || !dsc->drm.slice_width || !dsc->slice_per_pkt) {
+		DPU_ERROR("Invalid DSC/slices\n");
+		return;
+	}
+
+	slice_per_pkt = dsc->slice_per_pkt;
+	slice_per_intf = DIV_ROUND_UP(width, dsc->drm.slice_width);
+
+	/*
+	 * If slice_per_pkt is greater than slice_per_intf then default to 1.
+	 * This can happen during partial update.
+	 */
+	if (slice_per_pkt > slice_per_intf)
+		slice_per_pkt = 1;
+
+	bytes_in_slice = DIV_ROUND_UP(dsc->drm.slice_width *
+				      dsc->drm.bits_per_pixel, 8);
+	total_bytes_per_intf = bytes_in_slice * slice_per_intf;
+
+	dsc->eol_byte_num = total_bytes_per_intf % 3;
+	dsc->pclk_per_line =  DIV_ROUND_UP(total_bytes_per_intf, 3);
+	dsc->bytes_in_slice = bytes_in_slice;
+	dsc->bytes_per_pkt = bytes_in_slice * slice_per_pkt;
+	dsc->pkt_per_line = slice_per_intf / slice_per_pkt;
+}
+
+static void
+dpu_encoder_dsc_initial_line_calc(struct msm_display_dsc_config *dsc,
+				  u32 enc_ip_width)
+{
+	int ssm_delay, total_pixels, soft_slice_per_enc;
+
+	soft_slice_per_enc = enc_ip_width / dsc->drm.slice_width;
+
+	/*
+	 * minimum number of initial line pixels is a sum of:
+	 * 1. sub-stream multiplexer delay (83 groups for 8bpc,
+	 *    91 for 10 bpc) * 3
+	 * 2. for two soft slice cases, add extra sub-stream multiplexer * 3
+	 * 3. the initial xmit delay
+	 * 4. total pipeline delay through the "lock step" of encoder (47)
+	 * 5. 6 additional pixels as the output of the rate buffer is
+	 *    48 bits wide
+	 */
+	ssm_delay = ((dsc->drm.bits_per_component < 10) ? 84 : 92);
+	total_pixels = ssm_delay * 3 + dsc->drm.initial_xmit_delay + 47;
+	if (soft_slice_per_enc > 1)
+		total_pixels += (ssm_delay * 3);
+	dsc->initial_lines = DIV_ROUND_UP(total_pixels, dsc->drm.slice_width);
+}
+
+static bool
+dpu_encoder_dsc_ich_reset_override_needed(struct msm_display_dsc_config *dsc, bool pu_en)
+{
+	/* As per the DSC spec, ICH_RESET can be either end of the slice line
+	 * or at the end of the slice. HW internally generates ich_reset at
+	 * end of the slice line if DSC_MERGE is used or encoder has two
+	 * soft slices. However, if encoder has only 1 soft slice and DSC_MERGE
+	 * is not used then it will generate ich_reset at the end of slice.
+	 *
+	 * Now as per the spec, during one PPS session, position where
+	 * ich_reset is generated should not change. Now if full-screen frame
+	 * has more than 1 soft slice then HW will automatically generate
+	 * ich_reset at the end of slice_line. But for the same panel, if
+	 * partial frame is enabled and only 1 encoder is used with 1 slice,
+	 * then HW will generate ich_reset at end of the slice. This is a
+	 * mismatch. Prevent this by overriding HW's decision.
+	 */
+	return pu_en && dsc && (dsc->drm.slice_count > 1) &&
+		(dsc->drm.slice_width == dsc->drm.pic_width);
+}
+
+static void dpu_encoder_dsc_pipe_cfg(struct dpu_hw_dsc *hw_dsc,
+				     struct dpu_hw_pingpong *hw_pp,
+				     struct msm_display_dsc_config *dsc,
+				     u32 common_mode, bool ich_reset)
+{
+	if (hw_dsc->ops.dsc_config)
+		hw_dsc->ops.dsc_config(hw_dsc, dsc, common_mode, ich_reset);
+
+	if (hw_dsc->ops.dsc_config_thresh)
+		hw_dsc->ops.dsc_config_thresh(hw_dsc, dsc);
+
+	if (hw_pp->ops.setup_dsc)
+		hw_pp->ops.setup_dsc(hw_pp);
+
+	if (hw_pp->ops.enable_dsc)
+		hw_pp->ops.enable_dsc(hw_pp);
+}
+
+static void dpu_encoder_prep_dsc(struct dpu_encoder_virt *dpu_enc,
+				 struct msm_display_dsc_config *dsc)
+{
+	/* coding only for 2LM, 2enc, 1 dsc config */
+	struct dpu_encoder_phys *enc_master = dpu_enc->cur_master;
+	struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
+	struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
+	int this_frame_slices;
+	int intf_ip_w, enc_ip_w;
+	int ich_res, dsc_common_mode;
+	int pic_width, pic_height;
+	int i;
+
+	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
+		hw_pp[i] = dpu_enc->hw_pp[i];
+		hw_dsc[i] = dpu_enc->hw_dsc[i];
+
+		if (!hw_pp[i] || !hw_dsc[i]) {
+			DPU_ERROR_ENC(dpu_enc, "invalid params for DSC\n");
+			return;
+		}
+	}
+
+	dsc_common_mode = 0;
+	pic_width = dsc->drm.pic_width;
+	pic_height = dsc->drm.pic_height;
+
+	dpu_encoder_dsc_update_pic_dim(dsc, pic_width, pic_height);
+
+	dsc_common_mode = DSC_MODE_MULTIPLEX | DSC_MODE_SPLIT_PANEL;
+	if (enc_master->intf_mode == INTF_MODE_VIDEO)
+		dsc_common_mode |= DSC_MODE_VIDEO;
+
+	this_frame_slices = pic_width / dsc->drm.slice_width;
+	intf_ip_w = this_frame_slices * dsc->drm.slice_width;
+
+	dpu_encoder_dsc_pclk_param_calc(dsc, intf_ip_w);
+
+	/*
+	 * dsc merge case: when using 2 encoders for the same stream,
+	 * no. of slices need to be same on both the encoders.
+	 */
+	enc_ip_w = intf_ip_w / 2;
+	dpu_encoder_dsc_initial_line_calc(dsc, enc_ip_w);
+
+	ich_res = dpu_encoder_dsc_ich_reset_override_needed(dsc, false);
+
+	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
+		dpu_encoder_dsc_pipe_cfg(hw_dsc[i], hw_pp[i], dsc, dsc_common_mode, ich_res);
+}
+
 void dpu_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc)
 {
 	struct dpu_encoder_virt *dpu_enc;
 	struct dpu_encoder_phys *phys;
+	struct msm_drm_private *priv;
 	bool needs_hw_reset = false;
 	unsigned int i;
 
@@ -1841,6 +2025,10 @@ void dpu_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc)
 			dpu_encoder_helper_hw_reset(dpu_enc->phys_encs[i]);
 		}
 	}
+
+	priv = drm_enc->dev->dev_private;
+	if (priv->dsc)
+		dpu_encoder_prep_dsc(dpu_enc, priv->dsc);
 }
 
 void dpu_encoder_kickoff(struct drm_encoder *drm_enc)
-- 
2.26.3


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

* [RFC PATCH 10/13] drm/msm/disp/dpu1: Add support for DSC in encoder
@ 2021-05-21 12:49   ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, Vinod Koul, dri-devel,
	Dmitry Baryshkov, freedreno

When DSC is enabled in DT, we need to configure the encoder for DSC
configuration, calculate DSC parameters for the given timing.

This patch adds that support by adding dpu_encoder_prep_dsc() which is
invoked when DSC is enabled in DT

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 190 +++++++++++++++++++-
 1 file changed, 189 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 8d942052db8a..18cb1274a8bb 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -21,12 +21,17 @@
 #include "dpu_hw_intf.h"
 #include "dpu_hw_ctl.h"
 #include "dpu_hw_dspp.h"
+#include "dpu_hw_dsc.h"
 #include "dpu_formats.h"
 #include "dpu_encoder_phys.h"
 #include "dpu_crtc.h"
 #include "dpu_trace.h"
 #include "dpu_core_irq.h"
 
+#define DSC_MODE_SPLIT_PANEL		BIT(0)
+#define DSC_MODE_MULTIPLEX		BIT(1)
+#define DSC_MODE_VIDEO			BIT(2)
+
 #define DPU_DEBUG_ENC(e, fmt, ...) DPU_DEBUG("enc%d " fmt,\
 		(e) ? (e)->base.base.id : -1, ##__VA_ARGS__)
 
@@ -135,6 +140,7 @@ enum dpu_enc_rc_states {
  * @cur_slave:		As above but for the slave encoder.
  * @hw_pp:		Handle to the pingpong blocks used for the display. No.
  *			pingpong blocks can be different than num_phys_encs.
+ * @hw_dsc		Handle to the DSC blocks used for the display.
  * @intfs_swapped:	Whether or not the phys_enc interfaces have been swapped
  *			for partial update right-only cases, such as pingpong
  *			split where virtual pingpong does not generate IRQs
@@ -180,6 +186,7 @@ struct dpu_encoder_virt {
 	struct dpu_encoder_phys *cur_master;
 	struct dpu_encoder_phys *cur_slave;
 	struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
+	struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
 
 	bool intfs_swapped;
 
@@ -566,6 +573,8 @@ static struct msm_display_topology dpu_encoder_get_topology(
 			struct drm_display_mode *mode)
 {
 	struct msm_display_topology topology = {0};
+	struct drm_encoder *drm_enc;
+	struct msm_drm_private *priv;
 	int i, intf_count = 0;
 
 	for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
@@ -1008,7 +1017,8 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 	struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
 	struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
 	struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL };
-	int num_lm, num_ctl, num_pp;
+	struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC];
+	int num_lm, num_ctl, num_pp, num_dsc;
 	int i, j;
 
 	if (!drm_enc) {
@@ -1061,11 +1071,16 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
 	dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
 		drm_enc->base.id, DPU_HW_BLK_DSPP, hw_dspp,
 		ARRAY_SIZE(hw_dspp));
+	num_dsc = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
+		drm_enc->base.id, DPU_HW_BLK_DSC, hw_dsc, ARRAY_SIZE(hw_dsc));
 
 	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
 		dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
 						: NULL;
 
+	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
+		dpu_enc->hw_dsc[i] = i < num_dsc ? to_dpu_hw_dsc(hw_dsc[i]) : NULL;
+
 	cstate = to_dpu_crtc_state(drm_crtc->state);
 
 	for (i = 0; i < num_lm; i++) {
@@ -1810,10 +1825,179 @@ static void dpu_encoder_vsync_event_work_handler(struct kthread_work *work)
 			nsecs_to_jiffies(ktime_to_ns(wakeup_time)));
 }
 
+static int dpu_encoder_dsc_update_pic_dim(struct msm_display_dsc_config *dsc,
+					  int pic_width, int pic_height)
+{
+	if (!dsc || !pic_width || !pic_height) {
+		DPU_ERROR("invalid input: pic_width=%d pic_height=%d\n",
+			  pic_width, pic_height);
+		return -EINVAL;
+	}
+
+	if ((pic_width % dsc->drm.slice_width) || (pic_height % dsc->drm.slice_height)) {
+		DPU_ERROR("pic_dim=%dx%d has to be multiple of slice=%dx%d\n",
+			  pic_width, pic_height, dsc->drm.slice_width, dsc->drm.slice_height);
+		return -EINVAL;
+	}
+
+	dsc->drm.pic_width = pic_width;
+	dsc->drm.pic_height = pic_height;
+
+	return 0;
+}
+
+static void
+dpu_encoder_dsc_pclk_param_calc(struct msm_display_dsc_config *dsc, u32 width)
+{
+	int slice_per_pkt, slice_per_intf;
+	int bytes_in_slice, total_bytes_per_intf;
+
+	if (!dsc || !dsc->drm.slice_width || !dsc->slice_per_pkt) {
+		DPU_ERROR("Invalid DSC/slices\n");
+		return;
+	}
+
+	slice_per_pkt = dsc->slice_per_pkt;
+	slice_per_intf = DIV_ROUND_UP(width, dsc->drm.slice_width);
+
+	/*
+	 * If slice_per_pkt is greater than slice_per_intf then default to 1.
+	 * This can happen during partial update.
+	 */
+	if (slice_per_pkt > slice_per_intf)
+		slice_per_pkt = 1;
+
+	bytes_in_slice = DIV_ROUND_UP(dsc->drm.slice_width *
+				      dsc->drm.bits_per_pixel, 8);
+	total_bytes_per_intf = bytes_in_slice * slice_per_intf;
+
+	dsc->eol_byte_num = total_bytes_per_intf % 3;
+	dsc->pclk_per_line =  DIV_ROUND_UP(total_bytes_per_intf, 3);
+	dsc->bytes_in_slice = bytes_in_slice;
+	dsc->bytes_per_pkt = bytes_in_slice * slice_per_pkt;
+	dsc->pkt_per_line = slice_per_intf / slice_per_pkt;
+}
+
+static void
+dpu_encoder_dsc_initial_line_calc(struct msm_display_dsc_config *dsc,
+				  u32 enc_ip_width)
+{
+	int ssm_delay, total_pixels, soft_slice_per_enc;
+
+	soft_slice_per_enc = enc_ip_width / dsc->drm.slice_width;
+
+	/*
+	 * minimum number of initial line pixels is a sum of:
+	 * 1. sub-stream multiplexer delay (83 groups for 8bpc,
+	 *    91 for 10 bpc) * 3
+	 * 2. for two soft slice cases, add extra sub-stream multiplexer * 3
+	 * 3. the initial xmit delay
+	 * 4. total pipeline delay through the "lock step" of encoder (47)
+	 * 5. 6 additional pixels as the output of the rate buffer is
+	 *    48 bits wide
+	 */
+	ssm_delay = ((dsc->drm.bits_per_component < 10) ? 84 : 92);
+	total_pixels = ssm_delay * 3 + dsc->drm.initial_xmit_delay + 47;
+	if (soft_slice_per_enc > 1)
+		total_pixels += (ssm_delay * 3);
+	dsc->initial_lines = DIV_ROUND_UP(total_pixels, dsc->drm.slice_width);
+}
+
+static bool
+dpu_encoder_dsc_ich_reset_override_needed(struct msm_display_dsc_config *dsc, bool pu_en)
+{
+	/* As per the DSC spec, ICH_RESET can be either end of the slice line
+	 * or at the end of the slice. HW internally generates ich_reset at
+	 * end of the slice line if DSC_MERGE is used or encoder has two
+	 * soft slices. However, if encoder has only 1 soft slice and DSC_MERGE
+	 * is not used then it will generate ich_reset at the end of slice.
+	 *
+	 * Now as per the spec, during one PPS session, position where
+	 * ich_reset is generated should not change. Now if full-screen frame
+	 * has more than 1 soft slice then HW will automatically generate
+	 * ich_reset at the end of slice_line. But for the same panel, if
+	 * partial frame is enabled and only 1 encoder is used with 1 slice,
+	 * then HW will generate ich_reset at end of the slice. This is a
+	 * mismatch. Prevent this by overriding HW's decision.
+	 */
+	return pu_en && dsc && (dsc->drm.slice_count > 1) &&
+		(dsc->drm.slice_width == dsc->drm.pic_width);
+}
+
+static void dpu_encoder_dsc_pipe_cfg(struct dpu_hw_dsc *hw_dsc,
+				     struct dpu_hw_pingpong *hw_pp,
+				     struct msm_display_dsc_config *dsc,
+				     u32 common_mode, bool ich_reset)
+{
+	if (hw_dsc->ops.dsc_config)
+		hw_dsc->ops.dsc_config(hw_dsc, dsc, common_mode, ich_reset);
+
+	if (hw_dsc->ops.dsc_config_thresh)
+		hw_dsc->ops.dsc_config_thresh(hw_dsc, dsc);
+
+	if (hw_pp->ops.setup_dsc)
+		hw_pp->ops.setup_dsc(hw_pp);
+
+	if (hw_pp->ops.enable_dsc)
+		hw_pp->ops.enable_dsc(hw_pp);
+}
+
+static void dpu_encoder_prep_dsc(struct dpu_encoder_virt *dpu_enc,
+				 struct msm_display_dsc_config *dsc)
+{
+	/* coding only for 2LM, 2enc, 1 dsc config */
+	struct dpu_encoder_phys *enc_master = dpu_enc->cur_master;
+	struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
+	struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
+	int this_frame_slices;
+	int intf_ip_w, enc_ip_w;
+	int ich_res, dsc_common_mode;
+	int pic_width, pic_height;
+	int i;
+
+	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
+		hw_pp[i] = dpu_enc->hw_pp[i];
+		hw_dsc[i] = dpu_enc->hw_dsc[i];
+
+		if (!hw_pp[i] || !hw_dsc[i]) {
+			DPU_ERROR_ENC(dpu_enc, "invalid params for DSC\n");
+			return;
+		}
+	}
+
+	dsc_common_mode = 0;
+	pic_width = dsc->drm.pic_width;
+	pic_height = dsc->drm.pic_height;
+
+	dpu_encoder_dsc_update_pic_dim(dsc, pic_width, pic_height);
+
+	dsc_common_mode = DSC_MODE_MULTIPLEX | DSC_MODE_SPLIT_PANEL;
+	if (enc_master->intf_mode == INTF_MODE_VIDEO)
+		dsc_common_mode |= DSC_MODE_VIDEO;
+
+	this_frame_slices = pic_width / dsc->drm.slice_width;
+	intf_ip_w = this_frame_slices * dsc->drm.slice_width;
+
+	dpu_encoder_dsc_pclk_param_calc(dsc, intf_ip_w);
+
+	/*
+	 * dsc merge case: when using 2 encoders for the same stream,
+	 * no. of slices need to be same on both the encoders.
+	 */
+	enc_ip_w = intf_ip_w / 2;
+	dpu_encoder_dsc_initial_line_calc(dsc, enc_ip_w);
+
+	ich_res = dpu_encoder_dsc_ich_reset_override_needed(dsc, false);
+
+	for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
+		dpu_encoder_dsc_pipe_cfg(hw_dsc[i], hw_pp[i], dsc, dsc_common_mode, ich_res);
+}
+
 void dpu_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc)
 {
 	struct dpu_encoder_virt *dpu_enc;
 	struct dpu_encoder_phys *phys;
+	struct msm_drm_private *priv;
 	bool needs_hw_reset = false;
 	unsigned int i;
 
@@ -1841,6 +2025,10 @@ void dpu_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc)
 			dpu_encoder_helper_hw_reset(dpu_enc->phys_encs[i]);
 		}
 	}
+
+	priv = drm_enc->dev->dev_private;
+	if (priv->dsc)
+		dpu_encoder_prep_dsc(dpu_enc, priv->dsc);
 }
 
 void dpu_encoder_kickoff(struct drm_encoder *drm_enc)
-- 
2.26.3


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

* [RFC PATCH 11/13] drm/msm/disp/dpu1: Add support for DSC in topology
  2021-05-21 12:49 ` Vinod Koul
@ 2021-05-21 12:49   ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, David Airlie,
	Daniel Vetter, Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar,
	linux-kernel, dri-devel, freedreno

For DSC to work we typically need a 2,2,1 configuration. This should
suffice for resolutions upto 4k. For more resolutions like 8k this won't
work.

Furthermore, we can use 1 DSC encoder in lesser resulutions, but that is
not power efficient according to Abhinav, so it is recommended to always
use 2 encoders.

So for now we blindly create 2,2,1 topology when DSC is enabled

Co-developed-by: Abhinav Kumar <abhinavk@codeaurora.org>
Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org>
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 18cb1274a8bb..bffb40085c67 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -609,8 +609,22 @@ static struct msm_display_topology dpu_encoder_get_topology(
 	topology.num_enc = 0;
 	topology.num_intf = intf_count;
 
+	drm_enc = &dpu_enc->base;
+	priv = drm_enc->dev->dev_private;
+	if (priv && priv->dsc) {
+		/* In case of Display Stream Compression DSC, we would use
+		 * 2 encoders, 2 line mixers and 1 interface
+		 * this is power optimal and can drive upto (including) 4k
+		 * screens
+		 */
+		topology.num_enc = 2;
+		topology.num_intf = 1;
+		topology.num_lm = 2;
+	}
+
 	return topology;
 }
+
 static int dpu_encoder_virt_atomic_check(
 		struct drm_encoder *drm_enc,
 		struct drm_crtc_state *crtc_state,
-- 
2.26.3


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

* [RFC PATCH 11/13] drm/msm/disp/dpu1: Add support for DSC in topology
@ 2021-05-21 12:49   ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, Vinod Koul, dri-devel,
	Dmitry Baryshkov, freedreno

For DSC to work we typically need a 2,2,1 configuration. This should
suffice for resolutions upto 4k. For more resolutions like 8k this won't
work.

Furthermore, we can use 1 DSC encoder in lesser resulutions, but that is
not power efficient according to Abhinav, so it is recommended to always
use 2 encoders.

So for now we blindly create 2,2,1 topology when DSC is enabled

Co-developed-by: Abhinav Kumar <abhinavk@codeaurora.org>
Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org>
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 18cb1274a8bb..bffb40085c67 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -609,8 +609,22 @@ static struct msm_display_topology dpu_encoder_get_topology(
 	topology.num_enc = 0;
 	topology.num_intf = intf_count;
 
+	drm_enc = &dpu_enc->base;
+	priv = drm_enc->dev->dev_private;
+	if (priv && priv->dsc) {
+		/* In case of Display Stream Compression DSC, we would use
+		 * 2 encoders, 2 line mixers and 1 interface
+		 * this is power optimal and can drive upto (including) 4k
+		 * screens
+		 */
+		topology.num_enc = 2;
+		topology.num_intf = 1;
+		topology.num_lm = 2;
+	}
+
 	return topology;
 }
+
 static int dpu_encoder_virt_atomic_check(
 		struct drm_encoder *drm_enc,
 		struct drm_crtc_state *crtc_state,
-- 
2.26.3


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

* [RFC PATCH 12/13] drm/msm/dsi: Add support for DSC configuration
  2021-05-21 12:49 ` Vinod Koul
@ 2021-05-21 12:49   ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, David Airlie,
	Daniel Vetter, Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar,
	linux-kernel, dri-devel, freedreno

When DSC is enabled, we need to configure DSI registers accordingly and
configure the respective stream compression registers.

Add support to calculate the register setting based on DSC params and
timing information and configure these registers.

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/dsi/dsi.xml.h  |  10 +++
 drivers/gpu/drm/msm/dsi/dsi_host.c | 118 ++++++++++++++++++++++++++---
 2 files changed, 118 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h b/drivers/gpu/drm/msm/dsi/dsi.xml.h
index 50eb4d1b8fdd..b8e9e608abfc 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
@@ -2310,4 +2310,14 @@ static inline uint32_t REG_DSI_7nm_PHY_LN_TX_DCTRL(uint32_t i0) { return 0x00000
 
 #define REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE			0x00000260
 
+#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL			0x0000029c
+
+#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL2			0x000002a0
+
+#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL			0x000002a4
+
+#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2			0x000002a8
+
+#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL3			0x000002ac
+
 #endif /* DSI_XML */
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 864d3c655e73..e26545fc82e0 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -954,6 +954,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi)
 	u32 va_end = va_start + mode->vdisplay;
 	u32 hdisplay = mode->hdisplay;
 	u32 wc;
+	u32 data;
 
 	DBG("");
 
@@ -972,7 +973,69 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi)
 		hdisplay /= 2;
 	}
 
+	if (msm_host->dsc) {
+		struct msm_display_dsc_config *dsc = msm_host->dsc;
+
+		/* update dsc params with timing params */
+		dsc->drm.pic_width = mode->hdisplay;
+		dsc->drm.pic_height = mode->vdisplay;
+
+		/* Divide the display by 3 but keep back/font porch and
+		 * pulse width same
+		 */
+		h_total -= hdisplay;
+		hdisplay /= 3;
+		h_total += hdisplay;
+		ha_end = ha_start + hdisplay;
+	}
+
 	if (msm_host->mode_flags & MIPI_DSI_MODE_VIDEO) {
+		if (msm_host->dsc) {
+			struct msm_display_dsc_config *dsc = msm_host->dsc;
+			u32 reg, intf_width, slice_per_intf, width;
+			u32 total_bytes_per_intf;
+
+			/* first calculate dsc parameters and then program
+			 * compress mode registers
+			 */
+			intf_width = hdisplay;
+			slice_per_intf = DIV_ROUND_UP(intf_width, dsc->drm.slice_width);
+
+			/* If slice_per_pkt > slice_per_intf, then use 1
+			 * This can happen during partial update
+			 */
+			if (dsc->slice_per_pkt > slice_per_intf)
+				dsc->slice_per_pkt = 1;
+
+			dsc->bytes_in_slice = DIV_ROUND_UP(dsc->drm.slice_width * 8, 8);
+			total_bytes_per_intf = dsc->bytes_in_slice * slice_per_intf;
+
+			dsc->eol_byte_num = total_bytes_per_intf % 3;
+			dsc->pclk_per_line =  DIV_ROUND_UP(total_bytes_per_intf, 3);
+			dsc->bytes_per_pkt = dsc->bytes_in_slice * dsc->slice_per_pkt;
+			dsc->pkt_per_line = slice_per_intf / dsc->slice_per_pkt;
+
+			width = dsc->pclk_per_line;
+			reg = dsc->bytes_per_pkt << 16;
+			reg |= (0x0b << 8);    /* dtype of compressed image */
+
+			/* pkt_per_line:
+			 * 0 == 1 pkt
+			 * 1 == 2 pkt
+			 * 2 == 4 pkt
+			 * 3 pkt is not supported
+			 * above translates to ffs() - 1
+			 */
+			reg |= (ffs(dsc->pkt_per_line) - 1) << 6;
+
+			dsc->eol_byte_num = total_bytes_per_intf % 3;
+			reg |= dsc->eol_byte_num << 4;
+			reg |= 1;
+
+			dsi_write(msm_host,
+				  REG_DSI_VIDEO_COMPRESSION_MODE_CTRL, reg);
+		}
+
 		dsi_write(msm_host, REG_DSI_ACTIVE_H,
 			DSI_ACTIVE_H_START(ha_start) |
 			DSI_ACTIVE_H_END(ha_end));
@@ -991,19 +1054,50 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi)
 			DSI_ACTIVE_VSYNC_VPOS_START(vs_start) |
 			DSI_ACTIVE_VSYNC_VPOS_END(vs_end));
 	} else {		/* command mode */
+		if (msm_host->dsc) {
+			struct msm_display_dsc_config *dsc = msm_host->dsc;
+			u32 reg, reg_ctrl, reg_ctrl2;
+			u32 slice_per_intf, bytes_in_slice, total_bytes_per_intf;
+
+			reg_ctrl = dsi_read(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL);
+			reg_ctrl2 = dsi_read(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2);
+
+			slice_per_intf = DIV_ROUND_UP(hdisplay, dsc->drm.slice_width);
+			bytes_in_slice = DIV_ROUND_UP(dsc->drm.slice_width *
+						      dsc->drm.bits_per_pixel, 8);
+			dsc->drm.slice_chunk_size = bytes_in_slice;
+			total_bytes_per_intf = dsc->bytes_in_slice * slice_per_intf;
+			dsc->pkt_per_line = slice_per_intf / dsc->slice_per_pkt;
+
+			reg = 0x39 << 8;
+			reg |= ffs(dsc->pkt_per_line) << 6;
+
+			dsc->eol_byte_num = total_bytes_per_intf % 3;
+			reg |= dsc->eol_byte_num << 4;
+			reg |= 1;
+
+			reg_ctrl |= reg;
+			reg_ctrl2 |= bytes_in_slice;
+
+			dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL, reg);
+			dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2, reg_ctrl2);
+		}
+
 		/* image data and 1 byte write_memory_start cmd */
-		wc = hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1;
+		if (!msm_host->dsc)
+			wc = hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1;
+		else
+			wc = mode->hdisplay / 2 + 1;
+
+		data = DSI_CMD_MDP_STREAM0_CTRL_WORD_COUNT(wc) |
+		       DSI_CMD_MDP_STREAM0_CTRL_VIRTUAL_CHANNEL(msm_host->channel) |
+			DSI_CMD_MDP_STREAM0_CTRL_DATA_TYPE(MIPI_DSI_DCS_LONG_WRITE);
 
-		dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_CTRL,
-			DSI_CMD_MDP_STREAM0_CTRL_WORD_COUNT(wc) |
-			DSI_CMD_MDP_STREAM0_CTRL_VIRTUAL_CHANNEL(
-					msm_host->channel) |
-			DSI_CMD_MDP_STREAM0_CTRL_DATA_TYPE(
-					MIPI_DSI_DCS_LONG_WRITE));
+		dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_CTRL, data);
 
-		dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_TOTAL,
-			DSI_CMD_MDP_STREAM0_TOTAL_H_TOTAL(hdisplay) |
-			DSI_CMD_MDP_STREAM0_TOTAL_V_TOTAL(mode->vdisplay));
+		data = DSI_CMD_MDP_STREAM0_TOTAL_H_TOTAL(hdisplay) |
+			DSI_CMD_MDP_STREAM0_TOTAL_V_TOTAL(mode->vdisplay);
+		dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_TOTAL, data);
 	}
 }
 
@@ -2111,6 +2205,7 @@ int msm_dsi_host_modeset_init(struct mipi_dsi_host *host,
 	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 	const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
 	struct platform_device *pdev = msm_host->pdev;
+	struct msm_drm_private *priv;
 	int ret;
 
 	msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
@@ -2130,6 +2225,9 @@ int msm_dsi_host_modeset_init(struct mipi_dsi_host *host,
 	}
 
 	msm_host->dev = dev;
+	priv = dev->dev_private;
+	priv->dsc = msm_host->dsc;
+
 	ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K);
 	if (ret) {
 		pr_err("%s: alloc tx gem obj failed, %d\n", __func__, ret);
-- 
2.26.3


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

* [RFC PATCH 12/13] drm/msm/dsi: Add support for DSC configuration
@ 2021-05-21 12:49   ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, Vinod Koul, dri-devel,
	Dmitry Baryshkov, freedreno

When DSC is enabled, we need to configure DSI registers accordingly and
configure the respective stream compression registers.

Add support to calculate the register setting based on DSC params and
timing information and configure these registers.

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/dsi/dsi.xml.h  |  10 +++
 drivers/gpu/drm/msm/dsi/dsi_host.c | 118 ++++++++++++++++++++++++++---
 2 files changed, 118 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h b/drivers/gpu/drm/msm/dsi/dsi.xml.h
index 50eb4d1b8fdd..b8e9e608abfc 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
@@ -2310,4 +2310,14 @@ static inline uint32_t REG_DSI_7nm_PHY_LN_TX_DCTRL(uint32_t i0) { return 0x00000
 
 #define REG_DSI_7nm_PHY_PLL_PERF_OPTIMIZE			0x00000260
 
+#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL			0x0000029c
+
+#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL2			0x000002a0
+
+#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL			0x000002a4
+
+#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2			0x000002a8
+
+#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL3			0x000002ac
+
 #endif /* DSI_XML */
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 864d3c655e73..e26545fc82e0 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -954,6 +954,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi)
 	u32 va_end = va_start + mode->vdisplay;
 	u32 hdisplay = mode->hdisplay;
 	u32 wc;
+	u32 data;
 
 	DBG("");
 
@@ -972,7 +973,69 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi)
 		hdisplay /= 2;
 	}
 
+	if (msm_host->dsc) {
+		struct msm_display_dsc_config *dsc = msm_host->dsc;
+
+		/* update dsc params with timing params */
+		dsc->drm.pic_width = mode->hdisplay;
+		dsc->drm.pic_height = mode->vdisplay;
+
+		/* Divide the display by 3 but keep back/font porch and
+		 * pulse width same
+		 */
+		h_total -= hdisplay;
+		hdisplay /= 3;
+		h_total += hdisplay;
+		ha_end = ha_start + hdisplay;
+	}
+
 	if (msm_host->mode_flags & MIPI_DSI_MODE_VIDEO) {
+		if (msm_host->dsc) {
+			struct msm_display_dsc_config *dsc = msm_host->dsc;
+			u32 reg, intf_width, slice_per_intf, width;
+			u32 total_bytes_per_intf;
+
+			/* first calculate dsc parameters and then program
+			 * compress mode registers
+			 */
+			intf_width = hdisplay;
+			slice_per_intf = DIV_ROUND_UP(intf_width, dsc->drm.slice_width);
+
+			/* If slice_per_pkt > slice_per_intf, then use 1
+			 * This can happen during partial update
+			 */
+			if (dsc->slice_per_pkt > slice_per_intf)
+				dsc->slice_per_pkt = 1;
+
+			dsc->bytes_in_slice = DIV_ROUND_UP(dsc->drm.slice_width * 8, 8);
+			total_bytes_per_intf = dsc->bytes_in_slice * slice_per_intf;
+
+			dsc->eol_byte_num = total_bytes_per_intf % 3;
+			dsc->pclk_per_line =  DIV_ROUND_UP(total_bytes_per_intf, 3);
+			dsc->bytes_per_pkt = dsc->bytes_in_slice * dsc->slice_per_pkt;
+			dsc->pkt_per_line = slice_per_intf / dsc->slice_per_pkt;
+
+			width = dsc->pclk_per_line;
+			reg = dsc->bytes_per_pkt << 16;
+			reg |= (0x0b << 8);    /* dtype of compressed image */
+
+			/* pkt_per_line:
+			 * 0 == 1 pkt
+			 * 1 == 2 pkt
+			 * 2 == 4 pkt
+			 * 3 pkt is not supported
+			 * above translates to ffs() - 1
+			 */
+			reg |= (ffs(dsc->pkt_per_line) - 1) << 6;
+
+			dsc->eol_byte_num = total_bytes_per_intf % 3;
+			reg |= dsc->eol_byte_num << 4;
+			reg |= 1;
+
+			dsi_write(msm_host,
+				  REG_DSI_VIDEO_COMPRESSION_MODE_CTRL, reg);
+		}
+
 		dsi_write(msm_host, REG_DSI_ACTIVE_H,
 			DSI_ACTIVE_H_START(ha_start) |
 			DSI_ACTIVE_H_END(ha_end));
@@ -991,19 +1054,50 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_dual_dsi)
 			DSI_ACTIVE_VSYNC_VPOS_START(vs_start) |
 			DSI_ACTIVE_VSYNC_VPOS_END(vs_end));
 	} else {		/* command mode */
+		if (msm_host->dsc) {
+			struct msm_display_dsc_config *dsc = msm_host->dsc;
+			u32 reg, reg_ctrl, reg_ctrl2;
+			u32 slice_per_intf, bytes_in_slice, total_bytes_per_intf;
+
+			reg_ctrl = dsi_read(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL);
+			reg_ctrl2 = dsi_read(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2);
+
+			slice_per_intf = DIV_ROUND_UP(hdisplay, dsc->drm.slice_width);
+			bytes_in_slice = DIV_ROUND_UP(dsc->drm.slice_width *
+						      dsc->drm.bits_per_pixel, 8);
+			dsc->drm.slice_chunk_size = bytes_in_slice;
+			total_bytes_per_intf = dsc->bytes_in_slice * slice_per_intf;
+			dsc->pkt_per_line = slice_per_intf / dsc->slice_per_pkt;
+
+			reg = 0x39 << 8;
+			reg |= ffs(dsc->pkt_per_line) << 6;
+
+			dsc->eol_byte_num = total_bytes_per_intf % 3;
+			reg |= dsc->eol_byte_num << 4;
+			reg |= 1;
+
+			reg_ctrl |= reg;
+			reg_ctrl2 |= bytes_in_slice;
+
+			dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL, reg);
+			dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2, reg_ctrl2);
+		}
+
 		/* image data and 1 byte write_memory_start cmd */
-		wc = hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1;
+		if (!msm_host->dsc)
+			wc = hdisplay * dsi_get_bpp(msm_host->format) / 8 + 1;
+		else
+			wc = mode->hdisplay / 2 + 1;
+
+		data = DSI_CMD_MDP_STREAM0_CTRL_WORD_COUNT(wc) |
+		       DSI_CMD_MDP_STREAM0_CTRL_VIRTUAL_CHANNEL(msm_host->channel) |
+			DSI_CMD_MDP_STREAM0_CTRL_DATA_TYPE(MIPI_DSI_DCS_LONG_WRITE);
 
-		dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_CTRL,
-			DSI_CMD_MDP_STREAM0_CTRL_WORD_COUNT(wc) |
-			DSI_CMD_MDP_STREAM0_CTRL_VIRTUAL_CHANNEL(
-					msm_host->channel) |
-			DSI_CMD_MDP_STREAM0_CTRL_DATA_TYPE(
-					MIPI_DSI_DCS_LONG_WRITE));
+		dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_CTRL, data);
 
-		dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_TOTAL,
-			DSI_CMD_MDP_STREAM0_TOTAL_H_TOTAL(hdisplay) |
-			DSI_CMD_MDP_STREAM0_TOTAL_V_TOTAL(mode->vdisplay));
+		data = DSI_CMD_MDP_STREAM0_TOTAL_H_TOTAL(hdisplay) |
+			DSI_CMD_MDP_STREAM0_TOTAL_V_TOTAL(mode->vdisplay);
+		dsi_write(msm_host, REG_DSI_CMD_MDP_STREAM0_TOTAL, data);
 	}
 }
 
@@ -2111,6 +2205,7 @@ int msm_dsi_host_modeset_init(struct mipi_dsi_host *host,
 	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 	const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
 	struct platform_device *pdev = msm_host->pdev;
+	struct msm_drm_private *priv;
 	int ret;
 
 	msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
@@ -2130,6 +2225,9 @@ int msm_dsi_host_modeset_init(struct mipi_dsi_host *host,
 	}
 
 	msm_host->dev = dev;
+	priv = dev->dev_private;
+	priv->dsc = msm_host->dsc;
+
 	ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K);
 	if (ret) {
 		pr_err("%s: alloc tx gem obj failed, %d\n", __func__, ret);
-- 
2.26.3


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

* [RFC PATCH 13/13] drm/msm/dsi: Pass DSC params to drm_panel
  2021-05-21 12:49 ` Vinod Koul
@ 2021-05-21 12:49   ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, Vinod Koul, David Airlie,
	Daniel Vetter, Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar,
	linux-kernel, dri-devel, freedreno

When DSC is enabled, we need to pass the DSC parameters to panel driver
as well, so add a dsc parameter in panel and set it when DSC is enabled

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 5 +++++
 include/drm/drm_panel.h            | 7 +++++++
 2 files changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index e26545fc82e0..7fc7002eda78 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1700,6 +1700,7 @@ static int dsi_host_attach(struct mipi_dsi_host *host,
 					struct mipi_dsi_device *dsi)
 {
 	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+	struct drm_panel *panel;
 	int ret;
 
 	if (dsi->lanes > msm_host->num_data_lanes)
@@ -1719,6 +1720,10 @@ static int dsi_host_attach(struct mipi_dsi_host *host,
 	if (msm_host->dev)
 		queue_work(msm_host->workqueue, &msm_host->hpd_work);
 
+	panel = msm_dsi_host_get_panel(host);
+	if (panel)
+		panel->dsc = &msm_host->dsc->drm;
+
 	return 0;
 }
 
diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h
index 33605c3f0eba..27a7808a29f2 100644
--- a/include/drm/drm_panel.h
+++ b/include/drm/drm_panel.h
@@ -171,6 +171,13 @@ struct drm_panel {
 	 * Panel entry in registry.
 	 */
 	struct list_head list;
+
+	/**
+	 * @dsc:
+	 *
+	 * Panel DSC pps payload to be sent
+	 */
+	struct drm_dsc_config *dsc;
 };
 
 void drm_panel_init(struct drm_panel *panel, struct device *dev,
-- 
2.26.3


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

* [RFC PATCH 13/13] drm/msm/dsi: Pass DSC params to drm_panel
@ 2021-05-21 12:49   ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 12:49 UTC (permalink / raw)
  To: Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, Vinod Koul, dri-devel,
	Dmitry Baryshkov, freedreno

When DSC is enabled, we need to pass the DSC parameters to panel driver
as well, so add a dsc parameter in panel and set it when DSC is enabled

Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 5 +++++
 include/drm/drm_panel.h            | 7 +++++++
 2 files changed, 12 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index e26545fc82e0..7fc7002eda78 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1700,6 +1700,7 @@ static int dsi_host_attach(struct mipi_dsi_host *host,
 					struct mipi_dsi_device *dsi)
 {
 	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+	struct drm_panel *panel;
 	int ret;
 
 	if (dsi->lanes > msm_host->num_data_lanes)
@@ -1719,6 +1720,10 @@ static int dsi_host_attach(struct mipi_dsi_host *host,
 	if (msm_host->dev)
 		queue_work(msm_host->workqueue, &msm_host->hpd_work);
 
+	panel = msm_dsi_host_get_panel(host);
+	if (panel)
+		panel->dsc = &msm_host->dsc->drm;
+
 	return 0;
 }
 
diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h
index 33605c3f0eba..27a7808a29f2 100644
--- a/include/drm/drm_panel.h
+++ b/include/drm/drm_panel.h
@@ -171,6 +171,13 @@ struct drm_panel {
 	 * Panel entry in registry.
 	 */
 	struct list_head list;
+
+	/**
+	 * @dsc:
+	 *
+	 * Panel DSC pps payload to be sent
+	 */
+	struct drm_dsc_config *dsc;
 };
 
 void drm_panel_init(struct drm_panel *panel, struct device *dev,
-- 
2.26.3


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

* Re: [RFC PATCH 02/13] dt-bindings: msm/dsi: Document Display Stream Compression (DSC) parameters
  2021-05-21 12:49   ` Vinod Koul
@ 2021-05-21 13:18     ` Rob Herring
  -1 siblings, 0 replies; 91+ messages in thread
From: Rob Herring @ 2021-05-21 13:18 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Rob Clark, linux-arm-msm, Bjorn Andersson, David Airlie,
	Daniel Vetter, Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar,
	linux-kernel, dri-devel, freedreno, devicetree

On Fri, May 21, 2021 at 7:50 AM Vinod Koul <vkoul@kernel.org> wrote:
>
> DSC enables streams to be compressed before we send to panel. This
> requires DSC enabled encoder and a panel to be present. So we add this
> information in board DTS and find if DSC can be enabled and the
> parameters required to configure DSC are added to binding document along
> with example
>
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>  .../devicetree/bindings/display/msm/dsi.txt       | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)

This is getting converted to schema. Hopefully, v17 will be it. Sigh.

Rob

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

* Re: [RFC PATCH 02/13] dt-bindings: msm/dsi: Document Display Stream Compression (DSC) parameters
@ 2021-05-21 13:18     ` Rob Herring
  0 siblings, 0 replies; 91+ messages in thread
From: Rob Herring @ 2021-05-21 13:18 UTC (permalink / raw)
  To: Vinod Koul
  Cc: devicetree, Jonathan Marek, David Airlie, linux-arm-msm,
	linux-kernel, Abhinav Kumar, Bjorn Andersson, dri-devel,
	Dmitry Baryshkov, freedreno

On Fri, May 21, 2021 at 7:50 AM Vinod Koul <vkoul@kernel.org> wrote:
>
> DSC enables streams to be compressed before we send to panel. This
> requires DSC enabled encoder and a panel to be present. So we add this
> information in board DTS and find if DSC can be enabled and the
> parameters required to configure DSC are added to binding document along
> with example
>
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>  .../devicetree/bindings/display/msm/dsi.txt       | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)

This is getting converted to schema. Hopefully, v17 will be it. Sigh.

Rob

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

* Re: [RFC PATCH 02/13] dt-bindings: msm/dsi: Document Display Stream Compression (DSC) parameters
  2021-05-21 13:18     ` Rob Herring
@ 2021-05-21 13:23       ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 13:23 UTC (permalink / raw)
  To: Rob Herring
  Cc: Rob Clark, linux-arm-msm, Bjorn Andersson, David Airlie,
	Daniel Vetter, Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar,
	linux-kernel, dri-devel, freedreno, devicetree

On 21-05-21, 08:18, Rob Herring wrote:
> On Fri, May 21, 2021 at 7:50 AM Vinod Koul <vkoul@kernel.org> wrote:
> >
> > DSC enables streams to be compressed before we send to panel. This
> > requires DSC enabled encoder and a panel to be present. So we add this
> > information in board DTS and find if DSC can be enabled and the
> > parameters required to configure DSC are added to binding document along
> > with example
> >
> > Signed-off-by: Vinod Koul <vkoul@kernel.org>
> > ---
> >  .../devicetree/bindings/display/msm/dsi.txt       | 15 +++++++++++++++
> >  1 file changed, 15 insertions(+)
> 
> This is getting converted to schema. Hopefully, v17 will be it. Sigh.

I will update these on top, whenever that one gets merged... Any comments
on the parameters added here?

-- 
~Vinod

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

* Re: [RFC PATCH 02/13] dt-bindings: msm/dsi: Document Display Stream Compression (DSC) parameters
@ 2021-05-21 13:23       ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-21 13:23 UTC (permalink / raw)
  To: Rob Herring
  Cc: devicetree, Jonathan Marek, David Airlie, linux-arm-msm,
	linux-kernel, Abhinav Kumar, Bjorn Andersson, dri-devel,
	Dmitry Baryshkov, freedreno

On 21-05-21, 08:18, Rob Herring wrote:
> On Fri, May 21, 2021 at 7:50 AM Vinod Koul <vkoul@kernel.org> wrote:
> >
> > DSC enables streams to be compressed before we send to panel. This
> > requires DSC enabled encoder and a panel to be present. So we add this
> > information in board DTS and find if DSC can be enabled and the
> > parameters required to configure DSC are added to binding document along
> > with example
> >
> > Signed-off-by: Vinod Koul <vkoul@kernel.org>
> > ---
> >  .../devicetree/bindings/display/msm/dsi.txt       | 15 +++++++++++++++
> >  1 file changed, 15 insertions(+)
> 
> This is getting converted to schema. Hopefully, v17 will be it. Sigh.

I will update these on top, whenever that one gets merged... Any comments
on the parameters added here?

-- 
~Vinod

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

* Re: [Freedreno] [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support
  2021-05-21 12:49 ` Vinod Koul
@ 2021-05-21 14:09   ` Jeffrey Hugo
  -1 siblings, 0 replies; 91+ messages in thread
From: Jeffrey Hugo @ 2021-05-21 14:09 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Rob Clark, DTML, Jonathan Marek, David Airlie, MSM, lkml,
	Abhinav Kumar, Bjorn Andersson, Rob Herring,
	open list:DRM PANEL DRIVERS, Daniel Vetter, Dmitry Baryshkov,
	freedreno

On Fri, May 21, 2021 at 6:50 AM Vinod Koul <vkoul@kernel.org> wrote:
>
> Display Stream Compression (DSC) compresses the display stream in host which
> is later decoded by panel. This series enables this for Qualcomm msm driver.
> This was tested on Google Pixel3 phone which use LGE SW43408 panel.
>
> The changes include adding DT properties for DSC then hardware blocks support
> required in DPU1 driver and support in encoder. We also add support in DSI
> and introduce required topology changes.
>
> In order for panel to set the DSC parameters we add dsc in drm_panel and set
> it from the msm driver.
>
> Complete changes which enable this for Pixel3 along with panel driver (not
> part of this series) and DT changes can be found at:
> git.linaro.org/people/vinod.koul/kernel.git pixel/dsc_rfc
>
> Comments welcome!

This feels backwards to me.  I've only skimmed this series, and the DT
changes didn't come through for me, so perhaps I have an incomplete
view.

DSC is not MSM specific.  There is a standard for it.  Yet it looks
like everything is implemented in a MSM specific way, and then pushed
to the panel.  So, every vendor needs to implement their vendor
specific way to get the DSC info, and then push it to the panel?
Seems wrong, given there is an actual standard for this feature.

Additionally, we define panel properties (resolution, BPP, etc) at the
panel, and have the display drivers pull it from the panel.  However,
for DSC, you do the reverse (define it in the display driver, and push
it to the panel).  If the argument is that DSC properties can be
dynamic, well, so can resolution.  Every panel for MSM MTPs supports
multiple resolutions, yet we define that with the panel in Linux.

Finally, I haven't seen the DT bits, but I'm concerned about using DT
for this.  It inherently excludes ACPI systems.  You appear to have
sdm845 support in this series, but what about ACPI boot on the Lenovo
C630 for example?  Or any of the 8cx laptops?  We don't read the panel
resolution, etc from DT, so why the DSC?

I'm glad that work is being done to add DSC to Linux, it's something I
struggled with when working on the 8998 mtp, and I realize this is a
bit of a drive-by review.  However, it seems like there should be a
better way.

>
> Vinod Koul (13):
>   drm/dsc: Add dsc pps header init function
>   dt-bindings: msm/dsi: Document Display Stream Compression (DSC)
>     parameters
>   drm/msm/dsi: add support for dsc data
>   drm/msm/disp/dpu1: Add support for DSC
>   drm/msm/disp/dpu1: Add support for DSC in pingpong block
>   drm/msm/disp/dpu1: Add DSC support in RM
>   drm/msm/disp/dpu1: Add DSC for SDM845 to hw_catalog
>   drm/msm/disp/dpu1: Add DSC support in hw_ctl
>   drm/msm/disp/dpu1: Don't use DSC with mode_3d
>   drm/msm/disp/dpu1: Add support for DSC in encoder
>   drm/msm/disp/dpu1: Add support for DSC in topology
>   drm/msm/dsi: Add support for DSC configuration
>   drm/msm/dsi: Pass DSC params to drm_panel
>
>  .../devicetree/bindings/display/msm/dsi.txt   |  15 +
>  drivers/gpu/drm/drm_dsc.c                     |  11 +
>  drivers/gpu/drm/msm/Makefile                  |   1 +
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 204 +++++++++++-
>  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  11 +
>  .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c  |   2 +
>  .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c    |  22 ++
>  .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |  26 ++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c    |  12 +-
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h    |   2 +
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c    | 221 +++++++++++++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h    |  79 +++++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 +
>  .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   |  32 ++
>  .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   |  14 +
>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h       |   1 +
>  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c        |  32 ++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h        |   1 +
>  drivers/gpu/drm/msm/dsi/dsi.xml.h             |  10 +
>  drivers/gpu/drm/msm/dsi/dsi_host.c            | 293 +++++++++++++++++-
>  drivers/gpu/drm/msm/msm_drv.h                 |  32 ++
>  include/drm/drm_dsc.h                         |  16 +
>  include/drm/drm_panel.h                       |   7 +
>  23 files changed, 1043 insertions(+), 14 deletions(-)
>  create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
>  create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
>
> --
> 2.26.3
>
> _______________________________________________
> Freedreno mailing list
> Freedreno@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/freedreno

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

* Re: [Freedreno] [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support
@ 2021-05-21 14:09   ` Jeffrey Hugo
  0 siblings, 0 replies; 91+ messages in thread
From: Jeffrey Hugo @ 2021-05-21 14:09 UTC (permalink / raw)
  To: Vinod Koul
  Cc: DTML, Jonathan Marek, David Airlie, MSM, lkml, Abhinav Kumar,
	Bjorn Andersson, Rob Herring, open list:DRM PANEL DRIVERS,
	Dmitry Baryshkov, freedreno

On Fri, May 21, 2021 at 6:50 AM Vinod Koul <vkoul@kernel.org> wrote:
>
> Display Stream Compression (DSC) compresses the display stream in host which
> is later decoded by panel. This series enables this for Qualcomm msm driver.
> This was tested on Google Pixel3 phone which use LGE SW43408 panel.
>
> The changes include adding DT properties for DSC then hardware blocks support
> required in DPU1 driver and support in encoder. We also add support in DSI
> and introduce required topology changes.
>
> In order for panel to set the DSC parameters we add dsc in drm_panel and set
> it from the msm driver.
>
> Complete changes which enable this for Pixel3 along with panel driver (not
> part of this series) and DT changes can be found at:
> git.linaro.org/people/vinod.koul/kernel.git pixel/dsc_rfc
>
> Comments welcome!

This feels backwards to me.  I've only skimmed this series, and the DT
changes didn't come through for me, so perhaps I have an incomplete
view.

DSC is not MSM specific.  There is a standard for it.  Yet it looks
like everything is implemented in a MSM specific way, and then pushed
to the panel.  So, every vendor needs to implement their vendor
specific way to get the DSC info, and then push it to the panel?
Seems wrong, given there is an actual standard for this feature.

Additionally, we define panel properties (resolution, BPP, etc) at the
panel, and have the display drivers pull it from the panel.  However,
for DSC, you do the reverse (define it in the display driver, and push
it to the panel).  If the argument is that DSC properties can be
dynamic, well, so can resolution.  Every panel for MSM MTPs supports
multiple resolutions, yet we define that with the panel in Linux.

Finally, I haven't seen the DT bits, but I'm concerned about using DT
for this.  It inherently excludes ACPI systems.  You appear to have
sdm845 support in this series, but what about ACPI boot on the Lenovo
C630 for example?  Or any of the 8cx laptops?  We don't read the panel
resolution, etc from DT, so why the DSC?

I'm glad that work is being done to add DSC to Linux, it's something I
struggled with when working on the 8998 mtp, and I realize this is a
bit of a drive-by review.  However, it seems like there should be a
better way.

>
> Vinod Koul (13):
>   drm/dsc: Add dsc pps header init function
>   dt-bindings: msm/dsi: Document Display Stream Compression (DSC)
>     parameters
>   drm/msm/dsi: add support for dsc data
>   drm/msm/disp/dpu1: Add support for DSC
>   drm/msm/disp/dpu1: Add support for DSC in pingpong block
>   drm/msm/disp/dpu1: Add DSC support in RM
>   drm/msm/disp/dpu1: Add DSC for SDM845 to hw_catalog
>   drm/msm/disp/dpu1: Add DSC support in hw_ctl
>   drm/msm/disp/dpu1: Don't use DSC with mode_3d
>   drm/msm/disp/dpu1: Add support for DSC in encoder
>   drm/msm/disp/dpu1: Add support for DSC in topology
>   drm/msm/dsi: Add support for DSC configuration
>   drm/msm/dsi: Pass DSC params to drm_panel
>
>  .../devicetree/bindings/display/msm/dsi.txt   |  15 +
>  drivers/gpu/drm/drm_dsc.c                     |  11 +
>  drivers/gpu/drm/msm/Makefile                  |   1 +
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 204 +++++++++++-
>  .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  11 +
>  .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c  |   2 +
>  .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c    |  22 ++
>  .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |  26 ++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c    |  12 +-
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h    |   2 +
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c    | 221 +++++++++++++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h    |  79 +++++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 +
>  .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   |  32 ++
>  .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   |  14 +
>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h       |   1 +
>  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c        |  32 ++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h        |   1 +
>  drivers/gpu/drm/msm/dsi/dsi.xml.h             |  10 +
>  drivers/gpu/drm/msm/dsi/dsi_host.c            | 293 +++++++++++++++++-
>  drivers/gpu/drm/msm/msm_drv.h                 |  32 ++
>  include/drm/drm_dsc.h                         |  16 +
>  include/drm/drm_panel.h                       |   7 +
>  23 files changed, 1043 insertions(+), 14 deletions(-)
>  create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
>  create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
>
> --
> 2.26.3
>
> _______________________________________________
> Freedreno mailing list
> Freedreno@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/freedreno

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

* Re: [RFC PATCH 02/13] dt-bindings: msm/dsi: Document Display Stream Compression (DSC) parameters
  2021-05-21 12:49   ` Vinod Koul
@ 2021-05-21 14:42     ` Bjorn Andersson
  -1 siblings, 0 replies; 91+ messages in thread
From: Bjorn Andersson @ 2021-05-21 14:42 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Rob Clark, linux-arm-msm, David Airlie, Daniel Vetter,
	Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar, linux-kernel,
	dri-devel, freedreno, Rob Herring, devicetree

On Fri 21 May 07:49 CDT 2021, Vinod Koul wrote:

> DSC enables streams to be compressed before we send to panel. This
> requires DSC enabled encoder and a panel to be present. So we add this
> information in board DTS and find if DSC can be enabled and the
> parameters required to configure DSC are added to binding document along
> with example
> 
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>  .../devicetree/bindings/display/msm/dsi.txt       | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/display/msm/dsi.txt b/Documentation/devicetree/bindings/display/msm/dsi.txt
> index b9a64d3ff184..83d2fb92267e 100644
> --- a/Documentation/devicetree/bindings/display/msm/dsi.txt
> +++ b/Documentation/devicetree/bindings/display/msm/dsi.txt
> @@ -48,6 +48,13 @@ Optional properties:
>  - pinctrl-n: the "sleep" pinctrl state
>  - ports: contains DSI controller input and output ports as children, each
>    containing one endpoint subnode.
> +- qcom,mdss-dsc-enabled: Display Stream Compression (DSC) is enabled
> +- qcom,mdss-slice-height: DSC slice height in pixels
> +- qcom,mdss-slice-width: DSC slice width in pixels
> +- qcom,mdss-slice-per-pkt: DSC slices per packet
> +- qcom,mdss-bit-per-component: DSC bits per component
> +- qcom,mdss-bit-per-pixel: DSC bits per pixel
> +- qcom,mdss-block-prediction-enable: Block prediction mode of DSC enabled
>  
>    DSI Endpoint properties:
>    - remote-endpoint: For port@0, set to phandle of the connected panel/bridge's
> @@ -188,6 +195,14 @@ Example:
>  		qcom,master-dsi;
>  		qcom,sync-dual-dsi;
>  
> +		qcom,mdss-dsc-enabled;

To me the activation of DSC seems to be a property of the panel.

> +		qcom,mdss-slice-height = <16>;
> +		qcom,mdss-slice-width = <540>;
> +		qcom,mdss-slice-per-pkt = <1>;
> +		qcom,mdss-bit-per-component = <8>;
> +		qcom,mdss-bit-per-pixel = <8>;
> +		qcom,mdss-block-prediction-enable;

Which of these properties relates to the DSC encoder and what needs to
be agreed with the sink? Can't we derive e.g. bpp from the information
we have from the attached panel already?

Regards,
Bjorn

> +
>  		qcom,mdss-mdp-transfer-time-us = <12000>;
>  
>  		pinctrl-names = "default", "sleep";
> -- 
> 2.26.3
> 

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

* Re: [RFC PATCH 02/13] dt-bindings: msm/dsi: Document Display Stream Compression (DSC) parameters
@ 2021-05-21 14:42     ` Bjorn Andersson
  0 siblings, 0 replies; 91+ messages in thread
From: Bjorn Andersson @ 2021-05-21 14:42 UTC (permalink / raw)
  To: Vinod Koul
  Cc: devicetree, Jonathan Marek, David Airlie, linux-arm-msm,
	linux-kernel, Abhinav Kumar, Rob Herring, dri-devel,
	Dmitry Baryshkov, freedreno

On Fri 21 May 07:49 CDT 2021, Vinod Koul wrote:

> DSC enables streams to be compressed before we send to panel. This
> requires DSC enabled encoder and a panel to be present. So we add this
> information in board DTS and find if DSC can be enabled and the
> parameters required to configure DSC are added to binding document along
> with example
> 
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>  .../devicetree/bindings/display/msm/dsi.txt       | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/display/msm/dsi.txt b/Documentation/devicetree/bindings/display/msm/dsi.txt
> index b9a64d3ff184..83d2fb92267e 100644
> --- a/Documentation/devicetree/bindings/display/msm/dsi.txt
> +++ b/Documentation/devicetree/bindings/display/msm/dsi.txt
> @@ -48,6 +48,13 @@ Optional properties:
>  - pinctrl-n: the "sleep" pinctrl state
>  - ports: contains DSI controller input and output ports as children, each
>    containing one endpoint subnode.
> +- qcom,mdss-dsc-enabled: Display Stream Compression (DSC) is enabled
> +- qcom,mdss-slice-height: DSC slice height in pixels
> +- qcom,mdss-slice-width: DSC slice width in pixels
> +- qcom,mdss-slice-per-pkt: DSC slices per packet
> +- qcom,mdss-bit-per-component: DSC bits per component
> +- qcom,mdss-bit-per-pixel: DSC bits per pixel
> +- qcom,mdss-block-prediction-enable: Block prediction mode of DSC enabled
>  
>    DSI Endpoint properties:
>    - remote-endpoint: For port@0, set to phandle of the connected panel/bridge's
> @@ -188,6 +195,14 @@ Example:
>  		qcom,master-dsi;
>  		qcom,sync-dual-dsi;
>  
> +		qcom,mdss-dsc-enabled;

To me the activation of DSC seems to be a property of the panel.

> +		qcom,mdss-slice-height = <16>;
> +		qcom,mdss-slice-width = <540>;
> +		qcom,mdss-slice-per-pkt = <1>;
> +		qcom,mdss-bit-per-component = <8>;
> +		qcom,mdss-bit-per-pixel = <8>;
> +		qcom,mdss-block-prediction-enable;

Which of these properties relates to the DSC encoder and what needs to
be agreed with the sink? Can't we derive e.g. bpp from the information
we have from the attached panel already?

Regards,
Bjorn

> +
>  		qcom,mdss-mdp-transfer-time-us = <12000>;
>  
>  		pinctrl-names = "default", "sleep";
> -- 
> 2.26.3
> 

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

* Re: [RFC PATCH 01/13] drm/dsc: Add dsc pps header init function
  2021-05-21 12:49   ` Vinod Koul
@ 2021-05-21 15:29     ` Daniel Vetter
  -1 siblings, 0 replies; 91+ messages in thread
From: Daniel Vetter @ 2021-05-21 15:29 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Rob Clark, linux-arm-msm, Bjorn Andersson, David Airlie,
	Daniel Vetter, Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar,
	linux-kernel, dri-devel, freedreno

On Fri, May 21, 2021 at 06:19:30PM +0530, Vinod Koul wrote:
> We required a helper to create and set the dsc_dce_header, so add the
> dsc_dce_header and API drm_dsc_dsi_pps_header_init
> 
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>  drivers/gpu/drm/drm_dsc.c | 11 +++++++++++
>  include/drm/drm_dsc.h     | 16 ++++++++++++++++
>  2 files changed, 27 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_dsc.c b/drivers/gpu/drm/drm_dsc.c
> index ff602f7ec65b..0c1b745090e2 100644
> --- a/drivers/gpu/drm/drm_dsc.c
> +++ b/drivers/gpu/drm/drm_dsc.c
> @@ -49,6 +49,17 @@ void drm_dsc_dp_pps_header_init(struct dp_sdp_header *pps_header)
>  }
>  EXPORT_SYMBOL(drm_dsc_dp_pps_header_init);
>  
> +void drm_dsc_dsi_pps_header_init(struct dsc_dce_header *dsc_header)

Kerneldoc for anything exported to drivers please, also ideally for all
the structures.

Thanks, Daniel
> +{
> +	memset(dsc_header, 0, sizeof(*dsc_header));
> +
> +	dsc_header->bp0 = 0x0A;
> +	dsc_header->bp1 = 1;
> +	dsc_header->bp4 = 10;
> +	dsc_header->bp6 = 128;
> +}
> +EXPORT_SYMBOL(drm_dsc_dsi_pps_header_init);
> +
>  /**
>   * drm_dsc_dp_rc_buffer_size - get rc buffer size in bytes
>   * @rc_buffer_block_size: block size code, according to DPCD offset 62h
> diff --git a/include/drm/drm_dsc.h b/include/drm/drm_dsc.h
> index bbe120f461e5..5a3bbeb3e12f 100644
> --- a/include/drm/drm_dsc.h
> +++ b/include/drm/drm_dsc.h
> @@ -602,8 +602,24 @@ struct drm_dsc_pps_infoframe {
>  	struct drm_dsc_picture_parameter_set pps_payload;
>  } __packed;
>  
> +struct dsc_dce_header {
> +	u8 bp0;
> +	u8 bp1;
> +	u8 bp2;
> +	u8 bp3;
> +	u8 bp4;
> +	u8 bp5;
> +	u8 bp6;
> +} __packed;
> +
> +struct drm_dsi_dsc_infoframe {
> +	struct dsc_dce_header dsc_header;
> +	struct drm_dsc_picture_parameter_set pps_payload;
> +} __packed;
> +
>  void drm_dsc_dp_pps_header_init(struct dp_sdp_header *pps_header);
>  int drm_dsc_dp_rc_buffer_size(u8 rc_buffer_block_size, u8 rc_buffer_size);
> +void drm_dsc_dsi_pps_header_init(struct dsc_dce_header *dsc_header);
>  void drm_dsc_pps_payload_pack(struct drm_dsc_picture_parameter_set *pps_sdp,
>  				const struct drm_dsc_config *dsc_cfg);
>  int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg);
> -- 
> 2.26.3
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

* Re: [RFC PATCH 01/13] drm/dsc: Add dsc pps header init function
@ 2021-05-21 15:29     ` Daniel Vetter
  0 siblings, 0 replies; 91+ messages in thread
From: Daniel Vetter @ 2021-05-21 15:29 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, dri-devel, Dmitry Baryshkov,
	freedreno

On Fri, May 21, 2021 at 06:19:30PM +0530, Vinod Koul wrote:
> We required a helper to create and set the dsc_dce_header, so add the
> dsc_dce_header and API drm_dsc_dsi_pps_header_init
> 
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>  drivers/gpu/drm/drm_dsc.c | 11 +++++++++++
>  include/drm/drm_dsc.h     | 16 ++++++++++++++++
>  2 files changed, 27 insertions(+)
> 
> diff --git a/drivers/gpu/drm/drm_dsc.c b/drivers/gpu/drm/drm_dsc.c
> index ff602f7ec65b..0c1b745090e2 100644
> --- a/drivers/gpu/drm/drm_dsc.c
> +++ b/drivers/gpu/drm/drm_dsc.c
> @@ -49,6 +49,17 @@ void drm_dsc_dp_pps_header_init(struct dp_sdp_header *pps_header)
>  }
>  EXPORT_SYMBOL(drm_dsc_dp_pps_header_init);
>  
> +void drm_dsc_dsi_pps_header_init(struct dsc_dce_header *dsc_header)

Kerneldoc for anything exported to drivers please, also ideally for all
the structures.

Thanks, Daniel
> +{
> +	memset(dsc_header, 0, sizeof(*dsc_header));
> +
> +	dsc_header->bp0 = 0x0A;
> +	dsc_header->bp1 = 1;
> +	dsc_header->bp4 = 10;
> +	dsc_header->bp6 = 128;
> +}
> +EXPORT_SYMBOL(drm_dsc_dsi_pps_header_init);
> +
>  /**
>   * drm_dsc_dp_rc_buffer_size - get rc buffer size in bytes
>   * @rc_buffer_block_size: block size code, according to DPCD offset 62h
> diff --git a/include/drm/drm_dsc.h b/include/drm/drm_dsc.h
> index bbe120f461e5..5a3bbeb3e12f 100644
> --- a/include/drm/drm_dsc.h
> +++ b/include/drm/drm_dsc.h
> @@ -602,8 +602,24 @@ struct drm_dsc_pps_infoframe {
>  	struct drm_dsc_picture_parameter_set pps_payload;
>  } __packed;
>  
> +struct dsc_dce_header {
> +	u8 bp0;
> +	u8 bp1;
> +	u8 bp2;
> +	u8 bp3;
> +	u8 bp4;
> +	u8 bp5;
> +	u8 bp6;
> +} __packed;
> +
> +struct drm_dsi_dsc_infoframe {
> +	struct dsc_dce_header dsc_header;
> +	struct drm_dsc_picture_parameter_set pps_payload;
> +} __packed;
> +
>  void drm_dsc_dp_pps_header_init(struct dp_sdp_header *pps_header);
>  int drm_dsc_dp_rc_buffer_size(u8 rc_buffer_block_size, u8 rc_buffer_size);
> +void drm_dsc_dsi_pps_header_init(struct dsc_dce_header *dsc_header);
>  void drm_dsc_pps_payload_pack(struct drm_dsc_picture_parameter_set *pps_sdp,
>  				const struct drm_dsc_config *dsc_cfg);
>  int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg);
> -- 
> 2.26.3
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

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

* Re: [RFC PATCH 01/13] drm/dsc: Add dsc pps header init function
  2021-05-21 15:29     ` Daniel Vetter
  (?)
@ 2021-05-24  7:26     ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-24  7:26 UTC (permalink / raw)
  To: Rob Clark, linux-arm-msm, Bjorn Andersson, David Airlie,
	Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar, linux-kernel,
	dri-devel, freedreno

On 21-05-21, 17:29, Daniel Vetter wrote:
> On Fri, May 21, 2021 at 06:19:30PM +0530, Vinod Koul wrote:
> > We required a helper to create and set the dsc_dce_header, so add the
> > dsc_dce_header and API drm_dsc_dsi_pps_header_init
> > 
> > Signed-off-by: Vinod Koul <vkoul@kernel.org>
> > ---
> >  drivers/gpu/drm/drm_dsc.c | 11 +++++++++++
> >  include/drm/drm_dsc.h     | 16 ++++++++++++++++
> >  2 files changed, 27 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/drm_dsc.c b/drivers/gpu/drm/drm_dsc.c
> > index ff602f7ec65b..0c1b745090e2 100644
> > --- a/drivers/gpu/drm/drm_dsc.c
> > +++ b/drivers/gpu/drm/drm_dsc.c
> > @@ -49,6 +49,17 @@ void drm_dsc_dp_pps_header_init(struct dp_sdp_header *pps_header)
> >  }
> >  EXPORT_SYMBOL(drm_dsc_dp_pps_header_init);
> >  
> > +void drm_dsc_dsi_pps_header_init(struct dsc_dce_header *dsc_header)
> 
> Kerneldoc for anything exported to drivers please, also ideally for all
> the structures.

Sorry missed that, will add

-- 
~Vinod

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

* Re: [RFC PATCH 02/13] dt-bindings: msm/dsi: Document Display Stream Compression (DSC) parameters
  2021-05-21 14:42     ` Bjorn Andersson
@ 2021-05-24  7:30       ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-24  7:30 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Rob Clark, linux-arm-msm, David Airlie, Daniel Vetter,
	Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar, linux-kernel,
	dri-devel, freedreno, Rob Herring, devicetree

On 21-05-21, 09:42, Bjorn Andersson wrote:
> On Fri 21 May 07:49 CDT 2021, Vinod Koul wrote:
> 
> > DSC enables streams to be compressed before we send to panel. This
> > requires DSC enabled encoder and a panel to be present. So we add this
> > information in board DTS and find if DSC can be enabled and the
> > parameters required to configure DSC are added to binding document along
> > with example
> > 
> > Signed-off-by: Vinod Koul <vkoul@kernel.org>
> > ---
> >  .../devicetree/bindings/display/msm/dsi.txt       | 15 +++++++++++++++
> >  1 file changed, 15 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/display/msm/dsi.txt b/Documentation/devicetree/bindings/display/msm/dsi.txt
> > index b9a64d3ff184..83d2fb92267e 100644
> > --- a/Documentation/devicetree/bindings/display/msm/dsi.txt
> > +++ b/Documentation/devicetree/bindings/display/msm/dsi.txt
> > @@ -48,6 +48,13 @@ Optional properties:
> >  - pinctrl-n: the "sleep" pinctrl state
> >  - ports: contains DSI controller input and output ports as children, each
> >    containing one endpoint subnode.
> > +- qcom,mdss-dsc-enabled: Display Stream Compression (DSC) is enabled
> > +- qcom,mdss-slice-height: DSC slice height in pixels
> > +- qcom,mdss-slice-width: DSC slice width in pixels
> > +- qcom,mdss-slice-per-pkt: DSC slices per packet
> > +- qcom,mdss-bit-per-component: DSC bits per component
> > +- qcom,mdss-bit-per-pixel: DSC bits per pixel
> > +- qcom,mdss-block-prediction-enable: Block prediction mode of DSC enabled
> >  
> >    DSI Endpoint properties:
> >    - remote-endpoint: For port@0, set to phandle of the connected panel/bridge's
> > @@ -188,6 +195,14 @@ Example:
> >  		qcom,master-dsi;
> >  		qcom,sync-dual-dsi;
> >  
> > +		qcom,mdss-dsc-enabled;
> 
> To me the activation of DSC seems to be a property of the panel.

I think there are three parts to the problem
1. Panel needs to support it
2. Host needs to support it
3. Someone needs to decide to use when both the above conditions are
met.

There are cases where above 1, 2 will be satisfied, but we might be okay
without DSC too.. so how to decide when to do DSC :)

I feel it is more of a system property. And I also think that these
parameters here are host configuration and not really for panel...

> 
> > +		qcom,mdss-slice-height = <16>;
> > +		qcom,mdss-slice-width = <540>;
> > +		qcom,mdss-slice-per-pkt = <1>;
> > +		qcom,mdss-bit-per-component = <8>;
> > +		qcom,mdss-bit-per-pixel = <8>;
> > +		qcom,mdss-block-prediction-enable;
> 
> Which of these properties relates to the DSC encoder and what needs to
> be agreed with the sink? Can't we derive e.g. bpp from the information
> we have from the attached panel already?

Let me go back and check on this a bit more

Thanks
-- 
~Vinod

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

* Re: [RFC PATCH 02/13] dt-bindings: msm/dsi: Document Display Stream Compression (DSC) parameters
@ 2021-05-24  7:30       ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-24  7:30 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: devicetree, Jonathan Marek, David Airlie, linux-arm-msm,
	linux-kernel, Abhinav Kumar, Rob Herring, dri-devel,
	Dmitry Baryshkov, freedreno

On 21-05-21, 09:42, Bjorn Andersson wrote:
> On Fri 21 May 07:49 CDT 2021, Vinod Koul wrote:
> 
> > DSC enables streams to be compressed before we send to panel. This
> > requires DSC enabled encoder and a panel to be present. So we add this
> > information in board DTS and find if DSC can be enabled and the
> > parameters required to configure DSC are added to binding document along
> > with example
> > 
> > Signed-off-by: Vinod Koul <vkoul@kernel.org>
> > ---
> >  .../devicetree/bindings/display/msm/dsi.txt       | 15 +++++++++++++++
> >  1 file changed, 15 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/display/msm/dsi.txt b/Documentation/devicetree/bindings/display/msm/dsi.txt
> > index b9a64d3ff184..83d2fb92267e 100644
> > --- a/Documentation/devicetree/bindings/display/msm/dsi.txt
> > +++ b/Documentation/devicetree/bindings/display/msm/dsi.txt
> > @@ -48,6 +48,13 @@ Optional properties:
> >  - pinctrl-n: the "sleep" pinctrl state
> >  - ports: contains DSI controller input and output ports as children, each
> >    containing one endpoint subnode.
> > +- qcom,mdss-dsc-enabled: Display Stream Compression (DSC) is enabled
> > +- qcom,mdss-slice-height: DSC slice height in pixels
> > +- qcom,mdss-slice-width: DSC slice width in pixels
> > +- qcom,mdss-slice-per-pkt: DSC slices per packet
> > +- qcom,mdss-bit-per-component: DSC bits per component
> > +- qcom,mdss-bit-per-pixel: DSC bits per pixel
> > +- qcom,mdss-block-prediction-enable: Block prediction mode of DSC enabled
> >  
> >    DSI Endpoint properties:
> >    - remote-endpoint: For port@0, set to phandle of the connected panel/bridge's
> > @@ -188,6 +195,14 @@ Example:
> >  		qcom,master-dsi;
> >  		qcom,sync-dual-dsi;
> >  
> > +		qcom,mdss-dsc-enabled;
> 
> To me the activation of DSC seems to be a property of the panel.

I think there are three parts to the problem
1. Panel needs to support it
2. Host needs to support it
3. Someone needs to decide to use when both the above conditions are
met.

There are cases where above 1, 2 will be satisfied, but we might be okay
without DSC too.. so how to decide when to do DSC :)

I feel it is more of a system property. And I also think that these
parameters here are host configuration and not really for panel...

> 
> > +		qcom,mdss-slice-height = <16>;
> > +		qcom,mdss-slice-width = <540>;
> > +		qcom,mdss-slice-per-pkt = <1>;
> > +		qcom,mdss-bit-per-component = <8>;
> > +		qcom,mdss-bit-per-pixel = <8>;
> > +		qcom,mdss-block-prediction-enable;
> 
> Which of these properties relates to the DSC encoder and what needs to
> be agreed with the sink? Can't we derive e.g. bpp from the information
> we have from the attached panel already?

Let me go back and check on this a bit more

Thanks
-- 
~Vinod

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

* Re: [RFC PATCH 02/13] dt-bindings: msm/dsi: Document Display Stream Compression (DSC) parameters
  2021-05-24  7:30       ` Vinod Koul
@ 2021-05-24 15:08         ` Bjorn Andersson
  -1 siblings, 0 replies; 91+ messages in thread
From: Bjorn Andersson @ 2021-05-24 15:08 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Rob Clark, linux-arm-msm, David Airlie, Daniel Vetter,
	Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar, linux-kernel,
	dri-devel, freedreno, Rob Herring, devicetree

On Mon 24 May 02:30 CDT 2021, Vinod Koul wrote:

> On 21-05-21, 09:42, Bjorn Andersson wrote:
> > On Fri 21 May 07:49 CDT 2021, Vinod Koul wrote:
> > 
> > > DSC enables streams to be compressed before we send to panel. This
> > > requires DSC enabled encoder and a panel to be present. So we add this
> > > information in board DTS and find if DSC can be enabled and the
> > > parameters required to configure DSC are added to binding document along
> > > with example
> > > 
> > > Signed-off-by: Vinod Koul <vkoul@kernel.org>
> > > ---
> > >  .../devicetree/bindings/display/msm/dsi.txt       | 15 +++++++++++++++
> > >  1 file changed, 15 insertions(+)
> > > 
> > > diff --git a/Documentation/devicetree/bindings/display/msm/dsi.txt b/Documentation/devicetree/bindings/display/msm/dsi.txt
> > > index b9a64d3ff184..83d2fb92267e 100644
> > > --- a/Documentation/devicetree/bindings/display/msm/dsi.txt
> > > +++ b/Documentation/devicetree/bindings/display/msm/dsi.txt
> > > @@ -48,6 +48,13 @@ Optional properties:
> > >  - pinctrl-n: the "sleep" pinctrl state
> > >  - ports: contains DSI controller input and output ports as children, each
> > >    containing one endpoint subnode.
> > > +- qcom,mdss-dsc-enabled: Display Stream Compression (DSC) is enabled
> > > +- qcom,mdss-slice-height: DSC slice height in pixels
> > > +- qcom,mdss-slice-width: DSC slice width in pixels
> > > +- qcom,mdss-slice-per-pkt: DSC slices per packet
> > > +- qcom,mdss-bit-per-component: DSC bits per component
> > > +- qcom,mdss-bit-per-pixel: DSC bits per pixel
> > > +- qcom,mdss-block-prediction-enable: Block prediction mode of DSC enabled
> > >  
> > >    DSI Endpoint properties:
> > >    - remote-endpoint: For port@0, set to phandle of the connected panel/bridge's
> > > @@ -188,6 +195,14 @@ Example:
> > >  		qcom,master-dsi;
> > >  		qcom,sync-dual-dsi;
> > >  
> > > +		qcom,mdss-dsc-enabled;
> > 
> > To me the activation of DSC seems to be a property of the panel.
> 
> I think there are three parts to the problem
> 1. Panel needs to support it

In the case of DP there's bits to be read in the panel to figure this
out, for DSI panels this seems like a property that the panel (driver)
should know about.

> 2. Host needs to support it

Right, so this needs to be known by the driver. My suggestion is that we
derive it from the compatible or from the HW version.

> 3. Someone needs to decide to use when both the above conditions are
> met.
> 
> There are cases where above 1, 2 will be satisfied, but we might be okay
> without DSC too.. so how to decide when to do DSC :)
> 

Can we describe those cases? E.g. is it because enabling DSC would not
cause a reduction in clock speed that's worth the effort? Or do we only
use DSC for DSI when it allows us to squeeze everything into a single
link?

Regards,
Bjorn

> I feel it is more of a system property. And I also think that these
> parameters here are host configuration and not really for panel...
> 
> > 
> > > +		qcom,mdss-slice-height = <16>;
> > > +		qcom,mdss-slice-width = <540>;
> > > +		qcom,mdss-slice-per-pkt = <1>;
> > > +		qcom,mdss-bit-per-component = <8>;
> > > +		qcom,mdss-bit-per-pixel = <8>;
> > > +		qcom,mdss-block-prediction-enable;
> > 
> > Which of these properties relates to the DSC encoder and what needs to
> > be agreed with the sink? Can't we derive e.g. bpp from the information
> > we have from the attached panel already?
> 
> Let me go back and check on this a bit more
> 
> Thanks
> -- 
> ~Vinod

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

* Re: [RFC PATCH 02/13] dt-bindings: msm/dsi: Document Display Stream Compression (DSC) parameters
@ 2021-05-24 15:08         ` Bjorn Andersson
  0 siblings, 0 replies; 91+ messages in thread
From: Bjorn Andersson @ 2021-05-24 15:08 UTC (permalink / raw)
  To: Vinod Koul
  Cc: devicetree, Jonathan Marek, David Airlie, linux-arm-msm,
	linux-kernel, Abhinav Kumar, Rob Herring, dri-devel,
	Dmitry Baryshkov, freedreno

On Mon 24 May 02:30 CDT 2021, Vinod Koul wrote:

> On 21-05-21, 09:42, Bjorn Andersson wrote:
> > On Fri 21 May 07:49 CDT 2021, Vinod Koul wrote:
> > 
> > > DSC enables streams to be compressed before we send to panel. This
> > > requires DSC enabled encoder and a panel to be present. So we add this
> > > information in board DTS and find if DSC can be enabled and the
> > > parameters required to configure DSC are added to binding document along
> > > with example
> > > 
> > > Signed-off-by: Vinod Koul <vkoul@kernel.org>
> > > ---
> > >  .../devicetree/bindings/display/msm/dsi.txt       | 15 +++++++++++++++
> > >  1 file changed, 15 insertions(+)
> > > 
> > > diff --git a/Documentation/devicetree/bindings/display/msm/dsi.txt b/Documentation/devicetree/bindings/display/msm/dsi.txt
> > > index b9a64d3ff184..83d2fb92267e 100644
> > > --- a/Documentation/devicetree/bindings/display/msm/dsi.txt
> > > +++ b/Documentation/devicetree/bindings/display/msm/dsi.txt
> > > @@ -48,6 +48,13 @@ Optional properties:
> > >  - pinctrl-n: the "sleep" pinctrl state
> > >  - ports: contains DSI controller input and output ports as children, each
> > >    containing one endpoint subnode.
> > > +- qcom,mdss-dsc-enabled: Display Stream Compression (DSC) is enabled
> > > +- qcom,mdss-slice-height: DSC slice height in pixels
> > > +- qcom,mdss-slice-width: DSC slice width in pixels
> > > +- qcom,mdss-slice-per-pkt: DSC slices per packet
> > > +- qcom,mdss-bit-per-component: DSC bits per component
> > > +- qcom,mdss-bit-per-pixel: DSC bits per pixel
> > > +- qcom,mdss-block-prediction-enable: Block prediction mode of DSC enabled
> > >  
> > >    DSI Endpoint properties:
> > >    - remote-endpoint: For port@0, set to phandle of the connected panel/bridge's
> > > @@ -188,6 +195,14 @@ Example:
> > >  		qcom,master-dsi;
> > >  		qcom,sync-dual-dsi;
> > >  
> > > +		qcom,mdss-dsc-enabled;
> > 
> > To me the activation of DSC seems to be a property of the panel.
> 
> I think there are three parts to the problem
> 1. Panel needs to support it

In the case of DP there's bits to be read in the panel to figure this
out, for DSI panels this seems like a property that the panel (driver)
should know about.

> 2. Host needs to support it

Right, so this needs to be known by the driver. My suggestion is that we
derive it from the compatible or from the HW version.

> 3. Someone needs to decide to use when both the above conditions are
> met.
> 
> There are cases where above 1, 2 will be satisfied, but we might be okay
> without DSC too.. so how to decide when to do DSC :)
> 

Can we describe those cases? E.g. is it because enabling DSC would not
cause a reduction in clock speed that's worth the effort? Or do we only
use DSC for DSI when it allows us to squeeze everything into a single
link?

Regards,
Bjorn

> I feel it is more of a system property. And I also think that these
> parameters here are host configuration and not really for panel...
> 
> > 
> > > +		qcom,mdss-slice-height = <16>;
> > > +		qcom,mdss-slice-width = <540>;
> > > +		qcom,mdss-slice-per-pkt = <1>;
> > > +		qcom,mdss-bit-per-component = <8>;
> > > +		qcom,mdss-bit-per-pixel = <8>;
> > > +		qcom,mdss-block-prediction-enable;
> > 
> > Which of these properties relates to the DSC encoder and what needs to
> > be agreed with the sink? Can't we derive e.g. bpp from the information
> > we have from the attached panel already?
> 
> Let me go back and check on this a bit more
> 
> Thanks
> -- 
> ~Vinod

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

* Re: [RFC PATCH 02/13] dt-bindings: msm/dsi: Document Display Stream Compression (DSC) parameters
  2021-05-24 15:08         ` Bjorn Andersson
@ 2021-05-26  5:32           ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-26  5:32 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Rob Clark, linux-arm-msm, David Airlie, Daniel Vetter,
	Jonathan Marek, Dmitry Baryshkov, Abhinav Kumar, linux-kernel,
	dri-devel, freedreno, Rob Herring, devicetree

On 24-05-21, 10:08, Bjorn Andersson wrote:
> On Mon 24 May 02:30 CDT 2021, Vinod Koul wrote:
> 
> > On 21-05-21, 09:42, Bjorn Andersson wrote:
> > > On Fri 21 May 07:49 CDT 2021, Vinod Koul wrote:
> > > 
> > > > DSC enables streams to be compressed before we send to panel. This
> > > > requires DSC enabled encoder and a panel to be present. So we add this
> > > > information in board DTS and find if DSC can be enabled and the
> > > > parameters required to configure DSC are added to binding document along
> > > > with example
> > > > 
> > > > Signed-off-by: Vinod Koul <vkoul@kernel.org>
> > > > ---
> > > >  .../devicetree/bindings/display/msm/dsi.txt       | 15 +++++++++++++++
> > > >  1 file changed, 15 insertions(+)
> > > > 
> > > > diff --git a/Documentation/devicetree/bindings/display/msm/dsi.txt b/Documentation/devicetree/bindings/display/msm/dsi.txt
> > > > index b9a64d3ff184..83d2fb92267e 100644
> > > > --- a/Documentation/devicetree/bindings/display/msm/dsi.txt
> > > > +++ b/Documentation/devicetree/bindings/display/msm/dsi.txt
> > > > @@ -48,6 +48,13 @@ Optional properties:
> > > >  - pinctrl-n: the "sleep" pinctrl state
> > > >  - ports: contains DSI controller input and output ports as children, each
> > > >    containing one endpoint subnode.
> > > > +- qcom,mdss-dsc-enabled: Display Stream Compression (DSC) is enabled
> > > > +- qcom,mdss-slice-height: DSC slice height in pixels
> > > > +- qcom,mdss-slice-width: DSC slice width in pixels
> > > > +- qcom,mdss-slice-per-pkt: DSC slices per packet
> > > > +- qcom,mdss-bit-per-component: DSC bits per component
> > > > +- qcom,mdss-bit-per-pixel: DSC bits per pixel
> > > > +- qcom,mdss-block-prediction-enable: Block prediction mode of DSC enabled
> > > >  
> > > >    DSI Endpoint properties:
> > > >    - remote-endpoint: For port@0, set to phandle of the connected panel/bridge's
> > > > @@ -188,6 +195,14 @@ Example:
> > > >  		qcom,master-dsi;
> > > >  		qcom,sync-dual-dsi;
> > > >  
> > > > +		qcom,mdss-dsc-enabled;
> > > 
> > > To me the activation of DSC seems to be a property of the panel.
> > 
> > I think there are three parts to the problem
> > 1. Panel needs to support it
> 
> In the case of DP there's bits to be read in the panel to figure this
> out, for DSI panels this seems like a property that the panel (driver)
> should know about.

Yes panel should know..

> 
> > 2. Host needs to support it
> 
> Right, so this needs to be known by the driver. My suggestion is that we
> derive it from the compatible or from the HW version.

Okay

> 
> > 3. Someone needs to decide to use when both the above conditions are
> > met.
> > 
> > There are cases where above 1, 2 will be satisfied, but we might be okay
> > without DSC too.. so how to decide when to do DSC :)
> > 
> 
> Can we describe those cases? E.g. is it because enabling DSC would not
> cause a reduction in clock speed that's worth the effort? Or do we only
> use DSC for DSI when it allows us to squeeze everything into a single
> link?

I really dont know how and when we should decide that :-|
One thing we can do is that if both support then always enable and get
benefit of getting power and clock speed reduction.

With this, who should have slice and bpp settings, panel or host?

Thanks
-- 
~Vinod

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

* Re: [RFC PATCH 02/13] dt-bindings: msm/dsi: Document Display Stream Compression (DSC) parameters
@ 2021-05-26  5:32           ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-26  5:32 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: devicetree, Jonathan Marek, David Airlie, linux-arm-msm,
	linux-kernel, Abhinav Kumar, Rob Herring, dri-devel,
	Dmitry Baryshkov, freedreno

On 24-05-21, 10:08, Bjorn Andersson wrote:
> On Mon 24 May 02:30 CDT 2021, Vinod Koul wrote:
> 
> > On 21-05-21, 09:42, Bjorn Andersson wrote:
> > > On Fri 21 May 07:49 CDT 2021, Vinod Koul wrote:
> > > 
> > > > DSC enables streams to be compressed before we send to panel. This
> > > > requires DSC enabled encoder and a panel to be present. So we add this
> > > > information in board DTS and find if DSC can be enabled and the
> > > > parameters required to configure DSC are added to binding document along
> > > > with example
> > > > 
> > > > Signed-off-by: Vinod Koul <vkoul@kernel.org>
> > > > ---
> > > >  .../devicetree/bindings/display/msm/dsi.txt       | 15 +++++++++++++++
> > > >  1 file changed, 15 insertions(+)
> > > > 
> > > > diff --git a/Documentation/devicetree/bindings/display/msm/dsi.txt b/Documentation/devicetree/bindings/display/msm/dsi.txt
> > > > index b9a64d3ff184..83d2fb92267e 100644
> > > > --- a/Documentation/devicetree/bindings/display/msm/dsi.txt
> > > > +++ b/Documentation/devicetree/bindings/display/msm/dsi.txt
> > > > @@ -48,6 +48,13 @@ Optional properties:
> > > >  - pinctrl-n: the "sleep" pinctrl state
> > > >  - ports: contains DSI controller input and output ports as children, each
> > > >    containing one endpoint subnode.
> > > > +- qcom,mdss-dsc-enabled: Display Stream Compression (DSC) is enabled
> > > > +- qcom,mdss-slice-height: DSC slice height in pixels
> > > > +- qcom,mdss-slice-width: DSC slice width in pixels
> > > > +- qcom,mdss-slice-per-pkt: DSC slices per packet
> > > > +- qcom,mdss-bit-per-component: DSC bits per component
> > > > +- qcom,mdss-bit-per-pixel: DSC bits per pixel
> > > > +- qcom,mdss-block-prediction-enable: Block prediction mode of DSC enabled
> > > >  
> > > >    DSI Endpoint properties:
> > > >    - remote-endpoint: For port@0, set to phandle of the connected panel/bridge's
> > > > @@ -188,6 +195,14 @@ Example:
> > > >  		qcom,master-dsi;
> > > >  		qcom,sync-dual-dsi;
> > > >  
> > > > +		qcom,mdss-dsc-enabled;
> > > 
> > > To me the activation of DSC seems to be a property of the panel.
> > 
> > I think there are three parts to the problem
> > 1. Panel needs to support it
> 
> In the case of DP there's bits to be read in the panel to figure this
> out, for DSI panels this seems like a property that the panel (driver)
> should know about.

Yes panel should know..

> 
> > 2. Host needs to support it
> 
> Right, so this needs to be known by the driver. My suggestion is that we
> derive it from the compatible or from the HW version.

Okay

> 
> > 3. Someone needs to decide to use when both the above conditions are
> > met.
> > 
> > There are cases where above 1, 2 will be satisfied, but we might be okay
> > without DSC too.. so how to decide when to do DSC :)
> > 
> 
> Can we describe those cases? E.g. is it because enabling DSC would not
> cause a reduction in clock speed that's worth the effort? Or do we only
> use DSC for DSI when it allows us to squeeze everything into a single
> link?

I really dont know how and when we should decide that :-|
One thing we can do is that if both support then always enable and get
benefit of getting power and clock speed reduction.

With this, who should have slice and bpp settings, panel or host?

Thanks
-- 
~Vinod

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

* Re: [Freedreno] [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support
  2021-05-21 14:09   ` Jeffrey Hugo
@ 2021-05-26  5:46     ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-26  5:46 UTC (permalink / raw)
  To: Jeffrey Hugo
  Cc: Rob Clark, DTML, Jonathan Marek, David Airlie, MSM, lkml,
	Abhinav Kumar, Bjorn Andersson, Rob Herring,
	open list:DRM PANEL DRIVERS, Daniel Vetter, Dmitry Baryshkov,
	freedreno

Hello Jeff,

On 21-05-21, 08:09, Jeffrey Hugo wrote:
> On Fri, May 21, 2021 at 6:50 AM Vinod Koul <vkoul@kernel.org> wrote:
> >
> > Display Stream Compression (DSC) compresses the display stream in host which
> > is later decoded by panel. This series enables this for Qualcomm msm driver.
> > This was tested on Google Pixel3 phone which use LGE SW43408 panel.
> >
> > The changes include adding DT properties for DSC then hardware blocks support
> > required in DPU1 driver and support in encoder. We also add support in DSI
> > and introduce required topology changes.
> >
> > In order for panel to set the DSC parameters we add dsc in drm_panel and set
> > it from the msm driver.
> >
> > Complete changes which enable this for Pixel3 along with panel driver (not
> > part of this series) and DT changes can be found at:
> > git.linaro.org/people/vinod.koul/kernel.git pixel/dsc_rfc
> >
> > Comments welcome!
> 
> This feels backwards to me.  I've only skimmed this series, and the DT
> changes didn't come through for me, so perhaps I have an incomplete
> view.

Not sure why, I see it on lore:
https://lore.kernel.org/dri-devel/20210521124946.3617862-3-vkoul@kernel.org/

> DSC is not MSM specific.  There is a standard for it.  Yet it looks
> like everything is implemented in a MSM specific way, and then pushed
> to the panel.  So, every vendor needs to implement their vendor
> specific way to get the DSC info, and then push it to the panel?
> Seems wrong, given there is an actual standard for this feature.

I have added slice and bpp info in the DT here under the host and then
pass the generic struct drm_dsc_config to panel which allows panel to
write the pps cmd

Nothing above is MSM specific.. It can very well work with non MSM
controllers too.

I didn't envision DSC to be a specific thing, most of
the patches here are hardware enabling ones for DSC bits for MSM
hardware.

> Additionally, we define panel properties (resolution, BPP, etc) at the
> panel, and have the display drivers pull it from the panel.  However,
> for DSC, you do the reverse (define it in the display driver, and push
> it to the panel).  If the argument is that DSC properties can be
> dynamic, well, so can resolution.  Every panel for MSM MTPs supports
> multiple resolutions, yet we define that with the panel in Linux.

I dont have an answer for that right now, to start with yes the
properties are in host but I am okay to discuss this and put wherever we
feel is most correct thing.  I somehow dont like that we should pull
from panel DT and program host with that. Here using struct
drm_dsc_config allows me to configure panel based on resolution passed

> Finally, I haven't seen the DT bits, but I'm concerned about using DT
> for this.  It inherently excludes ACPI systems.  You appear to have
> sdm845 support in this series, but what about ACPI boot on the Lenovo
> C630 for example?  Or any of the 8cx laptops?  We don't read the panel
> resolution, etc from DT, so why the DSC?

But you must read from somewhere like ACPI tables. I think ACPI systems
would have some ACPI table info out there which would help on this.
Yes that is another task which we need to start with once we enable OF
systems.

Thanks
-- 
~Vinod

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

* Re: [Freedreno] [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support
@ 2021-05-26  5:46     ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-05-26  5:46 UTC (permalink / raw)
  To: Jeffrey Hugo
  Cc: DTML, Jonathan Marek, David Airlie, MSM, lkml, Abhinav Kumar,
	Bjorn Andersson, Rob Herring, open list:DRM PANEL DRIVERS,
	Dmitry Baryshkov, freedreno

Hello Jeff,

On 21-05-21, 08:09, Jeffrey Hugo wrote:
> On Fri, May 21, 2021 at 6:50 AM Vinod Koul <vkoul@kernel.org> wrote:
> >
> > Display Stream Compression (DSC) compresses the display stream in host which
> > is later decoded by panel. This series enables this for Qualcomm msm driver.
> > This was tested on Google Pixel3 phone which use LGE SW43408 panel.
> >
> > The changes include adding DT properties for DSC then hardware blocks support
> > required in DPU1 driver and support in encoder. We also add support in DSI
> > and introduce required topology changes.
> >
> > In order for panel to set the DSC parameters we add dsc in drm_panel and set
> > it from the msm driver.
> >
> > Complete changes which enable this for Pixel3 along with panel driver (not
> > part of this series) and DT changes can be found at:
> > git.linaro.org/people/vinod.koul/kernel.git pixel/dsc_rfc
> >
> > Comments welcome!
> 
> This feels backwards to me.  I've only skimmed this series, and the DT
> changes didn't come through for me, so perhaps I have an incomplete
> view.

Not sure why, I see it on lore:
https://lore.kernel.org/dri-devel/20210521124946.3617862-3-vkoul@kernel.org/

> DSC is not MSM specific.  There is a standard for it.  Yet it looks
> like everything is implemented in a MSM specific way, and then pushed
> to the panel.  So, every vendor needs to implement their vendor
> specific way to get the DSC info, and then push it to the panel?
> Seems wrong, given there is an actual standard for this feature.

I have added slice and bpp info in the DT here under the host and then
pass the generic struct drm_dsc_config to panel which allows panel to
write the pps cmd

Nothing above is MSM specific.. It can very well work with non MSM
controllers too.

I didn't envision DSC to be a specific thing, most of
the patches here are hardware enabling ones for DSC bits for MSM
hardware.

> Additionally, we define panel properties (resolution, BPP, etc) at the
> panel, and have the display drivers pull it from the panel.  However,
> for DSC, you do the reverse (define it in the display driver, and push
> it to the panel).  If the argument is that DSC properties can be
> dynamic, well, so can resolution.  Every panel for MSM MTPs supports
> multiple resolutions, yet we define that with the panel in Linux.

I dont have an answer for that right now, to start with yes the
properties are in host but I am okay to discuss this and put wherever we
feel is most correct thing.  I somehow dont like that we should pull
from panel DT and program host with that. Here using struct
drm_dsc_config allows me to configure panel based on resolution passed

> Finally, I haven't seen the DT bits, but I'm concerned about using DT
> for this.  It inherently excludes ACPI systems.  You appear to have
> sdm845 support in this series, but what about ACPI boot on the Lenovo
> C630 for example?  Or any of the 8cx laptops?  We don't read the panel
> resolution, etc from DT, so why the DSC?

But you must read from somewhere like ACPI tables. I think ACPI systems
would have some ACPI table info out there which would help on this.
Yes that is another task which we need to start with once we enable OF
systems.

Thanks
-- 
~Vinod

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

* Re: [Freedreno] [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support
  2021-05-26  5:46     ` Vinod Koul
@ 2021-05-26 15:00       ` Jeffrey Hugo
  -1 siblings, 0 replies; 91+ messages in thread
From: Jeffrey Hugo @ 2021-05-26 15:00 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Rob Clark, DTML, Jonathan Marek, David Airlie, MSM, lkml,
	Abhinav Kumar, Bjorn Andersson, Rob Herring,
	open list:DRM PANEL DRIVERS, Daniel Vetter, Dmitry Baryshkov,
	freedreno

On Tue, May 25, 2021 at 11:46 PM Vinod Koul <vkoul@kernel.org> wrote:
>
> Hello Jeff,
>
> On 21-05-21, 08:09, Jeffrey Hugo wrote:
> > On Fri, May 21, 2021 at 6:50 AM Vinod Koul <vkoul@kernel.org> wrote:
> > >
> > > Display Stream Compression (DSC) compresses the display stream in host which
> > > is later decoded by panel. This series enables this for Qualcomm msm driver.
> > > This was tested on Google Pixel3 phone which use LGE SW43408 panel.
> > >
> > > The changes include adding DT properties for DSC then hardware blocks support
> > > required in DPU1 driver and support in encoder. We also add support in DSI
> > > and introduce required topology changes.
> > >
> > > In order for panel to set the DSC parameters we add dsc in drm_panel and set
> > > it from the msm driver.
> > >
> > > Complete changes which enable this for Pixel3 along with panel driver (not
> > > part of this series) and DT changes can be found at:
> > > git.linaro.org/people/vinod.koul/kernel.git pixel/dsc_rfc
> > >
> > > Comments welcome!
> >
> > This feels backwards to me.  I've only skimmed this series, and the DT
> > changes didn't come through for me, so perhaps I have an incomplete
> > view.
>
> Not sure why, I see it on lore:
> https://lore.kernel.org/dri-devel/20210521124946.3617862-3-vkoul@kernel.org/
>
> > DSC is not MSM specific.  There is a standard for it.  Yet it looks
> > like everything is implemented in a MSM specific way, and then pushed
> > to the panel.  So, every vendor needs to implement their vendor
> > specific way to get the DSC info, and then push it to the panel?
> > Seems wrong, given there is an actual standard for this feature.
>
> I have added slice and bpp info in the DT here under the host and then
> pass the generic struct drm_dsc_config to panel which allows panel to
> write the pps cmd
>
> Nothing above is MSM specific.. It can very well work with non MSM
> controllers too.

I disagree.

The DT bindings you defined (thanks for the direct link) are MSM
specific.  I'm not talking (yet) about the properties you defined, but
purely from the stand point that you defined the binding within the
scope of the MSM dsi binding.  No other vendor can use those bindings.
Of course, if we look at the properties themselves, they are prefixed
with "qcom", which is vendor specific.

So, purely on the face of it, this is MSM specific.

Assuming we want a DT solution for DSC, I think it should be something
like Documentation/devicetree/bindings/clock/clock-bindings.txt (the
first example that comes to mind), which is a non-vendor specific
generic set of properties that each vendor/device specific binding can
inherit.  Panel has similar things.

Specific to the properties, I don't much like that you duplicate BPP,
which is already associated with the panel (although perhaps not in
the scope of DT).  What if the panel and your DSC bindings disagree?
Also, I guess I need to ask, have you read the DSC spec?  Last I
looked, there were something like 3 dozen properties that could be
configured.  You have five in your proposed binding.  To me, this is
not a generic DSC solution, this is MSM specific (and frankly I don't
think this supports all the configuration the MSM hardware can do,
either).

I'm surprised Rob Herring didn't have more to say on this.

> I didn't envision DSC to be a specific thing, most of
> the patches here are hardware enabling ones for DSC bits for MSM
> hardware.
>
> > Additionally, we define panel properties (resolution, BPP, etc) at the
> > panel, and have the display drivers pull it from the panel.  However,
> > for DSC, you do the reverse (define it in the display driver, and push
> > it to the panel).  If the argument is that DSC properties can be
> > dynamic, well, so can resolution.  Every panel for MSM MTPs supports
> > multiple resolutions, yet we define that with the panel in Linux.
>
> I dont have an answer for that right now, to start with yes the
> properties are in host but I am okay to discuss this and put wherever we
> feel is most correct thing.  I somehow dont like that we should pull
> from panel DT and program host with that. Here using struct
> drm_dsc_config allows me to configure panel based on resolution passed

I somewhat agree that pulling from the panel and programing the host
based on that is an odd solution, but we have it currently.  Have a
look at Documentation/devicetree/bindings/display/panel in particular
panel-timing.  All of that ends up informing the mdss programing
anyways (particularly the dsi and its phy).  So my problem is that we
currently have a solution that seems to just need to be extended, and
instead you have proposed a completely different solution which is
arguably contradictory.

However, I'd like to see thoughts from Rob Clark, David, and any
others that typically handle this stuff (maybe Sam Ravenborg from the
panel side?).  I consider them to be the experts, and if they think
your solution is the way to go, I'll shut up.  I consider myself to be
a novice that has dabbled in this area, and while this currently
doesn't make sense to me, maybe I need some education here to see the
light.

> > Finally, I haven't seen the DT bits, but I'm concerned about using DT
> > for this.  It inherently excludes ACPI systems.  You appear to have
> > sdm845 support in this series, but what about ACPI boot on the Lenovo
> > C630 for example?  Or any of the 8cx laptops?  We don't read the panel
> > resolution, etc from DT, so why the DSC?
>
> But you must read from somewhere like ACPI tables. I think ACPI systems
> would have some ACPI table info out there which would help on this.
> Yes that is another task which we need to start with once we enable OF
> systems.

Frankly, I don't like the MSM ACPI solution that I've seen on the laptops.
The ACPI assumes the entire MDSS (including DSI parts) and GPU is one
device, and ultimately handled by one driver.  That driver needs to
get a value from UEFI (set by the bootloader) that is the "panel id".
Then the driver calls into ACPI (I think its _ROM, but I might be
mistaken, doing this from memory) with that id.  It gets back a binary
blob which is mostly an xml file (format is publicly documented) that
contains the panel timings and such.

Generally we've defined simple-panel entities for these, with the
timings in code (you can see what Bjorn and I have upstreamed), and
just match on the compatible.

In summary, I don't mean to be difficult, I just think this solution
needs more "baking".

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

* Re: [Freedreno] [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support
@ 2021-05-26 15:00       ` Jeffrey Hugo
  0 siblings, 0 replies; 91+ messages in thread
From: Jeffrey Hugo @ 2021-05-26 15:00 UTC (permalink / raw)
  To: Vinod Koul
  Cc: DTML, Jonathan Marek, David Airlie, MSM, lkml, Abhinav Kumar,
	Bjorn Andersson, Rob Herring, open list:DRM PANEL DRIVERS,
	Dmitry Baryshkov, freedreno

On Tue, May 25, 2021 at 11:46 PM Vinod Koul <vkoul@kernel.org> wrote:
>
> Hello Jeff,
>
> On 21-05-21, 08:09, Jeffrey Hugo wrote:
> > On Fri, May 21, 2021 at 6:50 AM Vinod Koul <vkoul@kernel.org> wrote:
> > >
> > > Display Stream Compression (DSC) compresses the display stream in host which
> > > is later decoded by panel. This series enables this for Qualcomm msm driver.
> > > This was tested on Google Pixel3 phone which use LGE SW43408 panel.
> > >
> > > The changes include adding DT properties for DSC then hardware blocks support
> > > required in DPU1 driver and support in encoder. We also add support in DSI
> > > and introduce required topology changes.
> > >
> > > In order for panel to set the DSC parameters we add dsc in drm_panel and set
> > > it from the msm driver.
> > >
> > > Complete changes which enable this for Pixel3 along with panel driver (not
> > > part of this series) and DT changes can be found at:
> > > git.linaro.org/people/vinod.koul/kernel.git pixel/dsc_rfc
> > >
> > > Comments welcome!
> >
> > This feels backwards to me.  I've only skimmed this series, and the DT
> > changes didn't come through for me, so perhaps I have an incomplete
> > view.
>
> Not sure why, I see it on lore:
> https://lore.kernel.org/dri-devel/20210521124946.3617862-3-vkoul@kernel.org/
>
> > DSC is not MSM specific.  There is a standard for it.  Yet it looks
> > like everything is implemented in a MSM specific way, and then pushed
> > to the panel.  So, every vendor needs to implement their vendor
> > specific way to get the DSC info, and then push it to the panel?
> > Seems wrong, given there is an actual standard for this feature.
>
> I have added slice and bpp info in the DT here under the host and then
> pass the generic struct drm_dsc_config to panel which allows panel to
> write the pps cmd
>
> Nothing above is MSM specific.. It can very well work with non MSM
> controllers too.

I disagree.

The DT bindings you defined (thanks for the direct link) are MSM
specific.  I'm not talking (yet) about the properties you defined, but
purely from the stand point that you defined the binding within the
scope of the MSM dsi binding.  No other vendor can use those bindings.
Of course, if we look at the properties themselves, they are prefixed
with "qcom", which is vendor specific.

So, purely on the face of it, this is MSM specific.

Assuming we want a DT solution for DSC, I think it should be something
like Documentation/devicetree/bindings/clock/clock-bindings.txt (the
first example that comes to mind), which is a non-vendor specific
generic set of properties that each vendor/device specific binding can
inherit.  Panel has similar things.

Specific to the properties, I don't much like that you duplicate BPP,
which is already associated with the panel (although perhaps not in
the scope of DT).  What if the panel and your DSC bindings disagree?
Also, I guess I need to ask, have you read the DSC spec?  Last I
looked, there were something like 3 dozen properties that could be
configured.  You have five in your proposed binding.  To me, this is
not a generic DSC solution, this is MSM specific (and frankly I don't
think this supports all the configuration the MSM hardware can do,
either).

I'm surprised Rob Herring didn't have more to say on this.

> I didn't envision DSC to be a specific thing, most of
> the patches here are hardware enabling ones for DSC bits for MSM
> hardware.
>
> > Additionally, we define panel properties (resolution, BPP, etc) at the
> > panel, and have the display drivers pull it from the panel.  However,
> > for DSC, you do the reverse (define it in the display driver, and push
> > it to the panel).  If the argument is that DSC properties can be
> > dynamic, well, so can resolution.  Every panel for MSM MTPs supports
> > multiple resolutions, yet we define that with the panel in Linux.
>
> I dont have an answer for that right now, to start with yes the
> properties are in host but I am okay to discuss this and put wherever we
> feel is most correct thing.  I somehow dont like that we should pull
> from panel DT and program host with that. Here using struct
> drm_dsc_config allows me to configure panel based on resolution passed

I somewhat agree that pulling from the panel and programing the host
based on that is an odd solution, but we have it currently.  Have a
look at Documentation/devicetree/bindings/display/panel in particular
panel-timing.  All of that ends up informing the mdss programing
anyways (particularly the dsi and its phy).  So my problem is that we
currently have a solution that seems to just need to be extended, and
instead you have proposed a completely different solution which is
arguably contradictory.

However, I'd like to see thoughts from Rob Clark, David, and any
others that typically handle this stuff (maybe Sam Ravenborg from the
panel side?).  I consider them to be the experts, and if they think
your solution is the way to go, I'll shut up.  I consider myself to be
a novice that has dabbled in this area, and while this currently
doesn't make sense to me, maybe I need some education here to see the
light.

> > Finally, I haven't seen the DT bits, but I'm concerned about using DT
> > for this.  It inherently excludes ACPI systems.  You appear to have
> > sdm845 support in this series, but what about ACPI boot on the Lenovo
> > C630 for example?  Or any of the 8cx laptops?  We don't read the panel
> > resolution, etc from DT, so why the DSC?
>
> But you must read from somewhere like ACPI tables. I think ACPI systems
> would have some ACPI table info out there which would help on this.
> Yes that is another task which we need to start with once we enable OF
> systems.

Frankly, I don't like the MSM ACPI solution that I've seen on the laptops.
The ACPI assumes the entire MDSS (including DSI parts) and GPU is one
device, and ultimately handled by one driver.  That driver needs to
get a value from UEFI (set by the bootloader) that is the "panel id".
Then the driver calls into ACPI (I think its _ROM, but I might be
mistaken, doing this from memory) with that id.  It gets back a binary
blob which is mostly an xml file (format is publicly documented) that
contains the panel timings and such.

Generally we've defined simple-panel entities for these, with the
timings in code (you can see what Bjorn and I have upstreamed), and
just match on the compatible.

In summary, I don't mean to be difficult, I just think this solution
needs more "baking".

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

* Re: [Freedreno] [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support
  2021-05-26 15:00       ` Jeffrey Hugo
@ 2021-05-27 23:30         ` Rob Clark
  -1 siblings, 0 replies; 91+ messages in thread
From: Rob Clark @ 2021-05-27 23:30 UTC (permalink / raw)
  To: Jeffrey Hugo
  Cc: Vinod Koul, DTML, Jonathan Marek, David Airlie, MSM, lkml,
	Abhinav Kumar, Bjorn Andersson, Rob Herring,
	open list:DRM PANEL DRIVERS, Daniel Vetter, Dmitry Baryshkov,
	freedreno

On Wed, May 26, 2021 at 8:00 AM Jeffrey Hugo <jeffrey.l.hugo@gmail.com> wrote:
>
> On Tue, May 25, 2021 at 11:46 PM Vinod Koul <vkoul@kernel.org> wrote:
> >
> > Hello Jeff,
> >
> > On 21-05-21, 08:09, Jeffrey Hugo wrote:
> > > On Fri, May 21, 2021 at 6:50 AM Vinod Koul <vkoul@kernel.org> wrote:
> > > >
> > > > Display Stream Compression (DSC) compresses the display stream in host which
> > > > is later decoded by panel. This series enables this for Qualcomm msm driver.
> > > > This was tested on Google Pixel3 phone which use LGE SW43408 panel.
> > > >
> > > > The changes include adding DT properties for DSC then hardware blocks support
> > > > required in DPU1 driver and support in encoder. We also add support in DSI
> > > > and introduce required topology changes.
> > > >
> > > > In order for panel to set the DSC parameters we add dsc in drm_panel and set
> > > > it from the msm driver.
> > > >
> > > > Complete changes which enable this for Pixel3 along with panel driver (not
> > > > part of this series) and DT changes can be found at:
> > > > git.linaro.org/people/vinod.koul/kernel.git pixel/dsc_rfc
> > > >
> > > > Comments welcome!
> > >
> > > This feels backwards to me.  I've only skimmed this series, and the DT
> > > changes didn't come through for me, so perhaps I have an incomplete
> > > view.
> >
> > Not sure why, I see it on lore:
> > https://lore.kernel.org/dri-devel/20210521124946.3617862-3-vkoul@kernel.org/
> >
> > > DSC is not MSM specific.  There is a standard for it.  Yet it looks
> > > like everything is implemented in a MSM specific way, and then pushed
> > > to the panel.  So, every vendor needs to implement their vendor
> > > specific way to get the DSC info, and then push it to the panel?
> > > Seems wrong, given there is an actual standard for this feature.
> >
> > I have added slice and bpp info in the DT here under the host and then
> > pass the generic struct drm_dsc_config to panel which allows panel to
> > write the pps cmd
> >
> > Nothing above is MSM specific.. It can very well work with non MSM
> > controllers too.
>
> I disagree.
>
> The DT bindings you defined (thanks for the direct link) are MSM
> specific.  I'm not talking (yet) about the properties you defined, but
> purely from the stand point that you defined the binding within the
> scope of the MSM dsi binding.  No other vendor can use those bindings.
> Of course, if we look at the properties themselves, they are prefixed
> with "qcom", which is vendor specific.
>
> So, purely on the face of it, this is MSM specific.
>
> Assuming we want a DT solution for DSC, I think it should be something
> like Documentation/devicetree/bindings/clock/clock-bindings.txt (the
> first example that comes to mind), which is a non-vendor specific
> generic set of properties that each vendor/device specific binding can
> inherit.  Panel has similar things.
>
> Specific to the properties, I don't much like that you duplicate BPP,
> which is already associated with the panel (although perhaps not in
> the scope of DT).  What if the panel and your DSC bindings disagree?
> Also, I guess I need to ask, have you read the DSC spec?  Last I
> looked, there were something like 3 dozen properties that could be
> configured.  You have five in your proposed binding.  To me, this is
> not a generic DSC solution, this is MSM specific (and frankly I don't
> think this supports all the configuration the MSM hardware can do,
> either).
>
> I'm surprised Rob Herring didn't have more to say on this.
>
> > I didn't envision DSC to be a specific thing, most of
> > the patches here are hardware enabling ones for DSC bits for MSM
> > hardware.
> >
> > > Additionally, we define panel properties (resolution, BPP, etc) at the
> > > panel, and have the display drivers pull it from the panel.  However,
> > > for DSC, you do the reverse (define it in the display driver, and push
> > > it to the panel).  If the argument is that DSC properties can be
> > > dynamic, well, so can resolution.  Every panel for MSM MTPs supports
> > > multiple resolutions, yet we define that with the panel in Linux.
> >
> > I dont have an answer for that right now, to start with yes the
> > properties are in host but I am okay to discuss this and put wherever we
> > feel is most correct thing.  I somehow dont like that we should pull
> > from panel DT and program host with that. Here using struct
> > drm_dsc_config allows me to configure panel based on resolution passed
>
> I somewhat agree that pulling from the panel and programing the host
> based on that is an odd solution, but we have it currently.  Have a
> look at Documentation/devicetree/bindings/display/panel in particular
> panel-timing.  All of that ends up informing the mdss programing
> anyways (particularly the dsi and its phy).  So my problem is that we
> currently have a solution that seems to just need to be extended, and
> instead you have proposed a completely different solution which is
> arguably contradictory.
>
> However, I'd like to see thoughts from Rob Clark, David, and any
> others that typically handle this stuff (maybe Sam Ravenborg from the
> panel side?).  I consider them to be the experts, and if they think
> your solution is the way to go, I'll shut up.  I consider myself to be
> a novice that has dabbled in this area, and while this currently
> doesn't make sense to me, maybe I need some education here to see the
> light.
>
> > > Finally, I haven't seen the DT bits, but I'm concerned about using DT
> > > for this.  It inherently excludes ACPI systems.  You appear to have
> > > sdm845 support in this series, but what about ACPI boot on the Lenovo
> > > C630 for example?  Or any of the 8cx laptops?  We don't read the panel
> > > resolution, etc from DT, so why the DSC?
> >
> > But you must read from somewhere like ACPI tables. I think ACPI systems
> > would have some ACPI table info out there which would help on this.
> > Yes that is another task which we need to start with once we enable OF
> > systems.
>
> Frankly, I don't like the MSM ACPI solution that I've seen on the laptops.
> The ACPI assumes the entire MDSS (including DSI parts) and GPU is one
> device, and ultimately handled by one driver.  That driver needs to
> get a value from UEFI (set by the bootloader) that is the "panel id".
> Then the driver calls into ACPI (I think its _ROM, but I might be
> mistaken, doing this from memory) with that id.  It gets back a binary
> blob which is mostly an xml file (format is publicly documented) that
> contains the panel timings and such.

tbh, I kinda suspect that having a single "gpu" device (which also
includes venus, in addition to display, IIRC) in the ACPI tables is a
windowsism, trying to make things look to userspace like a single "GPU
card" in the x86 world.. but either way, I think the ACPI tables on
the windows arm laptops which use dsi->bridge->edp is too much of a
lost cause to even consider here.  Possibly ACPI boot on these devices
would be more feasible on newer devices which have direct eDP out of
the SoC without requiring external bridge/panel glue.

I'd worry more about what makes sense in a DT world, when it comes to
DT bindings.

BR,
-R

> Generally we've defined simple-panel entities for these, with the
> timings in code (you can see what Bjorn and I have upstreamed), and
> just match on the compatible.
>
> In summary, I don't mean to be difficult, I just think this solution
> needs more "baking".

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

* Re: [Freedreno] [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support
@ 2021-05-27 23:30         ` Rob Clark
  0 siblings, 0 replies; 91+ messages in thread
From: Rob Clark @ 2021-05-27 23:30 UTC (permalink / raw)
  To: Jeffrey Hugo
  Cc: DTML, Jonathan Marek, David Airlie, MSM, lkml, Abhinav Kumar,
	Bjorn Andersson, Vinod Koul, Rob Herring,
	open list:DRM PANEL DRIVERS, Dmitry Baryshkov, freedreno

On Wed, May 26, 2021 at 8:00 AM Jeffrey Hugo <jeffrey.l.hugo@gmail.com> wrote:
>
> On Tue, May 25, 2021 at 11:46 PM Vinod Koul <vkoul@kernel.org> wrote:
> >
> > Hello Jeff,
> >
> > On 21-05-21, 08:09, Jeffrey Hugo wrote:
> > > On Fri, May 21, 2021 at 6:50 AM Vinod Koul <vkoul@kernel.org> wrote:
> > > >
> > > > Display Stream Compression (DSC) compresses the display stream in host which
> > > > is later decoded by panel. This series enables this for Qualcomm msm driver.
> > > > This was tested on Google Pixel3 phone which use LGE SW43408 panel.
> > > >
> > > > The changes include adding DT properties for DSC then hardware blocks support
> > > > required in DPU1 driver and support in encoder. We also add support in DSI
> > > > and introduce required topology changes.
> > > >
> > > > In order for panel to set the DSC parameters we add dsc in drm_panel and set
> > > > it from the msm driver.
> > > >
> > > > Complete changes which enable this for Pixel3 along with panel driver (not
> > > > part of this series) and DT changes can be found at:
> > > > git.linaro.org/people/vinod.koul/kernel.git pixel/dsc_rfc
> > > >
> > > > Comments welcome!
> > >
> > > This feels backwards to me.  I've only skimmed this series, and the DT
> > > changes didn't come through for me, so perhaps I have an incomplete
> > > view.
> >
> > Not sure why, I see it on lore:
> > https://lore.kernel.org/dri-devel/20210521124946.3617862-3-vkoul@kernel.org/
> >
> > > DSC is not MSM specific.  There is a standard for it.  Yet it looks
> > > like everything is implemented in a MSM specific way, and then pushed
> > > to the panel.  So, every vendor needs to implement their vendor
> > > specific way to get the DSC info, and then push it to the panel?
> > > Seems wrong, given there is an actual standard for this feature.
> >
> > I have added slice and bpp info in the DT here under the host and then
> > pass the generic struct drm_dsc_config to panel which allows panel to
> > write the pps cmd
> >
> > Nothing above is MSM specific.. It can very well work with non MSM
> > controllers too.
>
> I disagree.
>
> The DT bindings you defined (thanks for the direct link) are MSM
> specific.  I'm not talking (yet) about the properties you defined, but
> purely from the stand point that you defined the binding within the
> scope of the MSM dsi binding.  No other vendor can use those bindings.
> Of course, if we look at the properties themselves, they are prefixed
> with "qcom", which is vendor specific.
>
> So, purely on the face of it, this is MSM specific.
>
> Assuming we want a DT solution for DSC, I think it should be something
> like Documentation/devicetree/bindings/clock/clock-bindings.txt (the
> first example that comes to mind), which is a non-vendor specific
> generic set of properties that each vendor/device specific binding can
> inherit.  Panel has similar things.
>
> Specific to the properties, I don't much like that you duplicate BPP,
> which is already associated with the panel (although perhaps not in
> the scope of DT).  What if the panel and your DSC bindings disagree?
> Also, I guess I need to ask, have you read the DSC spec?  Last I
> looked, there were something like 3 dozen properties that could be
> configured.  You have five in your proposed binding.  To me, this is
> not a generic DSC solution, this is MSM specific (and frankly I don't
> think this supports all the configuration the MSM hardware can do,
> either).
>
> I'm surprised Rob Herring didn't have more to say on this.
>
> > I didn't envision DSC to be a specific thing, most of
> > the patches here are hardware enabling ones for DSC bits for MSM
> > hardware.
> >
> > > Additionally, we define panel properties (resolution, BPP, etc) at the
> > > panel, and have the display drivers pull it from the panel.  However,
> > > for DSC, you do the reverse (define it in the display driver, and push
> > > it to the panel).  If the argument is that DSC properties can be
> > > dynamic, well, so can resolution.  Every panel for MSM MTPs supports
> > > multiple resolutions, yet we define that with the panel in Linux.
> >
> > I dont have an answer for that right now, to start with yes the
> > properties are in host but I am okay to discuss this and put wherever we
> > feel is most correct thing.  I somehow dont like that we should pull
> > from panel DT and program host with that. Here using struct
> > drm_dsc_config allows me to configure panel based on resolution passed
>
> I somewhat agree that pulling from the panel and programing the host
> based on that is an odd solution, but we have it currently.  Have a
> look at Documentation/devicetree/bindings/display/panel in particular
> panel-timing.  All of that ends up informing the mdss programing
> anyways (particularly the dsi and its phy).  So my problem is that we
> currently have a solution that seems to just need to be extended, and
> instead you have proposed a completely different solution which is
> arguably contradictory.
>
> However, I'd like to see thoughts from Rob Clark, David, and any
> others that typically handle this stuff (maybe Sam Ravenborg from the
> panel side?).  I consider them to be the experts, and if they think
> your solution is the way to go, I'll shut up.  I consider myself to be
> a novice that has dabbled in this area, and while this currently
> doesn't make sense to me, maybe I need some education here to see the
> light.
>
> > > Finally, I haven't seen the DT bits, but I'm concerned about using DT
> > > for this.  It inherently excludes ACPI systems.  You appear to have
> > > sdm845 support in this series, but what about ACPI boot on the Lenovo
> > > C630 for example?  Or any of the 8cx laptops?  We don't read the panel
> > > resolution, etc from DT, so why the DSC?
> >
> > But you must read from somewhere like ACPI tables. I think ACPI systems
> > would have some ACPI table info out there which would help on this.
> > Yes that is another task which we need to start with once we enable OF
> > systems.
>
> Frankly, I don't like the MSM ACPI solution that I've seen on the laptops.
> The ACPI assumes the entire MDSS (including DSI parts) and GPU is one
> device, and ultimately handled by one driver.  That driver needs to
> get a value from UEFI (set by the bootloader) that is the "panel id".
> Then the driver calls into ACPI (I think its _ROM, but I might be
> mistaken, doing this from memory) with that id.  It gets back a binary
> blob which is mostly an xml file (format is publicly documented) that
> contains the panel timings and such.

tbh, I kinda suspect that having a single "gpu" device (which also
includes venus, in addition to display, IIRC) in the ACPI tables is a
windowsism, trying to make things look to userspace like a single "GPU
card" in the x86 world.. but either way, I think the ACPI tables on
the windows arm laptops which use dsi->bridge->edp is too much of a
lost cause to even consider here.  Possibly ACPI boot on these devices
would be more feasible on newer devices which have direct eDP out of
the SoC without requiring external bridge/panel glue.

I'd worry more about what makes sense in a DT world, when it comes to
DT bindings.

BR,
-R

> Generally we've defined simple-panel entities for these, with the
> timings in code (you can see what Bjorn and I have upstreamed), and
> just match on the compatible.
>
> In summary, I don't mean to be difficult, I just think this solution
> needs more "baking".

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

* Re: [RFC PATCH 03/13] drm/msm/dsi: add support for dsc data
  2021-05-21 12:49   ` Vinod Koul
@ 2021-05-27 23:45     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 91+ messages in thread
From: Dmitry Baryshkov @ 2021-05-27 23:45 UTC (permalink / raw)
  To: Vinod Koul, Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, David Airlie, Daniel Vetter,
	Jonathan Marek, Abhinav Kumar, linux-kernel, dri-devel,
	freedreno

On 21/05/2021 15:49, Vinod Koul wrote:
> DSC needs some configuration from device tree, add support to read and
> store these params and add DSC structures in msm_drv
> 
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>   drivers/gpu/drm/msm/dsi/dsi_host.c | 170 +++++++++++++++++++++++++++++
>   drivers/gpu/drm/msm/msm_drv.h      |  32 ++++++
>   2 files changed, 202 insertions(+)
> 


[skipped]


>   		DRM_DEV_ERROR(dev, "%s: invalid lane configuration %d\n",
> diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
> index 2668941df529..26661dd43936 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -30,6 +30,7 @@
>   #include <drm/drm_plane_helper.h>
>   #include <drm/drm_probe_helper.h>
>   #include <drm/drm_fb_helper.h>
> +#include <drm/drm_dsc.h>
>   #include <drm/msm_drm.h>
>   #include <drm/drm_gem.h>
>   
> @@ -70,6 +71,16 @@ enum msm_mdp_plane_property {
>   #define MSM_GPU_MAX_RINGS 4
>   #define MAX_H_TILES_PER_DISPLAY 2
>   
> +/**
> + * enum msm_display_compression_type - compression method used for pixel stream
> + * @MSM_DISPLAY_COMPRESSION_NONE:	Pixel data is not compressed
> + * @MSM_DISPLAY_COMPRESSION_DSC:	DSC compresison is used
> + */
> +enum msm_display_compression_type {
> +	MSM_DISPLAY_COMPRESSION_NONE,
> +	MSM_DISPLAY_COMPRESSION_DSC,
> +};
> +

Seems to be unused

>   /**
>    * enum msm_display_caps - features/capabilities supported by displays
>    * @MSM_DISPLAY_CAP_VID_MODE:           Video or "active" mode supported



-- 
With best wishes
Dmitry

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

* Re: [RFC PATCH 03/13] drm/msm/dsi: add support for dsc data
@ 2021-05-27 23:45     ` Dmitry Baryshkov
  0 siblings, 0 replies; 91+ messages in thread
From: Dmitry Baryshkov @ 2021-05-27 23:45 UTC (permalink / raw)
  To: Vinod Koul, Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, dri-devel, freedreno

On 21/05/2021 15:49, Vinod Koul wrote:
> DSC needs some configuration from device tree, add support to read and
> store these params and add DSC structures in msm_drv
> 
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>   drivers/gpu/drm/msm/dsi/dsi_host.c | 170 +++++++++++++++++++++++++++++
>   drivers/gpu/drm/msm/msm_drv.h      |  32 ++++++
>   2 files changed, 202 insertions(+)
> 


[skipped]


>   		DRM_DEV_ERROR(dev, "%s: invalid lane configuration %d\n",
> diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
> index 2668941df529..26661dd43936 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -30,6 +30,7 @@
>   #include <drm/drm_plane_helper.h>
>   #include <drm/drm_probe_helper.h>
>   #include <drm/drm_fb_helper.h>
> +#include <drm/drm_dsc.h>
>   #include <drm/msm_drm.h>
>   #include <drm/drm_gem.h>
>   
> @@ -70,6 +71,16 @@ enum msm_mdp_plane_property {
>   #define MSM_GPU_MAX_RINGS 4
>   #define MAX_H_TILES_PER_DISPLAY 2
>   
> +/**
> + * enum msm_display_compression_type - compression method used for pixel stream
> + * @MSM_DISPLAY_COMPRESSION_NONE:	Pixel data is not compressed
> + * @MSM_DISPLAY_COMPRESSION_DSC:	DSC compresison is used
> + */
> +enum msm_display_compression_type {
> +	MSM_DISPLAY_COMPRESSION_NONE,
> +	MSM_DISPLAY_COMPRESSION_DSC,
> +};
> +

Seems to be unused

>   /**
>    * enum msm_display_caps - features/capabilities supported by displays
>    * @MSM_DISPLAY_CAP_VID_MODE:           Video or "active" mode supported



-- 
With best wishes
Dmitry

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

* Re: [RFC PATCH 03/13] drm/msm/disp/dpu1: Add support for DSC
  2021-05-21 12:49   ` Vinod Koul
@ 2021-05-27 23:49     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 91+ messages in thread
From: Dmitry Baryshkov @ 2021-05-27 23:49 UTC (permalink / raw)
  To: Vinod Koul, Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, David Airlie, Daniel Vetter,
	Jonathan Marek, Abhinav Kumar, linux-kernel, dri-devel,
	freedreno

On 21/05/2021 15:49, Vinod Koul wrote:
> Display Stream Compression (DSC) is one of the hw blocks in dpu, so add
> support by adding hw blocks for DSC
> 
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>   drivers/gpu/drm/msm/Makefile                  |   1 +
>   .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |  26 +++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c    | 221 ++++++++++++++++++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h    |  79 +++++++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 ++
>   5 files changed, 340 insertions(+)
>   create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
>   create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
> 
> diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
> index 610d630326bb..fd8fc57f1f58 100644
> --- a/drivers/gpu/drm/msm/Makefile
> +++ b/drivers/gpu/drm/msm/Makefile
> @@ -61,6 +61,7 @@ msm-y := \
>   	disp/dpu1/dpu_hw_blk.o \
>   	disp/dpu1/dpu_hw_catalog.o \
>   	disp/dpu1/dpu_hw_ctl.o \
> +	disp/dpu1/dpu_hw_dsc.o \
>   	disp/dpu1/dpu_hw_interrupts.o \
>   	disp/dpu1/dpu_hw_intf.o \
>   	disp/dpu1/dpu_hw_lm.o \
> 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 4dfd8a20ad5c..a699633f7013 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> @@ -165,6 +165,7 @@ enum {
>    * @DPU_PINGPONG_TE2        Additional tear check block for split pipes
>    * @DPU_PINGPONG_SPLIT      PP block supports split fifo
>    * @DPU_PINGPONG_SLAVE      PP block is a suitable slave for split fifo
> + * @DPU_PINGPONG_DSC        Display stream compression blocks

PP block supports DSC compression?

Also you don't seem to set it anywhere. Do we have hardware w/o DSC support?

>    * @DPU_PINGPONG_DITHER,    Dither blocks
>    * @DPU_PINGPONG_MAX
>    */
> @@ -173,10 +174,21 @@ enum {
>   	DPU_PINGPONG_TE2,
>   	DPU_PINGPONG_SPLIT,
>   	DPU_PINGPONG_SLAVE,
> +	DPU_PINGPONG_DSC,
>   	DPU_PINGPONG_DITHER,
>   	DPU_PINGPONG_MAX
>   };
>   
> +/**
> + * DSC sub-blocks
> + * @DPU_DSC		DSC sub block
> + * @DPU_DSC_MAX
> + */
> +enum {
> +	DPU_DSC = 0x1,
> +	DPU_DSC_MAX
> +};
> +

Unused

>   /**
>    * CTL sub-blocks
>    * @DPU_CTL_SPLIT_DISPLAY       CTL supports video mode split display
> @@ -413,6 +425,7 @@ struct dpu_dspp_sub_blks {
>   struct dpu_pingpong_sub_blks {
>   	struct dpu_pp_blk te;
>   	struct dpu_pp_blk te2;
> +	struct dpu_pp_blk dsc;
>   	struct dpu_pp_blk dither;
>   };

Unused


>   
> @@ -547,6 +560,16 @@ struct dpu_merge_3d_cfg  {
>   	const struct dpu_merge_3d_sub_blks *sblk;
>   };
>   
> +/**
> + * struct dpu_dsc_cfg - information of DSC blocks
> + * @id                 enum identifying this block
> + * @base               register offset of this block
> + * @features           bit mask identifying sub-blocks/features
> + */
> +struct dpu_dsc_cfg {
> +	DPU_HW_BLK_INFO;
> +};
> +
>   /**
>    * struct dpu_intf_cfg - information of timing engine blocks
>    * @id                 enum identifying this block
> @@ -748,6 +771,9 @@ struct dpu_mdss_cfg {
>   	u32 merge_3d_count;
>   	const struct dpu_merge_3d_cfg *merge_3d;
>   
> +	u32 dsc_count;
> +	struct dpu_dsc_cfg *dsc;
> +
>   	u32 intf_count;
>   	const struct dpu_intf_cfg *intf;
>   
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
> new file mode 100644
> index 000000000000..8b8d0553709d
> --- /dev/null
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
> @@ -0,0 +1,221 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2020, Linaro Limited
> + */
> +
> +#include "dpu_kms.h"
> +#include "dpu_hw_catalog.h"
> +#include "dpu_hwio.h"
> +#include "dpu_hw_mdss.h"
> +#include "dpu_hw_dsc.h"
> +
> +#define DSC_COMMON_MODE	                0x000
> +#define DSC_ENC                         0X004
> +#define DSC_PICTURE                     0x008
> +#define DSC_SLICE                       0x00C
> +#define DSC_CHUNK_SIZE                  0x010
> +#define DSC_DELAY                       0x014
> +#define DSC_SCALE_INITIAL               0x018
> +#define DSC_SCALE_DEC_INTERVAL          0x01C
> +#define DSC_SCALE_INC_INTERVAL          0x020
> +#define DSC_FIRST_LINE_BPG_OFFSET       0x024
> +#define DSC_BPG_OFFSET                  0x028
> +#define DSC_DSC_OFFSET                  0x02C
> +#define DSC_FLATNESS                    0x030
> +#define DSC_RC_MODEL_SIZE               0x034
> +#define DSC_RC                          0x038
> +#define DSC_RC_BUF_THRESH               0x03C
> +#define DSC_RANGE_MIN_QP                0x074
> +#define DSC_RANGE_MAX_QP                0x0B0
> +#define DSC_RANGE_BPG_OFFSET            0x0EC
> +
> +static void dpu_hw_dsc_disable(struct dpu_hw_dsc *dsc)
> +{
> +	struct dpu_hw_blk_reg_map *c = &dsc->hw;
> +
> +	DPU_REG_WRITE(c, DSC_COMMON_MODE, 0);
> +}
> +
> +static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
> +			      struct msm_display_dsc_config *dsc,
> +			      u32 mode, bool ich_reset_override)
> +{
> +	struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
> +	u32 data;
> +	u32 initial_lines = dsc->initial_lines;
> +	bool is_cmd_mode = !(mode & BIT(2));
> +
> +	DPU_REG_WRITE(c, DSC_COMMON_MODE, mode);
> +
> +	data = 0;
> +	if (ich_reset_override)
> +		data = 3 << 28;
> +
> +	if (is_cmd_mode)
> +		initial_lines += 1;
> +
> +	data |= (initial_lines << 20);
> +	data |= ((dsc->slice_last_group_size) << 18);
> +	/* bpp is 6.4 format, 4 LSBs bits are for fractional part */
> +	data |= dsc->drm.bits_per_pixel << 12;
> +	data |= (dsc->drm.block_pred_enable << 7);
> +	data |= (dsc->drm.line_buf_depth << 3);
> +	data |= (dsc->drm.simple_422 << 2);
> +	data |= (dsc->drm.convert_rgb << 1);
> +	if (dsc->drm.bits_per_component  == 10)
> +		data |= BIT(0);
> +
> +	DPU_REG_WRITE(c, DSC_ENC, data);
> +
> +	data = dsc->drm.pic_width << 16;
> +	data |= dsc->drm.pic_height;
> +	DPU_REG_WRITE(c, DSC_PICTURE, data);
> +
> +	data = dsc->drm.slice_width << 16;
> +	data |= dsc->drm.slice_height;
> +	DPU_REG_WRITE(c, DSC_SLICE, data);
> +
> +	data = DIV_ROUND_UP(dsc->drm.slice_width * dsc->drm.bits_per_pixel, 8) << 16;
> +
> +	DPU_REG_WRITE(c, DSC_CHUNK_SIZE, data);
> +
> +	data = dsc->drm.initial_dec_delay << 16;
> +	data |= dsc->drm.initial_xmit_delay;
> +	DPU_REG_WRITE(c, DSC_DELAY, data);
> +
> +	data = dsc->drm.initial_scale_value;
> +	DPU_REG_WRITE(c, DSC_SCALE_INITIAL, data);
> +
> +	data = dsc->drm.scale_decrement_interval;
> +	DPU_REG_WRITE(c, DSC_SCALE_DEC_INTERVAL, data);
> +
> +	data = 0x00000184; /* only this value works */
> +	DPU_REG_WRITE(c, DSC_SCALE_INC_INTERVAL, data);
> +
> +	data = dsc->drm.first_line_bpg_offset;
> +	DPU_REG_WRITE(c, DSC_FIRST_LINE_BPG_OFFSET, data);
> +
> +	data = dsc->drm.nfl_bpg_offset << 16;
> +	data |= dsc->drm.slice_bpg_offset;
> +	DPU_REG_WRITE(c, DSC_BPG_OFFSET, data);
> +
> +	data = dsc->drm.initial_offset << 16;
> +	data |= dsc->drm.final_offset;
> +	DPU_REG_WRITE(c, DSC_DSC_OFFSET, data);
> +
> +	data = dsc->det_thresh_flatness << 10;
> +	data |= dsc->drm.flatness_max_qp << 5;
> +	data |= dsc->drm.flatness_min_qp;
> +	DPU_REG_WRITE(c, DSC_FLATNESS, data);
> +
> +	data = dsc->drm.rc_model_size;
> +	DPU_REG_WRITE(c, DSC_RC_MODEL_SIZE, data);
> +
> +	data = dsc->drm.rc_tgt_offset_low << 18;
> +	data |= dsc->drm.rc_tgt_offset_high << 14;
> +	data |= dsc->drm.rc_quant_incr_limit1 << 9;
> +	data |= dsc->drm.rc_quant_incr_limit0 << 4;
> +	data |= dsc->drm.rc_edge_factor;
> +	DPU_REG_WRITE(c, DSC_RC, data);
> +}
> +
> +static void dpu_hw_dsc_config_thresh(struct dpu_hw_dsc *hw_dsc,
> +				     struct msm_display_dsc_config *dsc)
> +{
> +	struct drm_dsc_rc_range_parameters *rc = dsc->drm.rc_range_params;
> +	struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
> +	u32 off = 0x0;
> +	u16 *lp;
> +	int i;
> +
> +	lp = dsc->drm.rc_buf_thresh;
> +	off = DSC_RC_BUF_THRESH;
> +	for (i = 0; i < DSC_NUM_BUF_RANGES - 1 ; i++) {
> +		DPU_REG_WRITE(c, off, *lp++);
> +		off += 4;
> +	}
> +
> +	off = DSC_RANGE_MIN_QP;
> +	for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
> +		DPU_REG_WRITE(c, off, rc[i].range_min_qp);
> +		off += 4;
> +	}
> +
> +	off = DSC_RANGE_MAX_QP;
> +	for (i = 0; i < 15; i++) {
> +		DPU_REG_WRITE(c, off, rc[i].range_max_qp);
> +		off += 4;
> +	}
> +
> +	off = DSC_RANGE_BPG_OFFSET;
> +	for (i = 0; i < 15; i++) {
> +		DPU_REG_WRITE(c, off, rc[i].range_bpg_offset);
> +		off += 4;
> +	}
> +}
> +
> +static struct dpu_dsc_cfg *_dsc_offset(enum dpu_dsc dsc,
> +				       struct dpu_mdss_cfg *m,
> +				       void __iomem *addr,
> +				       struct dpu_hw_blk_reg_map *b)
> +{
> +	int i;
> +
> +	for (i = 0; i < m->dsc_count; i++) {
> +		if (dsc == m->dsc[i].id) {
> +			b->base_off = addr;
> +			b->blk_off = m->dsc[i].base;
> +			b->length = m->dsc[i].len;
> +			b->hwversion = m->hwversion;
> +			b->log_mask = DPU_DBG_MASK_DSC;
> +			return &m->dsc[i];
> +		}
> +	}
> +
> +	return NULL;
> +}
> +
> +static void _setup_dsc_ops(struct dpu_hw_dsc_ops *ops,
> +			   unsigned long cap)
> +{
> +	ops->dsc_disable = dpu_hw_dsc_disable;
> +	ops->dsc_config = dpu_hw_dsc_config;
> +	ops->dsc_config_thresh = dpu_hw_dsc_config_thresh;
> +};
> +
> +static struct dpu_hw_blk_ops dpu_hw_ops = {
> +	.start = NULL,
> +	.stop = NULL,
> +};
> +
> +struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr,
> +				   struct dpu_mdss_cfg *m)
> +{
> +	struct dpu_hw_dsc *c;
> +	struct dpu_dsc_cfg *cfg;
> +
> +	c = kzalloc(sizeof(*c), GFP_KERNEL);
> +	if (!c)
> +		return ERR_PTR(-ENOMEM);
> +
> +	cfg = _dsc_offset(idx, m, addr, &c->hw);
> +	if (IS_ERR_OR_NULL(cfg)) {
> +		kfree(c);
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	c->idx = idx;
> +	c->caps = cfg;
> +	_setup_dsc_ops(&c->ops, c->caps->features);
> +
> +	dpu_hw_blk_init(&c->base, DPU_HW_BLK_DSC, idx, &dpu_hw_ops);
> +
> +	return c;
> +}
> +
> +void dpu_hw_dsc_destroy(struct dpu_hw_dsc *dsc)
> +{
> +	if (dsc)
> +		dpu_hw_blk_destroy(&dsc->base);
> +	kfree(dsc);
> +}
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
> new file mode 100644
> index 000000000000..c680fd948865
> --- /dev/null
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
> @@ -0,0 +1,79 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/* Copyright (c) 2020, Linaro Limited */
> +
> +#ifndef _DPU_HW_DSC_H
> +#define _DPU_HW_DSC_H
> +
> +#include <drm/drm_dsc.h>
> +
> +#define DSC_MODE_SPLIT_PANEL            BIT(0)
> +#define DSC_MODE_MULTIPLEX              BIT(1)
> +#define DSC_MODE_VIDEO                  BIT(2)
> +
> +struct dpu_hw_dsc;
> +
> +/**
> + * struct dpu_hw_dsc_ops - interface to the dsc hardware driver functions
> + * Assumption is these functions will be called after clocks are enabled
> + */
> +struct dpu_hw_dsc_ops {
> +	/**
> +	 * dsc_disable - disable dsc
> +	 * @hw_dsc: Pointer to dsc context
> +	 */
> +	void (*dsc_disable)(struct dpu_hw_dsc *hw_dsc);
> +
> +	/**
> +	 * dsc_config - configures dsc encoder
> +	 * @hw_dsc: Pointer to dsc context
> +	 * @dsc: panel dsc parameters
> +	 * @mode: dsc topology mode to be set
> +	 * @ich_reset_override: option to reset ich
> +	 */
> +	void (*dsc_config)(struct dpu_hw_dsc *hw_dsc,
> +			   struct msm_display_dsc_config *dsc,
> +			   u32 mode, bool ich_reset_override);
> +
> +	/**
> +	 * dsc_config_thresh - programs panel thresholds
> +	 * @hw_dsc: Pointer to dsc context
> +	 * @dsc: panel dsc parameters
> +	 */
> +	void (*dsc_config_thresh)(struct dpu_hw_dsc *hw_dsc,
> +				  struct msm_display_dsc_config *dsc);
> +};
> +
> +struct dpu_hw_dsc {
> +	struct dpu_hw_blk base;
> +	struct dpu_hw_blk_reg_map hw;
> +
> +	/* dsc */
> +	enum dpu_dsc idx;
> +	const struct dpu_dsc_cfg *caps;
> +
> +	/* ops */
> +	struct dpu_hw_dsc_ops ops;
> +};
> +
> +/**
> + * dpu_hw_dsc_init - initializes the dsc block for the passed dsc idx.
> + * @idx:  DSC index for which driver object is required
> + * @addr: Mapped register io address of MDP
> + * @m:    Pointer to mdss catalog data
> + * Returns: Error code or allocated dpu_hw_dsc context
> + */
> +struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr,
> +				   struct dpu_mdss_cfg *m);
> +
> +/**
> + * dpu_hw_dsc_destroy - destroys dsc driver context
> + * @dsc:   Pointer to dsc driver context returned by dpu_hw_dsc_init
> + */
> +void dpu_hw_dsc_destroy(struct dpu_hw_dsc *dsc);
> +
> +static inline struct dpu_hw_dsc *to_dpu_hw_dsc(struct dpu_hw_blk *hw)
> +{
> +	return container_of(hw, struct dpu_hw_dsc, base);
> +}
> +
> +#endif /* _DPU_HW_DSC_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 09a3fb3e89f5..1b72c11090ee 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> @@ -97,6 +97,7 @@ enum dpu_hw_blk_type {
>   	DPU_HW_BLK_WB,
>   	DPU_HW_BLK_DSPP,
>   	DPU_HW_BLK_MERGE_3D,
> +	DPU_HW_BLK_DSC,
>   	DPU_HW_BLK_MAX,
>   };
>   
> @@ -176,6 +177,17 @@ enum dpu_ctl {
>   	CTL_MAX
>   };
>   
> +enum dpu_dsc {
> +	DSC_NONE = 0,
> +	DSC_0,
> +	DSC_1,
> +	DSC_2,
> +	DSC_3,
> +	DSC_4,
> +	DSC_5,
> +	DSC_MAX
> +};
> +
>   enum dpu_pingpong {
>   	PINGPONG_0 = 1,
>   	PINGPONG_1,
> @@ -437,5 +449,6 @@ struct dpu_mdss_color {
>   #define DPU_DBG_MASK_VBIF     (1 << 8)
>   #define DPU_DBG_MASK_ROT      (1 << 9)
>   #define DPU_DBG_MASK_DSPP     (1 << 10)
> +#define DPU_DBG_MASK_DSC      (1 << 11)
>   
>   #endif  /* _DPU_HW_MDSS_H */
> 


-- 
With best wishes
Dmitry

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

* Re: [RFC PATCH 03/13] drm/msm/disp/dpu1: Add support for DSC
@ 2021-05-27 23:49     ` Dmitry Baryshkov
  0 siblings, 0 replies; 91+ messages in thread
From: Dmitry Baryshkov @ 2021-05-27 23:49 UTC (permalink / raw)
  To: Vinod Koul, Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, dri-devel, freedreno

On 21/05/2021 15:49, Vinod Koul wrote:
> Display Stream Compression (DSC) is one of the hw blocks in dpu, so add
> support by adding hw blocks for DSC
> 
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>   drivers/gpu/drm/msm/Makefile                  |   1 +
>   .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |  26 +++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c    | 221 ++++++++++++++++++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h    |  79 +++++++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 ++
>   5 files changed, 340 insertions(+)
>   create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
>   create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
> 
> diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
> index 610d630326bb..fd8fc57f1f58 100644
> --- a/drivers/gpu/drm/msm/Makefile
> +++ b/drivers/gpu/drm/msm/Makefile
> @@ -61,6 +61,7 @@ msm-y := \
>   	disp/dpu1/dpu_hw_blk.o \
>   	disp/dpu1/dpu_hw_catalog.o \
>   	disp/dpu1/dpu_hw_ctl.o \
> +	disp/dpu1/dpu_hw_dsc.o \
>   	disp/dpu1/dpu_hw_interrupts.o \
>   	disp/dpu1/dpu_hw_intf.o \
>   	disp/dpu1/dpu_hw_lm.o \
> 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 4dfd8a20ad5c..a699633f7013 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> @@ -165,6 +165,7 @@ enum {
>    * @DPU_PINGPONG_TE2        Additional tear check block for split pipes
>    * @DPU_PINGPONG_SPLIT      PP block supports split fifo
>    * @DPU_PINGPONG_SLAVE      PP block is a suitable slave for split fifo
> + * @DPU_PINGPONG_DSC        Display stream compression blocks

PP block supports DSC compression?

Also you don't seem to set it anywhere. Do we have hardware w/o DSC support?

>    * @DPU_PINGPONG_DITHER,    Dither blocks
>    * @DPU_PINGPONG_MAX
>    */
> @@ -173,10 +174,21 @@ enum {
>   	DPU_PINGPONG_TE2,
>   	DPU_PINGPONG_SPLIT,
>   	DPU_PINGPONG_SLAVE,
> +	DPU_PINGPONG_DSC,
>   	DPU_PINGPONG_DITHER,
>   	DPU_PINGPONG_MAX
>   };
>   
> +/**
> + * DSC sub-blocks
> + * @DPU_DSC		DSC sub block
> + * @DPU_DSC_MAX
> + */
> +enum {
> +	DPU_DSC = 0x1,
> +	DPU_DSC_MAX
> +};
> +

Unused

>   /**
>    * CTL sub-blocks
>    * @DPU_CTL_SPLIT_DISPLAY       CTL supports video mode split display
> @@ -413,6 +425,7 @@ struct dpu_dspp_sub_blks {
>   struct dpu_pingpong_sub_blks {
>   	struct dpu_pp_blk te;
>   	struct dpu_pp_blk te2;
> +	struct dpu_pp_blk dsc;
>   	struct dpu_pp_blk dither;
>   };

Unused


>   
> @@ -547,6 +560,16 @@ struct dpu_merge_3d_cfg  {
>   	const struct dpu_merge_3d_sub_blks *sblk;
>   };
>   
> +/**
> + * struct dpu_dsc_cfg - information of DSC blocks
> + * @id                 enum identifying this block
> + * @base               register offset of this block
> + * @features           bit mask identifying sub-blocks/features
> + */
> +struct dpu_dsc_cfg {
> +	DPU_HW_BLK_INFO;
> +};
> +
>   /**
>    * struct dpu_intf_cfg - information of timing engine blocks
>    * @id                 enum identifying this block
> @@ -748,6 +771,9 @@ struct dpu_mdss_cfg {
>   	u32 merge_3d_count;
>   	const struct dpu_merge_3d_cfg *merge_3d;
>   
> +	u32 dsc_count;
> +	struct dpu_dsc_cfg *dsc;
> +
>   	u32 intf_count;
>   	const struct dpu_intf_cfg *intf;
>   
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
> new file mode 100644
> index 000000000000..8b8d0553709d
> --- /dev/null
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
> @@ -0,0 +1,221 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2020, Linaro Limited
> + */
> +
> +#include "dpu_kms.h"
> +#include "dpu_hw_catalog.h"
> +#include "dpu_hwio.h"
> +#include "dpu_hw_mdss.h"
> +#include "dpu_hw_dsc.h"
> +
> +#define DSC_COMMON_MODE	                0x000
> +#define DSC_ENC                         0X004
> +#define DSC_PICTURE                     0x008
> +#define DSC_SLICE                       0x00C
> +#define DSC_CHUNK_SIZE                  0x010
> +#define DSC_DELAY                       0x014
> +#define DSC_SCALE_INITIAL               0x018
> +#define DSC_SCALE_DEC_INTERVAL          0x01C
> +#define DSC_SCALE_INC_INTERVAL          0x020
> +#define DSC_FIRST_LINE_BPG_OFFSET       0x024
> +#define DSC_BPG_OFFSET                  0x028
> +#define DSC_DSC_OFFSET                  0x02C
> +#define DSC_FLATNESS                    0x030
> +#define DSC_RC_MODEL_SIZE               0x034
> +#define DSC_RC                          0x038
> +#define DSC_RC_BUF_THRESH               0x03C
> +#define DSC_RANGE_MIN_QP                0x074
> +#define DSC_RANGE_MAX_QP                0x0B0
> +#define DSC_RANGE_BPG_OFFSET            0x0EC
> +
> +static void dpu_hw_dsc_disable(struct dpu_hw_dsc *dsc)
> +{
> +	struct dpu_hw_blk_reg_map *c = &dsc->hw;
> +
> +	DPU_REG_WRITE(c, DSC_COMMON_MODE, 0);
> +}
> +
> +static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
> +			      struct msm_display_dsc_config *dsc,
> +			      u32 mode, bool ich_reset_override)
> +{
> +	struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
> +	u32 data;
> +	u32 initial_lines = dsc->initial_lines;
> +	bool is_cmd_mode = !(mode & BIT(2));
> +
> +	DPU_REG_WRITE(c, DSC_COMMON_MODE, mode);
> +
> +	data = 0;
> +	if (ich_reset_override)
> +		data = 3 << 28;
> +
> +	if (is_cmd_mode)
> +		initial_lines += 1;
> +
> +	data |= (initial_lines << 20);
> +	data |= ((dsc->slice_last_group_size) << 18);
> +	/* bpp is 6.4 format, 4 LSBs bits are for fractional part */
> +	data |= dsc->drm.bits_per_pixel << 12;
> +	data |= (dsc->drm.block_pred_enable << 7);
> +	data |= (dsc->drm.line_buf_depth << 3);
> +	data |= (dsc->drm.simple_422 << 2);
> +	data |= (dsc->drm.convert_rgb << 1);
> +	if (dsc->drm.bits_per_component  == 10)
> +		data |= BIT(0);
> +
> +	DPU_REG_WRITE(c, DSC_ENC, data);
> +
> +	data = dsc->drm.pic_width << 16;
> +	data |= dsc->drm.pic_height;
> +	DPU_REG_WRITE(c, DSC_PICTURE, data);
> +
> +	data = dsc->drm.slice_width << 16;
> +	data |= dsc->drm.slice_height;
> +	DPU_REG_WRITE(c, DSC_SLICE, data);
> +
> +	data = DIV_ROUND_UP(dsc->drm.slice_width * dsc->drm.bits_per_pixel, 8) << 16;
> +
> +	DPU_REG_WRITE(c, DSC_CHUNK_SIZE, data);
> +
> +	data = dsc->drm.initial_dec_delay << 16;
> +	data |= dsc->drm.initial_xmit_delay;
> +	DPU_REG_WRITE(c, DSC_DELAY, data);
> +
> +	data = dsc->drm.initial_scale_value;
> +	DPU_REG_WRITE(c, DSC_SCALE_INITIAL, data);
> +
> +	data = dsc->drm.scale_decrement_interval;
> +	DPU_REG_WRITE(c, DSC_SCALE_DEC_INTERVAL, data);
> +
> +	data = 0x00000184; /* only this value works */
> +	DPU_REG_WRITE(c, DSC_SCALE_INC_INTERVAL, data);
> +
> +	data = dsc->drm.first_line_bpg_offset;
> +	DPU_REG_WRITE(c, DSC_FIRST_LINE_BPG_OFFSET, data);
> +
> +	data = dsc->drm.nfl_bpg_offset << 16;
> +	data |= dsc->drm.slice_bpg_offset;
> +	DPU_REG_WRITE(c, DSC_BPG_OFFSET, data);
> +
> +	data = dsc->drm.initial_offset << 16;
> +	data |= dsc->drm.final_offset;
> +	DPU_REG_WRITE(c, DSC_DSC_OFFSET, data);
> +
> +	data = dsc->det_thresh_flatness << 10;
> +	data |= dsc->drm.flatness_max_qp << 5;
> +	data |= dsc->drm.flatness_min_qp;
> +	DPU_REG_WRITE(c, DSC_FLATNESS, data);
> +
> +	data = dsc->drm.rc_model_size;
> +	DPU_REG_WRITE(c, DSC_RC_MODEL_SIZE, data);
> +
> +	data = dsc->drm.rc_tgt_offset_low << 18;
> +	data |= dsc->drm.rc_tgt_offset_high << 14;
> +	data |= dsc->drm.rc_quant_incr_limit1 << 9;
> +	data |= dsc->drm.rc_quant_incr_limit0 << 4;
> +	data |= dsc->drm.rc_edge_factor;
> +	DPU_REG_WRITE(c, DSC_RC, data);
> +}
> +
> +static void dpu_hw_dsc_config_thresh(struct dpu_hw_dsc *hw_dsc,
> +				     struct msm_display_dsc_config *dsc)
> +{
> +	struct drm_dsc_rc_range_parameters *rc = dsc->drm.rc_range_params;
> +	struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
> +	u32 off = 0x0;
> +	u16 *lp;
> +	int i;
> +
> +	lp = dsc->drm.rc_buf_thresh;
> +	off = DSC_RC_BUF_THRESH;
> +	for (i = 0; i < DSC_NUM_BUF_RANGES - 1 ; i++) {
> +		DPU_REG_WRITE(c, off, *lp++);
> +		off += 4;
> +	}
> +
> +	off = DSC_RANGE_MIN_QP;
> +	for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
> +		DPU_REG_WRITE(c, off, rc[i].range_min_qp);
> +		off += 4;
> +	}
> +
> +	off = DSC_RANGE_MAX_QP;
> +	for (i = 0; i < 15; i++) {
> +		DPU_REG_WRITE(c, off, rc[i].range_max_qp);
> +		off += 4;
> +	}
> +
> +	off = DSC_RANGE_BPG_OFFSET;
> +	for (i = 0; i < 15; i++) {
> +		DPU_REG_WRITE(c, off, rc[i].range_bpg_offset);
> +		off += 4;
> +	}
> +}
> +
> +static struct dpu_dsc_cfg *_dsc_offset(enum dpu_dsc dsc,
> +				       struct dpu_mdss_cfg *m,
> +				       void __iomem *addr,
> +				       struct dpu_hw_blk_reg_map *b)
> +{
> +	int i;
> +
> +	for (i = 0; i < m->dsc_count; i++) {
> +		if (dsc == m->dsc[i].id) {
> +			b->base_off = addr;
> +			b->blk_off = m->dsc[i].base;
> +			b->length = m->dsc[i].len;
> +			b->hwversion = m->hwversion;
> +			b->log_mask = DPU_DBG_MASK_DSC;
> +			return &m->dsc[i];
> +		}
> +	}
> +
> +	return NULL;
> +}
> +
> +static void _setup_dsc_ops(struct dpu_hw_dsc_ops *ops,
> +			   unsigned long cap)
> +{
> +	ops->dsc_disable = dpu_hw_dsc_disable;
> +	ops->dsc_config = dpu_hw_dsc_config;
> +	ops->dsc_config_thresh = dpu_hw_dsc_config_thresh;
> +};
> +
> +static struct dpu_hw_blk_ops dpu_hw_ops = {
> +	.start = NULL,
> +	.stop = NULL,
> +};
> +
> +struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr,
> +				   struct dpu_mdss_cfg *m)
> +{
> +	struct dpu_hw_dsc *c;
> +	struct dpu_dsc_cfg *cfg;
> +
> +	c = kzalloc(sizeof(*c), GFP_KERNEL);
> +	if (!c)
> +		return ERR_PTR(-ENOMEM);
> +
> +	cfg = _dsc_offset(idx, m, addr, &c->hw);
> +	if (IS_ERR_OR_NULL(cfg)) {
> +		kfree(c);
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	c->idx = idx;
> +	c->caps = cfg;
> +	_setup_dsc_ops(&c->ops, c->caps->features);
> +
> +	dpu_hw_blk_init(&c->base, DPU_HW_BLK_DSC, idx, &dpu_hw_ops);
> +
> +	return c;
> +}
> +
> +void dpu_hw_dsc_destroy(struct dpu_hw_dsc *dsc)
> +{
> +	if (dsc)
> +		dpu_hw_blk_destroy(&dsc->base);
> +	kfree(dsc);
> +}
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
> new file mode 100644
> index 000000000000..c680fd948865
> --- /dev/null
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
> @@ -0,0 +1,79 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/* Copyright (c) 2020, Linaro Limited */
> +
> +#ifndef _DPU_HW_DSC_H
> +#define _DPU_HW_DSC_H
> +
> +#include <drm/drm_dsc.h>
> +
> +#define DSC_MODE_SPLIT_PANEL            BIT(0)
> +#define DSC_MODE_MULTIPLEX              BIT(1)
> +#define DSC_MODE_VIDEO                  BIT(2)
> +
> +struct dpu_hw_dsc;
> +
> +/**
> + * struct dpu_hw_dsc_ops - interface to the dsc hardware driver functions
> + * Assumption is these functions will be called after clocks are enabled
> + */
> +struct dpu_hw_dsc_ops {
> +	/**
> +	 * dsc_disable - disable dsc
> +	 * @hw_dsc: Pointer to dsc context
> +	 */
> +	void (*dsc_disable)(struct dpu_hw_dsc *hw_dsc);
> +
> +	/**
> +	 * dsc_config - configures dsc encoder
> +	 * @hw_dsc: Pointer to dsc context
> +	 * @dsc: panel dsc parameters
> +	 * @mode: dsc topology mode to be set
> +	 * @ich_reset_override: option to reset ich
> +	 */
> +	void (*dsc_config)(struct dpu_hw_dsc *hw_dsc,
> +			   struct msm_display_dsc_config *dsc,
> +			   u32 mode, bool ich_reset_override);
> +
> +	/**
> +	 * dsc_config_thresh - programs panel thresholds
> +	 * @hw_dsc: Pointer to dsc context
> +	 * @dsc: panel dsc parameters
> +	 */
> +	void (*dsc_config_thresh)(struct dpu_hw_dsc *hw_dsc,
> +				  struct msm_display_dsc_config *dsc);
> +};
> +
> +struct dpu_hw_dsc {
> +	struct dpu_hw_blk base;
> +	struct dpu_hw_blk_reg_map hw;
> +
> +	/* dsc */
> +	enum dpu_dsc idx;
> +	const struct dpu_dsc_cfg *caps;
> +
> +	/* ops */
> +	struct dpu_hw_dsc_ops ops;
> +};
> +
> +/**
> + * dpu_hw_dsc_init - initializes the dsc block for the passed dsc idx.
> + * @idx:  DSC index for which driver object is required
> + * @addr: Mapped register io address of MDP
> + * @m:    Pointer to mdss catalog data
> + * Returns: Error code or allocated dpu_hw_dsc context
> + */
> +struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr,
> +				   struct dpu_mdss_cfg *m);
> +
> +/**
> + * dpu_hw_dsc_destroy - destroys dsc driver context
> + * @dsc:   Pointer to dsc driver context returned by dpu_hw_dsc_init
> + */
> +void dpu_hw_dsc_destroy(struct dpu_hw_dsc *dsc);
> +
> +static inline struct dpu_hw_dsc *to_dpu_hw_dsc(struct dpu_hw_blk *hw)
> +{
> +	return container_of(hw, struct dpu_hw_dsc, base);
> +}
> +
> +#endif /* _DPU_HW_DSC_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 09a3fb3e89f5..1b72c11090ee 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> @@ -97,6 +97,7 @@ enum dpu_hw_blk_type {
>   	DPU_HW_BLK_WB,
>   	DPU_HW_BLK_DSPP,
>   	DPU_HW_BLK_MERGE_3D,
> +	DPU_HW_BLK_DSC,
>   	DPU_HW_BLK_MAX,
>   };
>   
> @@ -176,6 +177,17 @@ enum dpu_ctl {
>   	CTL_MAX
>   };
>   
> +enum dpu_dsc {
> +	DSC_NONE = 0,
> +	DSC_0,
> +	DSC_1,
> +	DSC_2,
> +	DSC_3,
> +	DSC_4,
> +	DSC_5,
> +	DSC_MAX
> +};
> +
>   enum dpu_pingpong {
>   	PINGPONG_0 = 1,
>   	PINGPONG_1,
> @@ -437,5 +449,6 @@ struct dpu_mdss_color {
>   #define DPU_DBG_MASK_VBIF     (1 << 8)
>   #define DPU_DBG_MASK_ROT      (1 << 9)
>   #define DPU_DBG_MASK_DSPP     (1 << 10)
> +#define DPU_DBG_MASK_DSC      (1 << 11)
>   
>   #endif  /* _DPU_HW_MDSS_H */
> 


-- 
With best wishes
Dmitry

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

* Re: [RFC PATCH 03/13] drm/msm/dsi: add support for dsc data
  2021-05-21 12:49   ` Vinod Koul
@ 2021-05-28 10:29     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 91+ messages in thread
From: Dmitry Baryshkov @ 2021-05-28 10:29 UTC (permalink / raw)
  To: Vinod Koul, Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, David Airlie, Daniel Vetter,
	Jonathan Marek, Abhinav Kumar, linux-kernel, dri-devel,
	freedreno

On 21/05/2021 15:49, Vinod Koul wrote:
> DSC needs some configuration from device tree, add support to read and
> store these params and add DSC structures in msm_drv
> 
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>   drivers/gpu/drm/msm/dsi/dsi_host.c | 170 +++++++++++++++++++++++++++++
>   drivers/gpu/drm/msm/msm_drv.h      |  32 ++++++
>   2 files changed, 202 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
> index 8a10e4343281..864d3c655e73 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_host.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
> @@ -156,6 +156,7 @@ struct msm_dsi_host {
>   	struct regmap *sfpb;
>   
>   	struct drm_display_mode *mode;
> +	struct msm_display_dsc_config *dsc;
>   
>   	/* connected device info */
>   	struct device_node *device_node;
> @@ -1744,6 +1745,168 @@ static int dsi_host_parse_lane_data(struct msm_dsi_host *msm_host,
>   	return -EINVAL;
>   }
>   
> +static u32 dsi_dsc_rc_buf_thresh[DSC_NUM_BUF_RANGES - 1] = {
> +	0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, 0x62,
> +	0x69, 0x70, 0x77, 0x79, 0x7b, 0x7d, 0x7e
> +};

I think we should move this table to a generic place. AMD and Intel DSC 
code uses the same table, shifted by 6 (and both of those drivers shift 
it before writing to the HW). Intel modifies this table for 6bpp case. 
AMD seems to use it as is.

> +
> +/* only 8bpc, 8bpp added */
> +static char min_qp[DSC_NUM_BUF_RANGES] = {
> +	0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 13
> +};
> +
> +static char max_qp[DSC_NUM_BUF_RANGES] = {
> +	4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 11, 12, 13, 13, 15
> +};
> +
> +static char bpg_offset[DSC_NUM_BUF_RANGES] = {
> +	2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12
> +};

And these parameters seem to be generic too. Intel DSC code contains 
them in a bit different form. Should we probably move them to the 
drm_dsc.c and use the tables the generic location?

AMD drivers uses a bit different values at the first glance, so let's 
stick with Intel version.

> +
> +static int dsi_populate_dsc_params(struct msm_display_dsc_config *dsc)
> +{
> +	int i;
> +
> +	dsc->drm.rc_model_size = 8192;
> +	dsc->drm.first_line_bpg_offset = 15;
> +	dsc->drm.rc_edge_factor = 6;
> +	dsc->drm.rc_tgt_offset_high = 3;
> +	dsc->drm.rc_tgt_offset_low = 3;
> +	dsc->drm.simple_422 = 0;
> +	dsc->drm.convert_rgb = 1;
> +	dsc->drm.vbr_enable = 0;
> +
> +	/* handle only bpp = bpc = 8 */
> +	for (i = 0; i < DSC_NUM_BUF_RANGES - 1 ; i++)
> +		dsc->drm.rc_buf_thresh[i] = dsi_dsc_rc_buf_thresh[i];
> +
> +	for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
> +		dsc->drm.rc_range_params[i].range_min_qp = min_qp[i];
> +		dsc->drm.rc_range_params[i].range_max_qp = max_qp[i];
> +		dsc->drm.rc_range_params[i].range_bpg_offset = bpg_offset[i];
> +	}
> +
> +	dsc->drm.initial_offset = 6144;
> +	dsc->drm.initial_xmit_delay = 512;
> +	dsc->drm.initial_scale_value = 32;
> +	dsc->drm.first_line_bpg_offset = 12;
> +	dsc->drm.line_buf_depth = dsc->drm.bits_per_component + 1;
> +
> +	/* bpc 8 */
> +	dsc->drm.flatness_min_qp = 3;
> +	dsc->drm.flatness_max_qp = 12;
> +	dsc->det_thresh_flatness = 7;
> +	dsc->drm.rc_quant_incr_limit0 = 11;
> +	dsc->drm.rc_quant_incr_limit1 = 11;
> +	dsc->drm.mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC;
> +
> +	/* FIXME: need to call drm_dsc_compute_rc_parameters() so that rest of
> +	 * params are calculated
> +	 */
> +
> +	i = dsc->drm.slice_width % 3;
> +	switch (i) {
> +	case 0:
> +		dsc->slice_last_group_size = 2;
> +		break;
> +
> +	case 1:
> +		dsc->slice_last_group_size = 0;
> +		break;
> +
> +	case 2:
> +		dsc->slice_last_group_size = 0;
> +		break;
> +
> +	default:
> +		break;
> +	}
> +
> +	return 0;
> +}
> +


-- 
With best wishes
Dmitry

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

* Re: [RFC PATCH 03/13] drm/msm/dsi: add support for dsc data
@ 2021-05-28 10:29     ` Dmitry Baryshkov
  0 siblings, 0 replies; 91+ messages in thread
From: Dmitry Baryshkov @ 2021-05-28 10:29 UTC (permalink / raw)
  To: Vinod Koul, Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, dri-devel, freedreno

On 21/05/2021 15:49, Vinod Koul wrote:
> DSC needs some configuration from device tree, add support to read and
> store these params and add DSC structures in msm_drv
> 
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>   drivers/gpu/drm/msm/dsi/dsi_host.c | 170 +++++++++++++++++++++++++++++
>   drivers/gpu/drm/msm/msm_drv.h      |  32 ++++++
>   2 files changed, 202 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
> index 8a10e4343281..864d3c655e73 100644
> --- a/drivers/gpu/drm/msm/dsi/dsi_host.c
> +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
> @@ -156,6 +156,7 @@ struct msm_dsi_host {
>   	struct regmap *sfpb;
>   
>   	struct drm_display_mode *mode;
> +	struct msm_display_dsc_config *dsc;
>   
>   	/* connected device info */
>   	struct device_node *device_node;
> @@ -1744,6 +1745,168 @@ static int dsi_host_parse_lane_data(struct msm_dsi_host *msm_host,
>   	return -EINVAL;
>   }
>   
> +static u32 dsi_dsc_rc_buf_thresh[DSC_NUM_BUF_RANGES - 1] = {
> +	0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, 0x62,
> +	0x69, 0x70, 0x77, 0x79, 0x7b, 0x7d, 0x7e
> +};

I think we should move this table to a generic place. AMD and Intel DSC 
code uses the same table, shifted by 6 (and both of those drivers shift 
it before writing to the HW). Intel modifies this table for 6bpp case. 
AMD seems to use it as is.

> +
> +/* only 8bpc, 8bpp added */
> +static char min_qp[DSC_NUM_BUF_RANGES] = {
> +	0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 13
> +};
> +
> +static char max_qp[DSC_NUM_BUF_RANGES] = {
> +	4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 11, 12, 13, 13, 15
> +};
> +
> +static char bpg_offset[DSC_NUM_BUF_RANGES] = {
> +	2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12
> +};

And these parameters seem to be generic too. Intel DSC code contains 
them in a bit different form. Should we probably move them to the 
drm_dsc.c and use the tables the generic location?

AMD drivers uses a bit different values at the first glance, so let's 
stick with Intel version.

> +
> +static int dsi_populate_dsc_params(struct msm_display_dsc_config *dsc)
> +{
> +	int i;
> +
> +	dsc->drm.rc_model_size = 8192;
> +	dsc->drm.first_line_bpg_offset = 15;
> +	dsc->drm.rc_edge_factor = 6;
> +	dsc->drm.rc_tgt_offset_high = 3;
> +	dsc->drm.rc_tgt_offset_low = 3;
> +	dsc->drm.simple_422 = 0;
> +	dsc->drm.convert_rgb = 1;
> +	dsc->drm.vbr_enable = 0;
> +
> +	/* handle only bpp = bpc = 8 */
> +	for (i = 0; i < DSC_NUM_BUF_RANGES - 1 ; i++)
> +		dsc->drm.rc_buf_thresh[i] = dsi_dsc_rc_buf_thresh[i];
> +
> +	for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
> +		dsc->drm.rc_range_params[i].range_min_qp = min_qp[i];
> +		dsc->drm.rc_range_params[i].range_max_qp = max_qp[i];
> +		dsc->drm.rc_range_params[i].range_bpg_offset = bpg_offset[i];
> +	}
> +
> +	dsc->drm.initial_offset = 6144;
> +	dsc->drm.initial_xmit_delay = 512;
> +	dsc->drm.initial_scale_value = 32;
> +	dsc->drm.first_line_bpg_offset = 12;
> +	dsc->drm.line_buf_depth = dsc->drm.bits_per_component + 1;
> +
> +	/* bpc 8 */
> +	dsc->drm.flatness_min_qp = 3;
> +	dsc->drm.flatness_max_qp = 12;
> +	dsc->det_thresh_flatness = 7;
> +	dsc->drm.rc_quant_incr_limit0 = 11;
> +	dsc->drm.rc_quant_incr_limit1 = 11;
> +	dsc->drm.mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC;
> +
> +	/* FIXME: need to call drm_dsc_compute_rc_parameters() so that rest of
> +	 * params are calculated
> +	 */
> +
> +	i = dsc->drm.slice_width % 3;
> +	switch (i) {
> +	case 0:
> +		dsc->slice_last_group_size = 2;
> +		break;
> +
> +	case 1:
> +		dsc->slice_last_group_size = 0;
> +		break;
> +
> +	case 2:
> +		dsc->slice_last_group_size = 0;
> +		break;
> +
> +	default:
> +		break;
> +	}
> +
> +	return 0;
> +}
> +


-- 
With best wishes
Dmitry

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

* Re: [RFC PATCH 04/13] drm/msm/disp/dpu1: Add support for DSC
  2021-05-21 12:49   ` Vinod Koul
@ 2021-05-28 10:31     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 91+ messages in thread
From: Dmitry Baryshkov @ 2021-05-28 10:31 UTC (permalink / raw)
  To: Vinod Koul, Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, David Airlie, Daniel Vetter,
	Jonathan Marek, Abhinav Kumar, linux-kernel, dri-devel,
	freedreno

On 21/05/2021 15:49, Vinod Koul wrote:
> Display Stream Compression (DSC) is one of the hw blocks in dpu, so add
> support by adding hw blocks for DSC
> 
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>   drivers/gpu/drm/msm/Makefile                  |   1 +
>   .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |  26 +++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c    | 221 ++++++++++++++++++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h    |  79 +++++++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 ++
>   5 files changed, 340 insertions(+)
>   create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
>   create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
> 
> diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
> index 610d630326bb..fd8fc57f1f58 100644
> --- a/drivers/gpu/drm/msm/Makefile
> +++ b/drivers/gpu/drm/msm/Makefile
> @@ -61,6 +61,7 @@ msm-y := \
>   	disp/dpu1/dpu_hw_blk.o \
>   	disp/dpu1/dpu_hw_catalog.o \
>   	disp/dpu1/dpu_hw_ctl.o \
> +	disp/dpu1/dpu_hw_dsc.o \
>   	disp/dpu1/dpu_hw_interrupts.o \
>   	disp/dpu1/dpu_hw_intf.o \
>   	disp/dpu1/dpu_hw_lm.o \
> 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 4dfd8a20ad5c..a699633f7013 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> @@ -165,6 +165,7 @@ enum {
>    * @DPU_PINGPONG_TE2        Additional tear check block for split pipes
>    * @DPU_PINGPONG_SPLIT      PP block supports split fifo
>    * @DPU_PINGPONG_SLAVE      PP block is a suitable slave for split fifo
> + * @DPU_PINGPONG_DSC        Display stream compression blocks
>    * @DPU_PINGPONG_DITHER,    Dither blocks
>    * @DPU_PINGPONG_MAX
>    */
> @@ -173,10 +174,21 @@ enum {
>   	DPU_PINGPONG_TE2,
>   	DPU_PINGPONG_SPLIT,
>   	DPU_PINGPONG_SLAVE,
> +	DPU_PINGPONG_DSC,
>   	DPU_PINGPONG_DITHER,
>   	DPU_PINGPONG_MAX
>   };
>   
> +/**
> + * DSC sub-blocks
> + * @DPU_DSC		DSC sub block
> + * @DPU_DSC_MAX
> + */
> +enum {
> +	DPU_DSC = 0x1,
> +	DPU_DSC_MAX
> +};

I don't think we need this. DSC is always a DSC. You can safely pass (0) 
as a features mask.

Once we'd have to add 1.2 block revision support, we might have to add 
it here.

> +
>   /**
>    * CTL sub-blocks
>    * @DPU_CTL_SPLIT_DISPLAY       CTL supports video mode split display
> @@ -413,6 +425,7 @@ struct dpu_dspp_sub_blks {
>   struct dpu_pingpong_sub_blks {
>   	struct dpu_pp_blk te;
>   	struct dpu_pp_blk te2;
> +	struct dpu_pp_blk dsc;

Is this used?


>   	struct dpu_pp_blk dither;
>   };
>   
> @@ -547,6 +560,16 @@ struct dpu_merge_3d_cfg  {
>   	const struct dpu_merge_3d_sub_blks *sblk;
>   };
>   
> +/**
> + * struct dpu_dsc_cfg - information of DSC blocks
> + * @id                 enum identifying this block
> + * @base               register offset of this block
> + * @features           bit mask identifying sub-blocks/features
> + */
> +struct dpu_dsc_cfg {
> +	DPU_HW_BLK_INFO;
> +};
> +
>   /**
>    * struct dpu_intf_cfg - information of timing engine blocks
>    * @id                 enum identifying this block
> @@ -748,6 +771,9 @@ struct dpu_mdss_cfg {
>   	u32 merge_3d_count;
>   	const struct dpu_merge_3d_cfg *merge_3d;
>   
> +	u32 dsc_count;
> +	struct dpu_dsc_cfg *dsc;
> +
>   	u32 intf_count;
>   	const struct dpu_intf_cfg *intf;
>   
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
> new file mode 100644
> index 000000000000..8b8d0553709d
> --- /dev/null
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
> @@ -0,0 +1,221 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2020, Linaro Limited
> + */
> +
> +#include "dpu_kms.h"
> +#include "dpu_hw_catalog.h"
> +#include "dpu_hwio.h"
> +#include "dpu_hw_mdss.h"
> +#include "dpu_hw_dsc.h"
> +
> +#define DSC_COMMON_MODE	                0x000
> +#define DSC_ENC                         0X004
> +#define DSC_PICTURE                     0x008
> +#define DSC_SLICE                       0x00C
> +#define DSC_CHUNK_SIZE                  0x010
> +#define DSC_DELAY                       0x014
> +#define DSC_SCALE_INITIAL               0x018
> +#define DSC_SCALE_DEC_INTERVAL          0x01C
> +#define DSC_SCALE_INC_INTERVAL          0x020
> +#define DSC_FIRST_LINE_BPG_OFFSET       0x024
> +#define DSC_BPG_OFFSET                  0x028
> +#define DSC_DSC_OFFSET                  0x02C
> +#define DSC_FLATNESS                    0x030
> +#define DSC_RC_MODEL_SIZE               0x034
> +#define DSC_RC                          0x038
> +#define DSC_RC_BUF_THRESH               0x03C
> +#define DSC_RANGE_MIN_QP                0x074
> +#define DSC_RANGE_MAX_QP                0x0B0
> +#define DSC_RANGE_BPG_OFFSET            0x0EC
> +
> +static void dpu_hw_dsc_disable(struct dpu_hw_dsc *dsc)
> +{
> +	struct dpu_hw_blk_reg_map *c = &dsc->hw;
> +
> +	DPU_REG_WRITE(c, DSC_COMMON_MODE, 0);
> +}
> +
> +static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
> +			      struct msm_display_dsc_config *dsc,
> +			      u32 mode, bool ich_reset_override)
> +{
> +	struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
> +	u32 data;
> +	u32 initial_lines = dsc->initial_lines;
> +	bool is_cmd_mode = !(mode & BIT(2));
> +
> +	DPU_REG_WRITE(c, DSC_COMMON_MODE, mode);
> +
> +	data = 0;
> +	if (ich_reset_override)
> +		data = 3 << 28;

Do we need this? It seems this is only necessary for the half panel 
partial updates, which is not enabled for now. Do you know if this is 
really handy at this point or if it's an odd case? We might drop the 
ich_reset logic alltogether and add it later if/when the need arises.

> +
> +	if (is_cmd_mode)
> +		initial_lines += 1;
> +
> +	data |= (initial_lines << 20);
> +	data |= ((dsc->slice_last_group_size) << 18);
> +	/* bpp is 6.4 format, 4 LSBs bits are for fractional part */
> +	data |= dsc->drm.bits_per_pixel << 12;
> +	data |= (dsc->drm.block_pred_enable << 7);
> +	data |= (dsc->drm.line_buf_depth << 3);
> +	data |= (dsc->drm.simple_422 << 2);
> +	data |= (dsc->drm.convert_rgb << 1);
> +	if (dsc->drm.bits_per_component  == 10)
> +		data |= BIT(0);
> +
> +	DPU_REG_WRITE(c, DSC_ENC, data);
> +
> +	data = dsc->drm.pic_width << 16;
> +	data |= dsc->drm.pic_height;
> +	DPU_REG_WRITE(c, DSC_PICTURE, data);
> +
> +	data = dsc->drm.slice_width << 16;
> +	data |= dsc->drm.slice_height;
> +	DPU_REG_WRITE(c, DSC_SLICE, data);
> +
> +	data = DIV_ROUND_UP(dsc->drm.slice_width * dsc->drm.bits_per_pixel, 8) << 16;
> +
> +	DPU_REG_WRITE(c, DSC_CHUNK_SIZE, data);
> +
> +	data = dsc->drm.initial_dec_delay << 16;
> +	data |= dsc->drm.initial_xmit_delay;
> +	DPU_REG_WRITE(c, DSC_DELAY, data);
> +
> +	data = dsc->drm.initial_scale_value;
> +	DPU_REG_WRITE(c, DSC_SCALE_INITIAL, data);
> +
> +	data = dsc->drm.scale_decrement_interval;
> +	DPU_REG_WRITE(c, DSC_SCALE_DEC_INTERVAL, data);
> +
> +	data = 0x00000184; /* only this value works */
> +	DPU_REG_WRITE(c, DSC_SCALE_INC_INTERVAL, data);
> +
> +	data = dsc->drm.first_line_bpg_offset;
> +	DPU_REG_WRITE(c, DSC_FIRST_LINE_BPG_OFFSET, data);
> +
> +	data = dsc->drm.nfl_bpg_offset << 16;
> +	data |= dsc->drm.slice_bpg_offset;
> +	DPU_REG_WRITE(c, DSC_BPG_OFFSET, data);
> +
> +	data = dsc->drm.initial_offset << 16;
> +	data |= dsc->drm.final_offset;
> +	DPU_REG_WRITE(c, DSC_DSC_OFFSET, data);
> +
> +	data = dsc->det_thresh_flatness << 10;
> +	data |= dsc->drm.flatness_max_qp << 5;
> +	data |= dsc->drm.flatness_min_qp;
> +	DPU_REG_WRITE(c, DSC_FLATNESS, data);
> +
> +	data = dsc->drm.rc_model_size;
> +	DPU_REG_WRITE(c, DSC_RC_MODEL_SIZE, data);
> +
> +	data = dsc->drm.rc_tgt_offset_low << 18;
> +	data |= dsc->drm.rc_tgt_offset_high << 14;
> +	data |= dsc->drm.rc_quant_incr_limit1 << 9;
> +	data |= dsc->drm.rc_quant_incr_limit0 << 4;
> +	data |= dsc->drm.rc_edge_factor;
> +	DPU_REG_WRITE(c, DSC_RC, data);
> +}
> +
> +static void dpu_hw_dsc_config_thresh(struct dpu_hw_dsc *hw_dsc,
> +				     struct msm_display_dsc_config *dsc)
> +{
> +	struct drm_dsc_rc_range_parameters *rc = dsc->drm.rc_range_params;
> +	struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
> +	u32 off = 0x0;
> +	u16 *lp;
> +	int i;
> +
> +	lp = dsc->drm.rc_buf_thresh;
> +	off = DSC_RC_BUF_THRESH;
> +	for (i = 0; i < DSC_NUM_BUF_RANGES - 1 ; i++) {
> +		DPU_REG_WRITE(c, off, *lp++);

Nit: no need for lp here. Use array access like you do below.

> +		off += 4;
> +	}
> +
> +	off = DSC_RANGE_MIN_QP;
> +	for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
> +		DPU_REG_WRITE(c, off, rc[i].range_min_qp);
> +		off += 4;
> +	}
> +
> +	off = DSC_RANGE_MAX_QP;
> +	for (i = 0; i < 15; i++) {
> +		DPU_REG_WRITE(c, off, rc[i].range_max_qp);
> +		off += 4;
> +	}
> +
> +	off = DSC_RANGE_BPG_OFFSET;
> +	for (i = 0; i < 15; i++) {
> +		DPU_REG_WRITE(c, off, rc[i].range_bpg_offset);
> +		off += 4;
> +	}



> +}
> +
> +static struct dpu_dsc_cfg *_dsc_offset(enum dpu_dsc dsc,
> +				       struct dpu_mdss_cfg *m,
> +				       void __iomem *addr,
> +				       struct dpu_hw_blk_reg_map *b)
> +{
> +	int i;
> +
> +	for (i = 0; i < m->dsc_count; i++) {
> +		if (dsc == m->dsc[i].id) {
> +			b->base_off = addr;
> +			b->blk_off = m->dsc[i].base;
> +			b->length = m->dsc[i].len;
> +			b->hwversion = m->hwversion;
> +			b->log_mask = DPU_DBG_MASK_DSC;
> +			return &m->dsc[i];
> +		}
> +	}
> +
> +	return NULL;
> +}
> +
> +static void _setup_dsc_ops(struct dpu_hw_dsc_ops *ops,
> +			   unsigned long cap)
> +{
> +	ops->dsc_disable = dpu_hw_dsc_disable;
> +	ops->dsc_config = dpu_hw_dsc_config;
> +	ops->dsc_config_thresh = dpu_hw_dsc_config_thresh;
> +};
> +
> +static struct dpu_hw_blk_ops dpu_hw_ops = {
> +	.start = NULL,
> +	.stop = NULL,
> +};
> +
> +struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr,
> +				   struct dpu_mdss_cfg *m)
> +{
> +	struct dpu_hw_dsc *c;
> +	struct dpu_dsc_cfg *cfg;
> +
> +	c = kzalloc(sizeof(*c), GFP_KERNEL);
> +	if (!c)
> +		return ERR_PTR(-ENOMEM);
> +
> +	cfg = _dsc_offset(idx, m, addr, &c->hw);
> +	if (IS_ERR_OR_NULL(cfg)) {
> +		kfree(c);
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	c->idx = idx;
> +	c->caps = cfg;
> +	_setup_dsc_ops(&c->ops, c->caps->features);
> +
> +	dpu_hw_blk_init(&c->base, DPU_HW_BLK_DSC, idx, &dpu_hw_ops);
> +
> +	return c;
> +}
> +
> +void dpu_hw_dsc_destroy(struct dpu_hw_dsc *dsc)
> +{
> +	if (dsc)
> +		dpu_hw_blk_destroy(&dsc->base);
> +	kfree(dsc);
> +}
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
> new file mode 100644
> index 000000000000..c680fd948865
> --- /dev/null
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
> @@ -0,0 +1,79 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/* Copyright (c) 2020, Linaro Limited */
> +
> +#ifndef _DPU_HW_DSC_H
> +#define _DPU_HW_DSC_H
> +
> +#include <drm/drm_dsc.h>
> +
> +#define DSC_MODE_SPLIT_PANEL            BIT(0)
> +#define DSC_MODE_MULTIPLEX              BIT(1)
> +#define DSC_MODE_VIDEO                  BIT(2)
> +
> +struct dpu_hw_dsc;
> +
> +/**
> + * struct dpu_hw_dsc_ops - interface to the dsc hardware driver functions
> + * Assumption is these functions will be called after clocks are enabled
> + */
> +struct dpu_hw_dsc_ops {
> +	/**
> +	 * dsc_disable - disable dsc
> +	 * @hw_dsc: Pointer to dsc context
> +	 */
> +	void (*dsc_disable)(struct dpu_hw_dsc *hw_dsc);
> +
> +	/**
> +	 * dsc_config - configures dsc encoder
> +	 * @hw_dsc: Pointer to dsc context
> +	 * @dsc: panel dsc parameters
> +	 * @mode: dsc topology mode to be set
> +	 * @ich_reset_override: option to reset ich
> +	 */
> +	void (*dsc_config)(struct dpu_hw_dsc *hw_dsc,
> +			   struct msm_display_dsc_config *dsc,
> +			   u32 mode, bool ich_reset_override);
> +
> +	/**
> +	 * dsc_config_thresh - programs panel thresholds
> +	 * @hw_dsc: Pointer to dsc context
> +	 * @dsc: panel dsc parameters
> +	 */
> +	void (*dsc_config_thresh)(struct dpu_hw_dsc *hw_dsc,
> +				  struct msm_display_dsc_config *dsc);
> +};
> +
> +struct dpu_hw_dsc {
> +	struct dpu_hw_blk base;
> +	struct dpu_hw_blk_reg_map hw;
> +
> +	/* dsc */
> +	enum dpu_dsc idx;
> +	const struct dpu_dsc_cfg *caps;
> +
> +	/* ops */
> +	struct dpu_hw_dsc_ops ops;
> +};
> +
> +/**
> + * dpu_hw_dsc_init - initializes the dsc block for the passed dsc idx.
> + * @idx:  DSC index for which driver object is required
> + * @addr: Mapped register io address of MDP
> + * @m:    Pointer to mdss catalog data
> + * Returns: Error code or allocated dpu_hw_dsc context
> + */
> +struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr,
> +				   struct dpu_mdss_cfg *m);
> +
> +/**
> + * dpu_hw_dsc_destroy - destroys dsc driver context
> + * @dsc:   Pointer to dsc driver context returned by dpu_hw_dsc_init
> + */
> +void dpu_hw_dsc_destroy(struct dpu_hw_dsc *dsc);
> +
> +static inline struct dpu_hw_dsc *to_dpu_hw_dsc(struct dpu_hw_blk *hw)
> +{
> +	return container_of(hw, struct dpu_hw_dsc, base);
> +}
> +
> +#endif /* _DPU_HW_DSC_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 09a3fb3e89f5..1b72c11090ee 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> @@ -97,6 +97,7 @@ enum dpu_hw_blk_type {
>   	DPU_HW_BLK_WB,
>   	DPU_HW_BLK_DSPP,
>   	DPU_HW_BLK_MERGE_3D,
> +	DPU_HW_BLK_DSC,
>   	DPU_HW_BLK_MAX,
>   };
>   
> @@ -176,6 +177,17 @@ enum dpu_ctl {
>   	CTL_MAX
>   };
>   
> +enum dpu_dsc {
> +	DSC_NONE = 0,
> +	DSC_0,
> +	DSC_1,
> +	DSC_2,
> +	DSC_3,
> +	DSC_4,
> +	DSC_5,
> +	DSC_MAX
> +};
> +
>   enum dpu_pingpong {
>   	PINGPONG_0 = 1,
>   	PINGPONG_1,
> @@ -437,5 +449,6 @@ struct dpu_mdss_color {
>   #define DPU_DBG_MASK_VBIF     (1 << 8)
>   #define DPU_DBG_MASK_ROT      (1 << 9)
>   #define DPU_DBG_MASK_DSPP     (1 << 10)
> +#define DPU_DBG_MASK_DSC      (1 << 11)
>   
>   #endif  /* _DPU_HW_MDSS_H */
> 


-- 
With best wishes
Dmitry

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

* Re: [RFC PATCH 04/13] drm/msm/disp/dpu1: Add support for DSC
@ 2021-05-28 10:31     ` Dmitry Baryshkov
  0 siblings, 0 replies; 91+ messages in thread
From: Dmitry Baryshkov @ 2021-05-28 10:31 UTC (permalink / raw)
  To: Vinod Koul, Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, dri-devel, freedreno

On 21/05/2021 15:49, Vinod Koul wrote:
> Display Stream Compression (DSC) is one of the hw blocks in dpu, so add
> support by adding hw blocks for DSC
> 
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>   drivers/gpu/drm/msm/Makefile                  |   1 +
>   .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h    |  26 +++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c    | 221 ++++++++++++++++++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h    |  79 +++++++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 ++
>   5 files changed, 340 insertions(+)
>   create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
>   create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
> 
> diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
> index 610d630326bb..fd8fc57f1f58 100644
> --- a/drivers/gpu/drm/msm/Makefile
> +++ b/drivers/gpu/drm/msm/Makefile
> @@ -61,6 +61,7 @@ msm-y := \
>   	disp/dpu1/dpu_hw_blk.o \
>   	disp/dpu1/dpu_hw_catalog.o \
>   	disp/dpu1/dpu_hw_ctl.o \
> +	disp/dpu1/dpu_hw_dsc.o \
>   	disp/dpu1/dpu_hw_interrupts.o \
>   	disp/dpu1/dpu_hw_intf.o \
>   	disp/dpu1/dpu_hw_lm.o \
> 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 4dfd8a20ad5c..a699633f7013 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
> @@ -165,6 +165,7 @@ enum {
>    * @DPU_PINGPONG_TE2        Additional tear check block for split pipes
>    * @DPU_PINGPONG_SPLIT      PP block supports split fifo
>    * @DPU_PINGPONG_SLAVE      PP block is a suitable slave for split fifo
> + * @DPU_PINGPONG_DSC        Display stream compression blocks
>    * @DPU_PINGPONG_DITHER,    Dither blocks
>    * @DPU_PINGPONG_MAX
>    */
> @@ -173,10 +174,21 @@ enum {
>   	DPU_PINGPONG_TE2,
>   	DPU_PINGPONG_SPLIT,
>   	DPU_PINGPONG_SLAVE,
> +	DPU_PINGPONG_DSC,
>   	DPU_PINGPONG_DITHER,
>   	DPU_PINGPONG_MAX
>   };
>   
> +/**
> + * DSC sub-blocks
> + * @DPU_DSC		DSC sub block
> + * @DPU_DSC_MAX
> + */
> +enum {
> +	DPU_DSC = 0x1,
> +	DPU_DSC_MAX
> +};

I don't think we need this. DSC is always a DSC. You can safely pass (0) 
as a features mask.

Once we'd have to add 1.2 block revision support, we might have to add 
it here.

> +
>   /**
>    * CTL sub-blocks
>    * @DPU_CTL_SPLIT_DISPLAY       CTL supports video mode split display
> @@ -413,6 +425,7 @@ struct dpu_dspp_sub_blks {
>   struct dpu_pingpong_sub_blks {
>   	struct dpu_pp_blk te;
>   	struct dpu_pp_blk te2;
> +	struct dpu_pp_blk dsc;

Is this used?


>   	struct dpu_pp_blk dither;
>   };
>   
> @@ -547,6 +560,16 @@ struct dpu_merge_3d_cfg  {
>   	const struct dpu_merge_3d_sub_blks *sblk;
>   };
>   
> +/**
> + * struct dpu_dsc_cfg - information of DSC blocks
> + * @id                 enum identifying this block
> + * @base               register offset of this block
> + * @features           bit mask identifying sub-blocks/features
> + */
> +struct dpu_dsc_cfg {
> +	DPU_HW_BLK_INFO;
> +};
> +
>   /**
>    * struct dpu_intf_cfg - information of timing engine blocks
>    * @id                 enum identifying this block
> @@ -748,6 +771,9 @@ struct dpu_mdss_cfg {
>   	u32 merge_3d_count;
>   	const struct dpu_merge_3d_cfg *merge_3d;
>   
> +	u32 dsc_count;
> +	struct dpu_dsc_cfg *dsc;
> +
>   	u32 intf_count;
>   	const struct dpu_intf_cfg *intf;
>   
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
> new file mode 100644
> index 000000000000..8b8d0553709d
> --- /dev/null
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
> @@ -0,0 +1,221 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2020, Linaro Limited
> + */
> +
> +#include "dpu_kms.h"
> +#include "dpu_hw_catalog.h"
> +#include "dpu_hwio.h"
> +#include "dpu_hw_mdss.h"
> +#include "dpu_hw_dsc.h"
> +
> +#define DSC_COMMON_MODE	                0x000
> +#define DSC_ENC                         0X004
> +#define DSC_PICTURE                     0x008
> +#define DSC_SLICE                       0x00C
> +#define DSC_CHUNK_SIZE                  0x010
> +#define DSC_DELAY                       0x014
> +#define DSC_SCALE_INITIAL               0x018
> +#define DSC_SCALE_DEC_INTERVAL          0x01C
> +#define DSC_SCALE_INC_INTERVAL          0x020
> +#define DSC_FIRST_LINE_BPG_OFFSET       0x024
> +#define DSC_BPG_OFFSET                  0x028
> +#define DSC_DSC_OFFSET                  0x02C
> +#define DSC_FLATNESS                    0x030
> +#define DSC_RC_MODEL_SIZE               0x034
> +#define DSC_RC                          0x038
> +#define DSC_RC_BUF_THRESH               0x03C
> +#define DSC_RANGE_MIN_QP                0x074
> +#define DSC_RANGE_MAX_QP                0x0B0
> +#define DSC_RANGE_BPG_OFFSET            0x0EC
> +
> +static void dpu_hw_dsc_disable(struct dpu_hw_dsc *dsc)
> +{
> +	struct dpu_hw_blk_reg_map *c = &dsc->hw;
> +
> +	DPU_REG_WRITE(c, DSC_COMMON_MODE, 0);
> +}
> +
> +static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
> +			      struct msm_display_dsc_config *dsc,
> +			      u32 mode, bool ich_reset_override)
> +{
> +	struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
> +	u32 data;
> +	u32 initial_lines = dsc->initial_lines;
> +	bool is_cmd_mode = !(mode & BIT(2));
> +
> +	DPU_REG_WRITE(c, DSC_COMMON_MODE, mode);
> +
> +	data = 0;
> +	if (ich_reset_override)
> +		data = 3 << 28;

Do we need this? It seems this is only necessary for the half panel 
partial updates, which is not enabled for now. Do you know if this is 
really handy at this point or if it's an odd case? We might drop the 
ich_reset logic alltogether and add it later if/when the need arises.

> +
> +	if (is_cmd_mode)
> +		initial_lines += 1;
> +
> +	data |= (initial_lines << 20);
> +	data |= ((dsc->slice_last_group_size) << 18);
> +	/* bpp is 6.4 format, 4 LSBs bits are for fractional part */
> +	data |= dsc->drm.bits_per_pixel << 12;
> +	data |= (dsc->drm.block_pred_enable << 7);
> +	data |= (dsc->drm.line_buf_depth << 3);
> +	data |= (dsc->drm.simple_422 << 2);
> +	data |= (dsc->drm.convert_rgb << 1);
> +	if (dsc->drm.bits_per_component  == 10)
> +		data |= BIT(0);
> +
> +	DPU_REG_WRITE(c, DSC_ENC, data);
> +
> +	data = dsc->drm.pic_width << 16;
> +	data |= dsc->drm.pic_height;
> +	DPU_REG_WRITE(c, DSC_PICTURE, data);
> +
> +	data = dsc->drm.slice_width << 16;
> +	data |= dsc->drm.slice_height;
> +	DPU_REG_WRITE(c, DSC_SLICE, data);
> +
> +	data = DIV_ROUND_UP(dsc->drm.slice_width * dsc->drm.bits_per_pixel, 8) << 16;
> +
> +	DPU_REG_WRITE(c, DSC_CHUNK_SIZE, data);
> +
> +	data = dsc->drm.initial_dec_delay << 16;
> +	data |= dsc->drm.initial_xmit_delay;
> +	DPU_REG_WRITE(c, DSC_DELAY, data);
> +
> +	data = dsc->drm.initial_scale_value;
> +	DPU_REG_WRITE(c, DSC_SCALE_INITIAL, data);
> +
> +	data = dsc->drm.scale_decrement_interval;
> +	DPU_REG_WRITE(c, DSC_SCALE_DEC_INTERVAL, data);
> +
> +	data = 0x00000184; /* only this value works */
> +	DPU_REG_WRITE(c, DSC_SCALE_INC_INTERVAL, data);
> +
> +	data = dsc->drm.first_line_bpg_offset;
> +	DPU_REG_WRITE(c, DSC_FIRST_LINE_BPG_OFFSET, data);
> +
> +	data = dsc->drm.nfl_bpg_offset << 16;
> +	data |= dsc->drm.slice_bpg_offset;
> +	DPU_REG_WRITE(c, DSC_BPG_OFFSET, data);
> +
> +	data = dsc->drm.initial_offset << 16;
> +	data |= dsc->drm.final_offset;
> +	DPU_REG_WRITE(c, DSC_DSC_OFFSET, data);
> +
> +	data = dsc->det_thresh_flatness << 10;
> +	data |= dsc->drm.flatness_max_qp << 5;
> +	data |= dsc->drm.flatness_min_qp;
> +	DPU_REG_WRITE(c, DSC_FLATNESS, data);
> +
> +	data = dsc->drm.rc_model_size;
> +	DPU_REG_WRITE(c, DSC_RC_MODEL_SIZE, data);
> +
> +	data = dsc->drm.rc_tgt_offset_low << 18;
> +	data |= dsc->drm.rc_tgt_offset_high << 14;
> +	data |= dsc->drm.rc_quant_incr_limit1 << 9;
> +	data |= dsc->drm.rc_quant_incr_limit0 << 4;
> +	data |= dsc->drm.rc_edge_factor;
> +	DPU_REG_WRITE(c, DSC_RC, data);
> +}
> +
> +static void dpu_hw_dsc_config_thresh(struct dpu_hw_dsc *hw_dsc,
> +				     struct msm_display_dsc_config *dsc)
> +{
> +	struct drm_dsc_rc_range_parameters *rc = dsc->drm.rc_range_params;
> +	struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
> +	u32 off = 0x0;
> +	u16 *lp;
> +	int i;
> +
> +	lp = dsc->drm.rc_buf_thresh;
> +	off = DSC_RC_BUF_THRESH;
> +	for (i = 0; i < DSC_NUM_BUF_RANGES - 1 ; i++) {
> +		DPU_REG_WRITE(c, off, *lp++);

Nit: no need for lp here. Use array access like you do below.

> +		off += 4;
> +	}
> +
> +	off = DSC_RANGE_MIN_QP;
> +	for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
> +		DPU_REG_WRITE(c, off, rc[i].range_min_qp);
> +		off += 4;
> +	}
> +
> +	off = DSC_RANGE_MAX_QP;
> +	for (i = 0; i < 15; i++) {
> +		DPU_REG_WRITE(c, off, rc[i].range_max_qp);
> +		off += 4;
> +	}
> +
> +	off = DSC_RANGE_BPG_OFFSET;
> +	for (i = 0; i < 15; i++) {
> +		DPU_REG_WRITE(c, off, rc[i].range_bpg_offset);
> +		off += 4;
> +	}



> +}
> +
> +static struct dpu_dsc_cfg *_dsc_offset(enum dpu_dsc dsc,
> +				       struct dpu_mdss_cfg *m,
> +				       void __iomem *addr,
> +				       struct dpu_hw_blk_reg_map *b)
> +{
> +	int i;
> +
> +	for (i = 0; i < m->dsc_count; i++) {
> +		if (dsc == m->dsc[i].id) {
> +			b->base_off = addr;
> +			b->blk_off = m->dsc[i].base;
> +			b->length = m->dsc[i].len;
> +			b->hwversion = m->hwversion;
> +			b->log_mask = DPU_DBG_MASK_DSC;
> +			return &m->dsc[i];
> +		}
> +	}
> +
> +	return NULL;
> +}
> +
> +static void _setup_dsc_ops(struct dpu_hw_dsc_ops *ops,
> +			   unsigned long cap)
> +{
> +	ops->dsc_disable = dpu_hw_dsc_disable;
> +	ops->dsc_config = dpu_hw_dsc_config;
> +	ops->dsc_config_thresh = dpu_hw_dsc_config_thresh;
> +};
> +
> +static struct dpu_hw_blk_ops dpu_hw_ops = {
> +	.start = NULL,
> +	.stop = NULL,
> +};
> +
> +struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr,
> +				   struct dpu_mdss_cfg *m)
> +{
> +	struct dpu_hw_dsc *c;
> +	struct dpu_dsc_cfg *cfg;
> +
> +	c = kzalloc(sizeof(*c), GFP_KERNEL);
> +	if (!c)
> +		return ERR_PTR(-ENOMEM);
> +
> +	cfg = _dsc_offset(idx, m, addr, &c->hw);
> +	if (IS_ERR_OR_NULL(cfg)) {
> +		kfree(c);
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	c->idx = idx;
> +	c->caps = cfg;
> +	_setup_dsc_ops(&c->ops, c->caps->features);
> +
> +	dpu_hw_blk_init(&c->base, DPU_HW_BLK_DSC, idx, &dpu_hw_ops);
> +
> +	return c;
> +}
> +
> +void dpu_hw_dsc_destroy(struct dpu_hw_dsc *dsc)
> +{
> +	if (dsc)
> +		dpu_hw_blk_destroy(&dsc->base);
> +	kfree(dsc);
> +}
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
> new file mode 100644
> index 000000000000..c680fd948865
> --- /dev/null
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h
> @@ -0,0 +1,79 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/* Copyright (c) 2020, Linaro Limited */
> +
> +#ifndef _DPU_HW_DSC_H
> +#define _DPU_HW_DSC_H
> +
> +#include <drm/drm_dsc.h>
> +
> +#define DSC_MODE_SPLIT_PANEL            BIT(0)
> +#define DSC_MODE_MULTIPLEX              BIT(1)
> +#define DSC_MODE_VIDEO                  BIT(2)
> +
> +struct dpu_hw_dsc;
> +
> +/**
> + * struct dpu_hw_dsc_ops - interface to the dsc hardware driver functions
> + * Assumption is these functions will be called after clocks are enabled
> + */
> +struct dpu_hw_dsc_ops {
> +	/**
> +	 * dsc_disable - disable dsc
> +	 * @hw_dsc: Pointer to dsc context
> +	 */
> +	void (*dsc_disable)(struct dpu_hw_dsc *hw_dsc);
> +
> +	/**
> +	 * dsc_config - configures dsc encoder
> +	 * @hw_dsc: Pointer to dsc context
> +	 * @dsc: panel dsc parameters
> +	 * @mode: dsc topology mode to be set
> +	 * @ich_reset_override: option to reset ich
> +	 */
> +	void (*dsc_config)(struct dpu_hw_dsc *hw_dsc,
> +			   struct msm_display_dsc_config *dsc,
> +			   u32 mode, bool ich_reset_override);
> +
> +	/**
> +	 * dsc_config_thresh - programs panel thresholds
> +	 * @hw_dsc: Pointer to dsc context
> +	 * @dsc: panel dsc parameters
> +	 */
> +	void (*dsc_config_thresh)(struct dpu_hw_dsc *hw_dsc,
> +				  struct msm_display_dsc_config *dsc);
> +};
> +
> +struct dpu_hw_dsc {
> +	struct dpu_hw_blk base;
> +	struct dpu_hw_blk_reg_map hw;
> +
> +	/* dsc */
> +	enum dpu_dsc idx;
> +	const struct dpu_dsc_cfg *caps;
> +
> +	/* ops */
> +	struct dpu_hw_dsc_ops ops;
> +};
> +
> +/**
> + * dpu_hw_dsc_init - initializes the dsc block for the passed dsc idx.
> + * @idx:  DSC index for which driver object is required
> + * @addr: Mapped register io address of MDP
> + * @m:    Pointer to mdss catalog data
> + * Returns: Error code or allocated dpu_hw_dsc context
> + */
> +struct dpu_hw_dsc *dpu_hw_dsc_init(enum dpu_dsc idx, void __iomem *addr,
> +				   struct dpu_mdss_cfg *m);
> +
> +/**
> + * dpu_hw_dsc_destroy - destroys dsc driver context
> + * @dsc:   Pointer to dsc driver context returned by dpu_hw_dsc_init
> + */
> +void dpu_hw_dsc_destroy(struct dpu_hw_dsc *dsc);
> +
> +static inline struct dpu_hw_dsc *to_dpu_hw_dsc(struct dpu_hw_blk *hw)
> +{
> +	return container_of(hw, struct dpu_hw_dsc, base);
> +}
> +
> +#endif /* _DPU_HW_DSC_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 09a3fb3e89f5..1b72c11090ee 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> @@ -97,6 +97,7 @@ enum dpu_hw_blk_type {
>   	DPU_HW_BLK_WB,
>   	DPU_HW_BLK_DSPP,
>   	DPU_HW_BLK_MERGE_3D,
> +	DPU_HW_BLK_DSC,
>   	DPU_HW_BLK_MAX,
>   };
>   
> @@ -176,6 +177,17 @@ enum dpu_ctl {
>   	CTL_MAX
>   };
>   
> +enum dpu_dsc {
> +	DSC_NONE = 0,
> +	DSC_0,
> +	DSC_1,
> +	DSC_2,
> +	DSC_3,
> +	DSC_4,
> +	DSC_5,
> +	DSC_MAX
> +};
> +
>   enum dpu_pingpong {
>   	PINGPONG_0 = 1,
>   	PINGPONG_1,
> @@ -437,5 +449,6 @@ struct dpu_mdss_color {
>   #define DPU_DBG_MASK_VBIF     (1 << 8)
>   #define DPU_DBG_MASK_ROT      (1 << 9)
>   #define DPU_DBG_MASK_DSPP     (1 << 10)
> +#define DPU_DBG_MASK_DSC      (1 << 11)
>   
>   #endif  /* _DPU_HW_MDSS_H */
> 


-- 
With best wishes
Dmitry

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

* Re: [RFC PATCH 06/13] drm/msm/disp/dpu1: Add DSC support in RM
  2021-05-21 12:49   ` Vinod Koul
@ 2021-05-28 10:33     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 91+ messages in thread
From: Dmitry Baryshkov @ 2021-05-28 10:33 UTC (permalink / raw)
  To: Vinod Koul, Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, David Airlie, Daniel Vetter,
	Jonathan Marek, Abhinav Kumar, linux-kernel, dri-devel,
	freedreno

On 21/05/2021 15:49, Vinod Koul wrote:
> This add the bits in RM to enable the DSC blocks
> 
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |  1 +
>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c  | 32 +++++++++++++++++++++++++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h  |  1 +
>   3 files changed, 34 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> index d6717d6672f7..d56c05146dfe 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> @@ -165,6 +165,7 @@ struct dpu_global_state {
>   	uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
>   	uint32_t intf_to_enc_id[INTF_MAX - INTF_0];
>   	uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
> +	uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
>   };
>   
>   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 fd2d104f0a91..4da6d72b7996 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> @@ -11,6 +11,7 @@
>   #include "dpu_hw_intf.h"
>   #include "dpu_hw_dspp.h"
>   #include "dpu_hw_merge3d.h"
> +#include "dpu_hw_dsc.h"
>   #include "dpu_encoder.h"
>   #include "dpu_trace.h"
>   
> @@ -75,6 +76,14 @@ int dpu_rm_destroy(struct dpu_rm *rm)
>   			dpu_hw_intf_destroy(hw);
>   		}
>   	}
> +	for (i = 0; i < ARRAY_SIZE(rm->dsc_blks); i++) {
> +		struct dpu_hw_dsc *hw;
> +
> +		if (rm->intf_blks[i]) {
> +			hw = to_dpu_hw_dsc(rm->dsc_blks[i]);
> +			dpu_hw_dsc_destroy(hw);
> +		}
> +	}
>   
>   	return 0;
>   }
> @@ -221,6 +230,19 @@ int dpu_rm_init(struct dpu_rm *rm,
>   		rm->dspp_blks[dspp->id - DSPP_0] = &hw->base;
>   	}
>   
> +	for (i = 0; i < cat->dsc_count; i++) {
> +		struct dpu_hw_dsc *hw;
> +		const struct dpu_dsc_cfg *dsc = &cat->dsc[i];
> +
> +		hw = dpu_hw_dsc_init(dsc->id, mmio, cat);
> +		if (IS_ERR_OR_NULL(hw)) {
> +			rc = PTR_ERR(hw);
> +			DPU_ERROR("failed dsc object creation: err %d\n", rc);
> +			goto fail;
> +		}
> +		rm->dsc_blks[dsc->id - DSC_0] = &hw->base;
> +	}
> +
>   	return 0;
>   
>   fail:
> @@ -476,6 +498,9 @@ static int _dpu_rm_reserve_intf(
>   	}
>   
>   	global_state->intf_to_enc_id[idx] = enc_id;
> +
> +	global_state->dsc_to_enc_id[0] = enc_id;
> +	global_state->dsc_to_enc_id[1] = enc_id;

This should bear at least the FIXME.

>   	return 0;
>   }
>   
> @@ -567,6 +592,8 @@ void dpu_rm_release(struct dpu_global_state *global_state,
>   		ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);
>   	_dpu_rm_clear_mapping(global_state->intf_to_enc_id,
>   		ARRAY_SIZE(global_state->intf_to_enc_id), enc->base.id);
> +	_dpu_rm_clear_mapping(global_state->dsc_to_enc_id,
> +		ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
>   }
>   
>   int dpu_rm_reserve(
> @@ -640,6 +667,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>   		hw_to_enc_id = global_state->dspp_to_enc_id;
>   		max_blks = ARRAY_SIZE(rm->dspp_blks);
>   		break;
> +	case DPU_HW_BLK_DSC:
> +		hw_blks = rm->dsc_blks;
> +		hw_to_enc_id = global_state->dsc_to_enc_id;
> +		max_blks = ARRAY_SIZE(rm->dsc_blks);
> +		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 1f12c8d5b8aa..278d2a510b80 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> @@ -30,6 +30,7 @@ struct dpu_rm {
>   	struct dpu_hw_blk *intf_blks[INTF_MAX - INTF_0];
>   	struct dpu_hw_blk *dspp_blks[DSPP_MAX - DSPP_0];
>   	struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0];
> +	struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0];
>   
>   	uint32_t lm_max_width;
>   };
> 


-- 
With best wishes
Dmitry

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

* Re: [RFC PATCH 06/13] drm/msm/disp/dpu1: Add DSC support in RM
@ 2021-05-28 10:33     ` Dmitry Baryshkov
  0 siblings, 0 replies; 91+ messages in thread
From: Dmitry Baryshkov @ 2021-05-28 10:33 UTC (permalink / raw)
  To: Vinod Koul, Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, dri-devel, freedreno

On 21/05/2021 15:49, Vinod Koul wrote:
> This add the bits in RM to enable the DSC blocks
> 
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |  1 +
>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c  | 32 +++++++++++++++++++++++++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h  |  1 +
>   3 files changed, 34 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> index d6717d6672f7..d56c05146dfe 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> @@ -165,6 +165,7 @@ struct dpu_global_state {
>   	uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
>   	uint32_t intf_to_enc_id[INTF_MAX - INTF_0];
>   	uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
> +	uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
>   };
>   
>   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 fd2d104f0a91..4da6d72b7996 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> @@ -11,6 +11,7 @@
>   #include "dpu_hw_intf.h"
>   #include "dpu_hw_dspp.h"
>   #include "dpu_hw_merge3d.h"
> +#include "dpu_hw_dsc.h"
>   #include "dpu_encoder.h"
>   #include "dpu_trace.h"
>   
> @@ -75,6 +76,14 @@ int dpu_rm_destroy(struct dpu_rm *rm)
>   			dpu_hw_intf_destroy(hw);
>   		}
>   	}
> +	for (i = 0; i < ARRAY_SIZE(rm->dsc_blks); i++) {
> +		struct dpu_hw_dsc *hw;
> +
> +		if (rm->intf_blks[i]) {
> +			hw = to_dpu_hw_dsc(rm->dsc_blks[i]);
> +			dpu_hw_dsc_destroy(hw);
> +		}
> +	}
>   
>   	return 0;
>   }
> @@ -221,6 +230,19 @@ int dpu_rm_init(struct dpu_rm *rm,
>   		rm->dspp_blks[dspp->id - DSPP_0] = &hw->base;
>   	}
>   
> +	for (i = 0; i < cat->dsc_count; i++) {
> +		struct dpu_hw_dsc *hw;
> +		const struct dpu_dsc_cfg *dsc = &cat->dsc[i];
> +
> +		hw = dpu_hw_dsc_init(dsc->id, mmio, cat);
> +		if (IS_ERR_OR_NULL(hw)) {
> +			rc = PTR_ERR(hw);
> +			DPU_ERROR("failed dsc object creation: err %d\n", rc);
> +			goto fail;
> +		}
> +		rm->dsc_blks[dsc->id - DSC_0] = &hw->base;
> +	}
> +
>   	return 0;
>   
>   fail:
> @@ -476,6 +498,9 @@ static int _dpu_rm_reserve_intf(
>   	}
>   
>   	global_state->intf_to_enc_id[idx] = enc_id;
> +
> +	global_state->dsc_to_enc_id[0] = enc_id;
> +	global_state->dsc_to_enc_id[1] = enc_id;

This should bear at least the FIXME.

>   	return 0;
>   }
>   
> @@ -567,6 +592,8 @@ void dpu_rm_release(struct dpu_global_state *global_state,
>   		ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);
>   	_dpu_rm_clear_mapping(global_state->intf_to_enc_id,
>   		ARRAY_SIZE(global_state->intf_to_enc_id), enc->base.id);
> +	_dpu_rm_clear_mapping(global_state->dsc_to_enc_id,
> +		ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
>   }
>   
>   int dpu_rm_reserve(
> @@ -640,6 +667,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>   		hw_to_enc_id = global_state->dspp_to_enc_id;
>   		max_blks = ARRAY_SIZE(rm->dspp_blks);
>   		break;
> +	case DPU_HW_BLK_DSC:
> +		hw_blks = rm->dsc_blks;
> +		hw_to_enc_id = global_state->dsc_to_enc_id;
> +		max_blks = ARRAY_SIZE(rm->dsc_blks);
> +		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 1f12c8d5b8aa..278d2a510b80 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> @@ -30,6 +30,7 @@ struct dpu_rm {
>   	struct dpu_hw_blk *intf_blks[INTF_MAX - INTF_0];
>   	struct dpu_hw_blk *dspp_blks[DSPP_MAX - DSPP_0];
>   	struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0];
> +	struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0];
>   
>   	uint32_t lm_max_width;
>   };
> 


-- 
With best wishes
Dmitry

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

* Re: [RFC PATCH 09/13] drm/msm/disp/dpu1: Don't use DSC with mode_3d
  2021-05-21 12:49   ` Vinod Koul
@ 2021-05-28 10:36     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 91+ messages in thread
From: Dmitry Baryshkov @ 2021-05-28 10:36 UTC (permalink / raw)
  To: Vinod Koul, Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, David Airlie, Daniel Vetter,
	Jonathan Marek, Abhinav Kumar, linux-kernel, dri-devel,
	freedreno

On 21/05/2021 15:49, Vinod Koul wrote:
> We cannot enable mode_3d when we are using the DSC. So pass
> configuration to detect DSC is enabled and not enable mode_3d
> when we are using DSC
> 
> We add a helper dpu_encoder_helper_get_dsc_mode() to detect dsc
> enabled and pass this to .setup_intf_cfg()
> 
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h     | 11 +++++++++++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c |  2 ++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c           |  5 +++--
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h           |  2 ++
>   4 files changed, 18 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> index ecbc4be98980..d43b804528eb 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> @@ -336,6 +336,17 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
>   	return BLEND_3D_NONE;
>   }
>   
> +static inline bool dpu_encoder_helper_get_dsc_mode(struct dpu_encoder_phys *phys_enc)
> +{
> +	struct drm_encoder *drm_enc = phys_enc->parent;
> +	struct msm_drm_private *priv = drm_enc->dev->dev_private;
> +
> +	if (priv->dsc)
> +		return true;
> +
> +	return false;
> +}
> +
>   /**
>    * dpu_encoder_helper_split_config - split display configuration helper function
>    *	This helper function may be used by physical encoders to configure
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
> index b2be39b9144e..5fe87881c30c 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
> @@ -69,6 +69,8 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg(
>   	intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD;
>   	intf_cfg.stream_sel = cmd_enc->stream_sel;
>   	intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc);
> +	intf_cfg.dsc = dpu_encoder_helper_get_dsc_mode(phys_enc);
> +
>   	ctl->ops.setup_intf_cfg(ctl, &intf_cfg);
>   }
>   
> 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 aeea6add61ee..f059416311ee 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> @@ -121,7 +121,7 @@ static u32 dpu_hw_ctl_get_pending_flush(struct dpu_hw_ctl *ctx)
>   	return ctx->pending_flush_mask;
>   }
>   
> -static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
> +static void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
>   {
>   	DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH, BIT(0) | BIT(1) | BIT(2) | BIT(3));
>   
> @@ -522,7 +522,8 @@ static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
>   
>   	intf_cfg |= (cfg->intf & 0xF) << 4;
>   
> -	if (cfg->mode_3d) {
> +	/* In DSC we can't set merge, so check for dsc too */
> +	if (cfg->mode_3d && !cfg->dsc) {

I think we should catch this earlier (in atomic_check?), so that we 
won't enable modes that would require merge_3d with DSC enabled (until 
we support DSC merge?)

>   		intf_cfg |= BIT(19);
>   		intf_cfg |= (cfg->mode_3d - 0x1) << 20;
>   	}
> 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 806c171e5df2..347a653c1e01 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
> + * @dsc:                   DSC is enabled
>    * @stream_sel:            Stream selection for multi-stream interfaces
>    */
>   struct dpu_hw_intf_cfg {
> @@ -46,6 +47,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;
> +	bool dsc;
>   	int stream_sel;
>   };
>   
> 


-- 
With best wishes
Dmitry

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

* Re: [RFC PATCH 09/13] drm/msm/disp/dpu1: Don't use DSC with mode_3d
@ 2021-05-28 10:36     ` Dmitry Baryshkov
  0 siblings, 0 replies; 91+ messages in thread
From: Dmitry Baryshkov @ 2021-05-28 10:36 UTC (permalink / raw)
  To: Vinod Koul, Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, dri-devel, freedreno

On 21/05/2021 15:49, Vinod Koul wrote:
> We cannot enable mode_3d when we are using the DSC. So pass
> configuration to detect DSC is enabled and not enable mode_3d
> when we are using DSC
> 
> We add a helper dpu_encoder_helper_get_dsc_mode() to detect dsc
> enabled and pass this to .setup_intf_cfg()
> 
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h     | 11 +++++++++++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c |  2 ++
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c           |  5 +++--
>   drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h           |  2 ++
>   4 files changed, 18 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> index ecbc4be98980..d43b804528eb 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
> @@ -336,6 +336,17 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
>   	return BLEND_3D_NONE;
>   }
>   
> +static inline bool dpu_encoder_helper_get_dsc_mode(struct dpu_encoder_phys *phys_enc)
> +{
> +	struct drm_encoder *drm_enc = phys_enc->parent;
> +	struct msm_drm_private *priv = drm_enc->dev->dev_private;
> +
> +	if (priv->dsc)
> +		return true;
> +
> +	return false;
> +}
> +
>   /**
>    * dpu_encoder_helper_split_config - split display configuration helper function
>    *	This helper function may be used by physical encoders to configure
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
> index b2be39b9144e..5fe87881c30c 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
> @@ -69,6 +69,8 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg(
>   	intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD;
>   	intf_cfg.stream_sel = cmd_enc->stream_sel;
>   	intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc);
> +	intf_cfg.dsc = dpu_encoder_helper_get_dsc_mode(phys_enc);
> +
>   	ctl->ops.setup_intf_cfg(ctl, &intf_cfg);
>   }
>   
> 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 aeea6add61ee..f059416311ee 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
> @@ -121,7 +121,7 @@ static u32 dpu_hw_ctl_get_pending_flush(struct dpu_hw_ctl *ctx)
>   	return ctx->pending_flush_mask;
>   }
>   
> -static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
> +static void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
>   {
>   	DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH, BIT(0) | BIT(1) | BIT(2) | BIT(3));
>   
> @@ -522,7 +522,8 @@ static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
>   
>   	intf_cfg |= (cfg->intf & 0xF) << 4;
>   
> -	if (cfg->mode_3d) {
> +	/* In DSC we can't set merge, so check for dsc too */
> +	if (cfg->mode_3d && !cfg->dsc) {

I think we should catch this earlier (in atomic_check?), so that we 
won't enable modes that would require merge_3d with DSC enabled (until 
we support DSC merge?)

>   		intf_cfg |= BIT(19);
>   		intf_cfg |= (cfg->mode_3d - 0x1) << 20;
>   	}
> 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 806c171e5df2..347a653c1e01 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
> + * @dsc:                   DSC is enabled
>    * @stream_sel:            Stream selection for multi-stream interfaces
>    */
>   struct dpu_hw_intf_cfg {
> @@ -46,6 +47,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;
> +	bool dsc;
>   	int stream_sel;
>   };
>   
> 


-- 
With best wishes
Dmitry

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

* Re: [RFC PATCH 11/13] drm/msm/disp/dpu1: Add support for DSC in topology
  2021-05-21 12:49   ` Vinod Koul
@ 2021-05-28 10:39     ` Dmitry Baryshkov
  -1 siblings, 0 replies; 91+ messages in thread
From: Dmitry Baryshkov @ 2021-05-28 10:39 UTC (permalink / raw)
  To: Vinod Koul, Rob Clark
  Cc: linux-arm-msm, Bjorn Andersson, David Airlie, Daniel Vetter,
	Jonathan Marek, Abhinav Kumar, linux-kernel, dri-devel,
	freedreno

On 21/05/2021 15:49, Vinod Koul wrote:
> For DSC to work we typically need a 2,2,1 configuration. This should
> suffice for resolutions upto 4k. For more resolutions like 8k this won't
> work.
> 
> Furthermore, we can use 1 DSC encoder in lesser resulutions, but that is
> not power efficient according to Abhinav, so it is recommended to always
> use 2 encoders.

Not power efficient because the second DSC would also be powered on or 
because single DSC enc would consume more power than two DSCs?

> 
> So for now we blindly create 2,2,1 topology when DSC is enabled
> 
> Co-developed-by: Abhinav Kumar <abhinavk@codeaurora.org>
> Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org>
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 14 ++++++++++++++
>   1 file changed, 14 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 18cb1274a8bb..bffb40085c67 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -609,8 +609,22 @@ static struct msm_display_topology dpu_encoder_get_topology(
>   	topology.num_enc = 0;
>   	topology.num_intf = intf_count;
>   
> +	drm_enc = &dpu_enc->base;
> +	priv = drm_enc->dev->dev_private;
> +	if (priv && priv->dsc) {
> +		/* In case of Display Stream Compression DSC, we would use
> +		 * 2 encoders, 2 line mixers and 1 interface
> +		 * this is power optimal and can drive upto (including) 4k
> +		 * screens
> +		 */
> +		topology.num_enc = 2;
> +		topology.num_intf = 1;
> +		topology.num_lm = 2;
> +	}
> +
>   	return topology;
>   }
> +
>   static int dpu_encoder_virt_atomic_check(
>   		struct drm_encoder *drm_enc,
>   		struct drm_crtc_state *crtc_state,
> 


-- 
With best wishes
Dmitry

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

* Re: [RFC PATCH 11/13] drm/msm/disp/dpu1: Add support for DSC in topology
@ 2021-05-28 10:39     ` Dmitry Baryshkov
  0 siblings, 0 replies; 91+ messages in thread
From: Dmitry Baryshkov @ 2021-05-28 10:39 UTC (permalink / raw)
  To: Vinod Koul, Rob Clark
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, dri-devel, freedreno

On 21/05/2021 15:49, Vinod Koul wrote:
> For DSC to work we typically need a 2,2,1 configuration. This should
> suffice for resolutions upto 4k. For more resolutions like 8k this won't
> work.
> 
> Furthermore, we can use 1 DSC encoder in lesser resulutions, but that is
> not power efficient according to Abhinav, so it is recommended to always
> use 2 encoders.

Not power efficient because the second DSC would also be powered on or 
because single DSC enc would consume more power than two DSCs?

> 
> So for now we blindly create 2,2,1 topology when DSC is enabled
> 
> Co-developed-by: Abhinav Kumar <abhinavk@codeaurora.org>
> Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org>
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> ---
>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 14 ++++++++++++++
>   1 file changed, 14 insertions(+)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 18cb1274a8bb..bffb40085c67 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -609,8 +609,22 @@ static struct msm_display_topology dpu_encoder_get_topology(
>   	topology.num_enc = 0;
>   	topology.num_intf = intf_count;
>   
> +	drm_enc = &dpu_enc->base;
> +	priv = drm_enc->dev->dev_private;
> +	if (priv && priv->dsc) {
> +		/* In case of Display Stream Compression DSC, we would use
> +		 * 2 encoders, 2 line mixers and 1 interface
> +		 * this is power optimal and can drive upto (including) 4k
> +		 * screens
> +		 */
> +		topology.num_enc = 2;
> +		topology.num_intf = 1;
> +		topology.num_lm = 2;
> +	}
> +
>   	return topology;
>   }
> +
>   static int dpu_encoder_virt_atomic_check(
>   		struct drm_encoder *drm_enc,
>   		struct drm_crtc_state *crtc_state,
> 


-- 
With best wishes
Dmitry

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

* Re: [RFC PATCH 11/13] drm/msm/disp/dpu1: Add support for DSC in topology
  2021-05-28 10:39     ` Dmitry Baryshkov
@ 2021-05-28 22:23       ` abhinavk
  -1 siblings, 0 replies; 91+ messages in thread
From: abhinavk @ 2021-05-28 22:23 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Vinod Koul, Rob Clark, linux-arm-msm, Bjorn Andersson,
	David Airlie, Daniel Vetter, Jonathan Marek, linux-kernel,
	dri-devel, freedreno

On 2021-05-28 03:39, Dmitry Baryshkov wrote:
> On 21/05/2021 15:49, Vinod Koul wrote:
>> For DSC to work we typically need a 2,2,1 configuration. This should
>> suffice for resolutions upto 4k. For more resolutions like 8k this 
>> won't
>> work.
>> 
>> Furthermore, we can use 1 DSC encoder in lesser resulutions, but that 
>> is
>> not power efficient according to Abhinav, so it is recommended to 
>> always
>> use 2 encoders.
> 
> Not power efficient because the second DSC would also be powered on or
> because single DSC enc would consume more power than two DSCs?

I havent got through the series yet but just thought of answering this,

So before coming to the power aspects of this, hard-coding was done for 
the foll reasons:

-> We do not have a topology DTSI property in upstream and will probably 
not have as well till
other features are added which support all the topologies
-> The DSC panel which is being upstreamed as part of this series is 
working with this 2,2,1 topology
downstream ( dual lm, dual DSC encoders, single DSI ). Other topologies 
have not been tried on it yet
-> There needs to be a better approach to handle all topologies once we 
have added support for them.
It can be either a DTSI property if others agree OR some helper API 
which will determine the best topology
based on various factors. Till then, since this will be the only DSC 
panel we are adding support for
I thought we can start with a fixed topology for now.

Coming to the power aspect, I only recommended 2-2-1 here because using 
two mixers is better power wise
as it will split the width/2. We can also do 2-1-1 by enabling 3D mux 
but this panel has not been validated
with a single DSC. So to keep things simple with what has been 
validated, I thought we can go ahead with
2-2-1 for now.

So rather than giving too much importance to the power aspect of it, the 
other reasons should also
be highlighted here as the main reason and the commit text should give 
these details as well.

>> 
>> So for now we blindly create 2,2,1 topology when DSC is enabled
>> 
>> Co-developed-by: Abhinav Kumar <abhinavk@codeaurora.org>
>> Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org>
>> Signed-off-by: Vinod Koul <vkoul@kernel.org>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 14 ++++++++++++++
>>   1 file changed, 14 insertions(+)
>> 
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> index 18cb1274a8bb..bffb40085c67 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> @@ -609,8 +609,22 @@ static struct msm_display_topology 
>> dpu_encoder_get_topology(
>>   	topology.num_enc = 0;
>>   	topology.num_intf = intf_count;
>>   +	drm_enc = &dpu_enc->base;
>> +	priv = drm_enc->dev->dev_private;
>> +	if (priv && priv->dsc) {
>> +		/* In case of Display Stream Compression DSC, we would use
>> +		 * 2 encoders, 2 line mixers and 1 interface
>> +		 * this is power optimal and can drive upto (including) 4k
>> +		 * screens
>> +		 */
>> +		topology.num_enc = 2;
>> +		topology.num_intf = 1;
>> +		topology.num_lm = 2;
>> +	}
>> +
>>   	return topology;
>>   }
>> +
>>   static int dpu_encoder_virt_atomic_check(
>>   		struct drm_encoder *drm_enc,
>>   		struct drm_crtc_state *crtc_state,
>> 

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

* Re: [RFC PATCH 11/13] drm/msm/disp/dpu1: Add support for DSC in topology
@ 2021-05-28 22:23       ` abhinavk
  0 siblings, 0 replies; 91+ messages in thread
From: abhinavk @ 2021-05-28 22:23 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, dri-devel,
	Bjorn Andersson, Vinod Koul, freedreno, linux-kernel

On 2021-05-28 03:39, Dmitry Baryshkov wrote:
> On 21/05/2021 15:49, Vinod Koul wrote:
>> For DSC to work we typically need a 2,2,1 configuration. This should
>> suffice for resolutions upto 4k. For more resolutions like 8k this 
>> won't
>> work.
>> 
>> Furthermore, we can use 1 DSC encoder in lesser resulutions, but that 
>> is
>> not power efficient according to Abhinav, so it is recommended to 
>> always
>> use 2 encoders.
> 
> Not power efficient because the second DSC would also be powered on or
> because single DSC enc would consume more power than two DSCs?

I havent got through the series yet but just thought of answering this,

So before coming to the power aspects of this, hard-coding was done for 
the foll reasons:

-> We do not have a topology DTSI property in upstream and will probably 
not have as well till
other features are added which support all the topologies
-> The DSC panel which is being upstreamed as part of this series is 
working with this 2,2,1 topology
downstream ( dual lm, dual DSC encoders, single DSI ). Other topologies 
have not been tried on it yet
-> There needs to be a better approach to handle all topologies once we 
have added support for them.
It can be either a DTSI property if others agree OR some helper API 
which will determine the best topology
based on various factors. Till then, since this will be the only DSC 
panel we are adding support for
I thought we can start with a fixed topology for now.

Coming to the power aspect, I only recommended 2-2-1 here because using 
two mixers is better power wise
as it will split the width/2. We can also do 2-1-1 by enabling 3D mux 
but this panel has not been validated
with a single DSC. So to keep things simple with what has been 
validated, I thought we can go ahead with
2-2-1 for now.

So rather than giving too much importance to the power aspect of it, the 
other reasons should also
be highlighted here as the main reason and the commit text should give 
these details as well.

>> 
>> So for now we blindly create 2,2,1 topology when DSC is enabled
>> 
>> Co-developed-by: Abhinav Kumar <abhinavk@codeaurora.org>
>> Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org>
>> Signed-off-by: Vinod Koul <vkoul@kernel.org>
>> ---
>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 14 ++++++++++++++
>>   1 file changed, 14 insertions(+)
>> 
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> index 18cb1274a8bb..bffb40085c67 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> @@ -609,8 +609,22 @@ static struct msm_display_topology 
>> dpu_encoder_get_topology(
>>   	topology.num_enc = 0;
>>   	topology.num_intf = intf_count;
>>   +	drm_enc = &dpu_enc->base;
>> +	priv = drm_enc->dev->dev_private;
>> +	if (priv && priv->dsc) {
>> +		/* In case of Display Stream Compression DSC, we would use
>> +		 * 2 encoders, 2 line mixers and 1 interface
>> +		 * this is power optimal and can drive upto (including) 4k
>> +		 * screens
>> +		 */
>> +		topology.num_enc = 2;
>> +		topology.num_intf = 1;
>> +		topology.num_lm = 2;
>> +	}
>> +
>>   	return topology;
>>   }
>> +
>>   static int dpu_encoder_virt_atomic_check(
>>   		struct drm_encoder *drm_enc,
>>   		struct drm_crtc_state *crtc_state,
>> 

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

* Re: [RFC PATCH 11/13] drm/msm/disp/dpu1: Add support for DSC in topology
  2021-05-28 22:23       ` abhinavk
@ 2021-05-28 22:29         ` Dmitry Baryshkov
  -1 siblings, 0 replies; 91+ messages in thread
From: Dmitry Baryshkov @ 2021-05-28 22:29 UTC (permalink / raw)
  To: abhinavk
  Cc: Vinod Koul, Rob Clark, linux-arm-msm, Bjorn Andersson,
	David Airlie, Daniel Vetter, Jonathan Marek, linux-kernel,
	dri-devel, freedreno

On 29/05/2021 01:23, abhinavk@codeaurora.org wrote:
> On 2021-05-28 03:39, Dmitry Baryshkov wrote:
>> On 21/05/2021 15:49, Vinod Koul wrote:
>>> For DSC to work we typically need a 2,2,1 configuration. This should
>>> suffice for resolutions upto 4k. For more resolutions like 8k this won't
>>> work.
>>>
>>> Furthermore, we can use 1 DSC encoder in lesser resulutions, but that is
>>> not power efficient according to Abhinav, so it is recommended to always
>>> use 2 encoders.
>>
>> Not power efficient because the second DSC would also be powered on or
>> because single DSC enc would consume more power than two DSCs?
> 
> I havent got through the series yet but just thought of answering this,
> 
> So before coming to the power aspects of this, hard-coding was done for 
> the foll reasons:
> 
> -> We do not have a topology DTSI property in upstream and will probably 
> not have as well till
> other features are added which support all the topologies
> -> The DSC panel which is being upstreamed as part of this series is 
> working with this 2,2,1 topology
> downstream ( dual lm, dual DSC encoders, single DSI ). Other topologies 
> have not been tried on it yet
> -> There needs to be a better approach to handle all topologies once we 
> have added support for them.
> It can be either a DTSI property if others agree OR some helper API 
> which will determine the best topology
> based on various factors. Till then, since this will be the only DSC 
> panel we are adding support for
> I thought we can start with a fixed topology for now.
> 
> Coming to the power aspect, I only recommended 2-2-1 here because using 
> two mixers is better power wise
> as it will split the width/2. We can also do 2-1-1 by enabling 3D mux 
> but this panel has not been validated
> with a single DSC. So to keep things simple with what has been 
> validated, I thought we can go ahead with
> 2-2-1 for now.
> 
> So rather than giving too much importance to the power aspect of it, the 
> other reasons should also
> be highlighted here as the main reason and the commit text should give 
> these details as well.

Sounds reasonable now, thank you!


> 
>>>
>>> So for now we blindly create 2,2,1 topology when DSC is enabled
>>>
>>> Co-developed-by: Abhinav Kumar <abhinavk@codeaurora.org>
>>> Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org>
>>> Signed-off-by: Vinod Koul <vkoul@kernel.org>
>>> ---
>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 14 ++++++++++++++
>>>   1 file changed, 14 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>> index 18cb1274a8bb..bffb40085c67 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>> @@ -609,8 +609,22 @@ static struct msm_display_topology 
>>> dpu_encoder_get_topology(
>>>       topology.num_enc = 0;
>>>       topology.num_intf = intf_count;
>>>   +    drm_enc = &dpu_enc->base;
>>> +    priv = drm_enc->dev->dev_private;
>>> +    if (priv && priv->dsc) {
>>> +        /* In case of Display Stream Compression DSC, we would use
>>> +         * 2 encoders, 2 line mixers and 1 interface
>>> +         * this is power optimal and can drive upto (including) 4k
>>> +         * screens
>>> +         */
>>> +        topology.num_enc = 2;
>>> +        topology.num_intf = 1;
>>> +        topology.num_lm = 2;
>>> +    }
>>> +
>>>       return topology;
>>>   }
>>> +
>>>   static int dpu_encoder_virt_atomic_check(
>>>           struct drm_encoder *drm_enc,
>>>           struct drm_crtc_state *crtc_state,
>>>


-- 
With best wishes
Dmitry

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

* Re: [RFC PATCH 11/13] drm/msm/disp/dpu1: Add support for DSC in topology
@ 2021-05-28 22:29         ` Dmitry Baryshkov
  0 siblings, 0 replies; 91+ messages in thread
From: Dmitry Baryshkov @ 2021-05-28 22:29 UTC (permalink / raw)
  To: abhinavk
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, dri-devel,
	Bjorn Andersson, Vinod Koul, freedreno, linux-kernel

On 29/05/2021 01:23, abhinavk@codeaurora.org wrote:
> On 2021-05-28 03:39, Dmitry Baryshkov wrote:
>> On 21/05/2021 15:49, Vinod Koul wrote:
>>> For DSC to work we typically need a 2,2,1 configuration. This should
>>> suffice for resolutions upto 4k. For more resolutions like 8k this won't
>>> work.
>>>
>>> Furthermore, we can use 1 DSC encoder in lesser resulutions, but that is
>>> not power efficient according to Abhinav, so it is recommended to always
>>> use 2 encoders.
>>
>> Not power efficient because the second DSC would also be powered on or
>> because single DSC enc would consume more power than two DSCs?
> 
> I havent got through the series yet but just thought of answering this,
> 
> So before coming to the power aspects of this, hard-coding was done for 
> the foll reasons:
> 
> -> We do not have a topology DTSI property in upstream and will probably 
> not have as well till
> other features are added which support all the topologies
> -> The DSC panel which is being upstreamed as part of this series is 
> working with this 2,2,1 topology
> downstream ( dual lm, dual DSC encoders, single DSI ). Other topologies 
> have not been tried on it yet
> -> There needs to be a better approach to handle all topologies once we 
> have added support for them.
> It can be either a DTSI property if others agree OR some helper API 
> which will determine the best topology
> based on various factors. Till then, since this will be the only DSC 
> panel we are adding support for
> I thought we can start with a fixed topology for now.
> 
> Coming to the power aspect, I only recommended 2-2-1 here because using 
> two mixers is better power wise
> as it will split the width/2. We can also do 2-1-1 by enabling 3D mux 
> but this panel has not been validated
> with a single DSC. So to keep things simple with what has been 
> validated, I thought we can go ahead with
> 2-2-1 for now.
> 
> So rather than giving too much importance to the power aspect of it, the 
> other reasons should also
> be highlighted here as the main reason and the commit text should give 
> these details as well.

Sounds reasonable now, thank you!


> 
>>>
>>> So for now we blindly create 2,2,1 topology when DSC is enabled
>>>
>>> Co-developed-by: Abhinav Kumar <abhinavk@codeaurora.org>
>>> Signed-off-by: Abhinav Kumar <abhinavk@codeaurora.org>
>>> Signed-off-by: Vinod Koul <vkoul@kernel.org>
>>> ---
>>>   drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 14 ++++++++++++++
>>>   1 file changed, 14 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
>>> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>> index 18cb1274a8bb..bffb40085c67 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>> @@ -609,8 +609,22 @@ static struct msm_display_topology 
>>> dpu_encoder_get_topology(
>>>       topology.num_enc = 0;
>>>       topology.num_intf = intf_count;
>>>   +    drm_enc = &dpu_enc->base;
>>> +    priv = drm_enc->dev->dev_private;
>>> +    if (priv && priv->dsc) {
>>> +        /* In case of Display Stream Compression DSC, we would use
>>> +         * 2 encoders, 2 line mixers and 1 interface
>>> +         * this is power optimal and can drive upto (including) 4k
>>> +         * screens
>>> +         */
>>> +        topology.num_enc = 2;
>>> +        topology.num_intf = 1;
>>> +        topology.num_lm = 2;
>>> +    }
>>> +
>>>       return topology;
>>>   }
>>> +
>>>   static int dpu_encoder_virt_atomic_check(
>>>           struct drm_encoder *drm_enc,
>>>           struct drm_crtc_state *crtc_state,
>>>


-- 
With best wishes
Dmitry

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

* Re: [Freedreno] [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support
  2021-05-26 15:00       ` Jeffrey Hugo
@ 2021-06-02 10:56         ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-06-02 10:56 UTC (permalink / raw)
  To: Jeffrey Hugo
  Cc: Rob Clark, DTML, Jonathan Marek, David Airlie, MSM, lkml,
	Abhinav Kumar, Bjorn Andersson, Rob Herring,
	open list:DRM PANEL DRIVERS, Daniel Vetter, Dmitry Baryshkov,
	freedreno

On 26-05-21, 09:00, Jeffrey Hugo wrote:
> On Tue, May 25, 2021 at 11:46 PM Vinod Koul <vkoul@kernel.org> wrote:
> > On 21-05-21, 08:09, Jeffrey Hugo wrote:
> > > On Fri, May 21, 2021 at 6:50 AM Vinod Koul <vkoul@kernel.org> wrote:
> > > >
> > > > Display Stream Compression (DSC) compresses the display stream in host which
> > > > is later decoded by panel. This series enables this for Qualcomm msm driver.
> > > > This was tested on Google Pixel3 phone which use LGE SW43408 panel.
> > > >
> > > > The changes include adding DT properties for DSC then hardware blocks support
> > > > required in DPU1 driver and support in encoder. We also add support in DSI
> > > > and introduce required topology changes.
> > > >
> > > > In order for panel to set the DSC parameters we add dsc in drm_panel and set
> > > > it from the msm driver.
> > > >
> > > > Complete changes which enable this for Pixel3 along with panel driver (not
> > > > part of this series) and DT changes can be found at:
> > > > git.linaro.org/people/vinod.koul/kernel.git pixel/dsc_rfc
> > > >
> > > > Comments welcome!
> > >
> > > This feels backwards to me.  I've only skimmed this series, and the DT
> > > changes didn't come through for me, so perhaps I have an incomplete
> > > view.
> >
> > Not sure why, I see it on lore:
> > https://lore.kernel.org/dri-devel/20210521124946.3617862-3-vkoul@kernel.org/
> >
> > > DSC is not MSM specific.  There is a standard for it.  Yet it looks
> > > like everything is implemented in a MSM specific way, and then pushed
> > > to the panel.  So, every vendor needs to implement their vendor
> > > specific way to get the DSC info, and then push it to the panel?
> > > Seems wrong, given there is an actual standard for this feature.
> >
> > I have added slice and bpp info in the DT here under the host and then
> > pass the generic struct drm_dsc_config to panel which allows panel to
> > write the pps cmd
> >
> > Nothing above is MSM specific.. It can very well work with non MSM
> > controllers too.
> 
> I disagree.
> 
> The DT bindings you defined (thanks for the direct link) are MSM
> specific.  I'm not talking (yet) about the properties you defined, but
> purely from the stand point that you defined the binding within the
> scope of the MSM dsi binding.  No other vendor can use those bindings.
> Of course, if we look at the properties themselves, they are prefixed
> with "qcom", which is vendor specific.
> 
> So, purely on the face of it, this is MSM specific.
> 
> Assuming we want a DT solution for DSC, I think it should be something
> like Documentation/devicetree/bindings/clock/clock-bindings.txt (the
> first example that comes to mind), which is a non-vendor specific
> generic set of properties that each vendor/device specific binding can
> inherit.  Panel has similar things.
> 
> Specific to the properties, I don't much like that you duplicate BPP,
> which is already associated with the panel (although perhaps not in
> the scope of DT).  What if the panel and your DSC bindings disagree?
> Also, I guess I need to ask, have you read the DSC spec?  Last I
> looked, there were something like 3 dozen properties that could be
> configured.  You have five in your proposed binding.  To me, this is
> not a generic DSC solution, this is MSM specific (and frankly I don't
> think this supports all the configuration the MSM hardware can do,
> either).

I would concede the point that DT is msm specific. I dont disagree on
making them a common dsc biding which anyone can use. I think your idea
does have merits...

I am still not sure who should include these properties, would it be the
panel or host. Either would work and rest of the system can use these
properties...

-- 
~Vinod

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

* Re: [Freedreno] [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support
@ 2021-06-02 10:56         ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-06-02 10:56 UTC (permalink / raw)
  To: Jeffrey Hugo
  Cc: DTML, Jonathan Marek, David Airlie, MSM, lkml, Abhinav Kumar,
	Bjorn Andersson, Rob Herring, open list:DRM PANEL DRIVERS,
	Dmitry Baryshkov, freedreno

On 26-05-21, 09:00, Jeffrey Hugo wrote:
> On Tue, May 25, 2021 at 11:46 PM Vinod Koul <vkoul@kernel.org> wrote:
> > On 21-05-21, 08:09, Jeffrey Hugo wrote:
> > > On Fri, May 21, 2021 at 6:50 AM Vinod Koul <vkoul@kernel.org> wrote:
> > > >
> > > > Display Stream Compression (DSC) compresses the display stream in host which
> > > > is later decoded by panel. This series enables this for Qualcomm msm driver.
> > > > This was tested on Google Pixel3 phone which use LGE SW43408 panel.
> > > >
> > > > The changes include adding DT properties for DSC then hardware blocks support
> > > > required in DPU1 driver and support in encoder. We also add support in DSI
> > > > and introduce required topology changes.
> > > >
> > > > In order for panel to set the DSC parameters we add dsc in drm_panel and set
> > > > it from the msm driver.
> > > >
> > > > Complete changes which enable this for Pixel3 along with panel driver (not
> > > > part of this series) and DT changes can be found at:
> > > > git.linaro.org/people/vinod.koul/kernel.git pixel/dsc_rfc
> > > >
> > > > Comments welcome!
> > >
> > > This feels backwards to me.  I've only skimmed this series, and the DT
> > > changes didn't come through for me, so perhaps I have an incomplete
> > > view.
> >
> > Not sure why, I see it on lore:
> > https://lore.kernel.org/dri-devel/20210521124946.3617862-3-vkoul@kernel.org/
> >
> > > DSC is not MSM specific.  There is a standard for it.  Yet it looks
> > > like everything is implemented in a MSM specific way, and then pushed
> > > to the panel.  So, every vendor needs to implement their vendor
> > > specific way to get the DSC info, and then push it to the panel?
> > > Seems wrong, given there is an actual standard for this feature.
> >
> > I have added slice and bpp info in the DT here under the host and then
> > pass the generic struct drm_dsc_config to panel which allows panel to
> > write the pps cmd
> >
> > Nothing above is MSM specific.. It can very well work with non MSM
> > controllers too.
> 
> I disagree.
> 
> The DT bindings you defined (thanks for the direct link) are MSM
> specific.  I'm not talking (yet) about the properties you defined, but
> purely from the stand point that you defined the binding within the
> scope of the MSM dsi binding.  No other vendor can use those bindings.
> Of course, if we look at the properties themselves, they are prefixed
> with "qcom", which is vendor specific.
> 
> So, purely on the face of it, this is MSM specific.
> 
> Assuming we want a DT solution for DSC, I think it should be something
> like Documentation/devicetree/bindings/clock/clock-bindings.txt (the
> first example that comes to mind), which is a non-vendor specific
> generic set of properties that each vendor/device specific binding can
> inherit.  Panel has similar things.
> 
> Specific to the properties, I don't much like that you duplicate BPP,
> which is already associated with the panel (although perhaps not in
> the scope of DT).  What if the panel and your DSC bindings disagree?
> Also, I guess I need to ask, have you read the DSC spec?  Last I
> looked, there were something like 3 dozen properties that could be
> configured.  You have five in your proposed binding.  To me, this is
> not a generic DSC solution, this is MSM specific (and frankly I don't
> think this supports all the configuration the MSM hardware can do,
> either).

I would concede the point that DT is msm specific. I dont disagree on
making them a common dsc biding which anyone can use. I think your idea
does have merits...

I am still not sure who should include these properties, would it be the
panel or host. Either would work and rest of the system can use these
properties...

-- 
~Vinod

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

* Re: [Freedreno] [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support
  2021-05-27 23:30         ` Rob Clark
@ 2021-06-02 11:01           ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-06-02 11:01 UTC (permalink / raw)
  To: Rob Clark
  Cc: Jeffrey Hugo, DTML, Jonathan Marek, David Airlie, MSM, lkml,
	Abhinav Kumar, Bjorn Andersson, Rob Herring,
	open list:DRM PANEL DRIVERS, Daniel Vetter, Dmitry Baryshkov,
	freedreno

On 27-05-21, 16:30, Rob Clark wrote:
> On Wed, May 26, 2021 at 8:00 AM Jeffrey Hugo <jeffrey.l.hugo@gmail.com> wrote:
> > On Tue, May 25, 2021 at 11:46 PM Vinod Koul <vkoul@kernel.org> wrote:

> > Frankly, I don't like the MSM ACPI solution that I've seen on the laptops.
> > The ACPI assumes the entire MDSS (including DSI parts) and GPU is one
> > device, and ultimately handled by one driver.  That driver needs to
> > get a value from UEFI (set by the bootloader) that is the "panel id".
> > Then the driver calls into ACPI (I think its _ROM, but I might be
> > mistaken, doing this from memory) with that id.  It gets back a binary
> > blob which is mostly an xml file (format is publicly documented) that
> > contains the panel timings and such.
> 
> tbh, I kinda suspect that having a single "gpu" device (which also
> includes venus, in addition to display, IIRC) in the ACPI tables is a
> windowsism, trying to make things look to userspace like a single "GPU
> card" in the x86 world.. but either way, I think the ACPI tables on
> the windows arm laptops which use dsi->bridge->edp is too much of a
> lost cause to even consider here.  Possibly ACPI boot on these devices
> would be more feasible on newer devices which have direct eDP out of
> the SoC without requiring external bridge/panel glue.

yeah that is always a very different world. although it might make sense
to use information in tables and try to deduce information about the
system can be helpful...

> I'd worry more about what makes sense in a DT world, when it comes to
> DT bindings.

And do you have thoughts on that..?

-- 
~Vinod

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

* Re: [Freedreno] [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support
@ 2021-06-02 11:01           ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-06-02 11:01 UTC (permalink / raw)
  To: Rob Clark
  Cc: DTML, Jonathan Marek, Jeffrey Hugo, David Airlie, MSM, lkml,
	Abhinav Kumar, Bjorn Andersson, Rob Herring,
	open list:DRM PANEL DRIVERS, Dmitry Baryshkov, freedreno

On 27-05-21, 16:30, Rob Clark wrote:
> On Wed, May 26, 2021 at 8:00 AM Jeffrey Hugo <jeffrey.l.hugo@gmail.com> wrote:
> > On Tue, May 25, 2021 at 11:46 PM Vinod Koul <vkoul@kernel.org> wrote:

> > Frankly, I don't like the MSM ACPI solution that I've seen on the laptops.
> > The ACPI assumes the entire MDSS (including DSI parts) and GPU is one
> > device, and ultimately handled by one driver.  That driver needs to
> > get a value from UEFI (set by the bootloader) that is the "panel id".
> > Then the driver calls into ACPI (I think its _ROM, but I might be
> > mistaken, doing this from memory) with that id.  It gets back a binary
> > blob which is mostly an xml file (format is publicly documented) that
> > contains the panel timings and such.
> 
> tbh, I kinda suspect that having a single "gpu" device (which also
> includes venus, in addition to display, IIRC) in the ACPI tables is a
> windowsism, trying to make things look to userspace like a single "GPU
> card" in the x86 world.. but either way, I think the ACPI tables on
> the windows arm laptops which use dsi->bridge->edp is too much of a
> lost cause to even consider here.  Possibly ACPI boot on these devices
> would be more feasible on newer devices which have direct eDP out of
> the SoC without requiring external bridge/panel glue.

yeah that is always a very different world. although it might make sense
to use information in tables and try to deduce information about the
system can be helpful...

> I'd worry more about what makes sense in a DT world, when it comes to
> DT bindings.

And do you have thoughts on that..?

-- 
~Vinod

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

* Re: [RFC PATCH 03/13] drm/msm/dsi: add support for dsc data
  2021-05-27 23:45     ` Dmitry Baryshkov
@ 2021-06-02 11:06       ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-06-02 11:06 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Rob Clark, linux-arm-msm, Bjorn Andersson, David Airlie,
	Daniel Vetter, Jonathan Marek, Abhinav Kumar, linux-kernel,
	dri-devel, freedreno

On 28-05-21, 02:45, Dmitry Baryshkov wrote:
> On 21/05/2021 15:49, Vinod Koul wrote:
> > DSC needs some configuration from device tree, add support to read and
> > store these params and add DSC structures in msm_drv
> > 
> > Signed-off-by: Vinod Koul <vkoul@kernel.org>
> > ---
> >   drivers/gpu/drm/msm/dsi/dsi_host.c | 170 +++++++++++++++++++++++++++++
> >   drivers/gpu/drm/msm/msm_drv.h      |  32 ++++++
> >   2 files changed, 202 insertions(+)
> > 
> 
> 
> [skipped]
> 
> 
> >   		DRM_DEV_ERROR(dev, "%s: invalid lane configuration %d\n",
> > diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
> > index 2668941df529..26661dd43936 100644
> > --- a/drivers/gpu/drm/msm/msm_drv.h
> > +++ b/drivers/gpu/drm/msm/msm_drv.h
> > @@ -30,6 +30,7 @@
> >   #include <drm/drm_plane_helper.h>
> >   #include <drm/drm_probe_helper.h>
> >   #include <drm/drm_fb_helper.h>
> > +#include <drm/drm_dsc.h>
> >   #include <drm/msm_drm.h>
> >   #include <drm/drm_gem.h>
> > @@ -70,6 +71,16 @@ enum msm_mdp_plane_property {
> >   #define MSM_GPU_MAX_RINGS 4
> >   #define MAX_H_TILES_PER_DISPLAY 2
> > +/**
> > + * enum msm_display_compression_type - compression method used for pixel stream
> > + * @MSM_DISPLAY_COMPRESSION_NONE:	Pixel data is not compressed
> > + * @MSM_DISPLAY_COMPRESSION_DSC:	DSC compresison is used
> > + */
> > +enum msm_display_compression_type {
> > +	MSM_DISPLAY_COMPRESSION_NONE,
> > +	MSM_DISPLAY_COMPRESSION_DSC,
> > +};
> > +
> 
> Seems to be unused

Yeah this was started from downstream which used this and I seem to have
not cleared this up, thanks for pointing. Will remove..

-- 
~Vinod

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

* Re: [RFC PATCH 03/13] drm/msm/dsi: add support for dsc data
@ 2021-06-02 11:06       ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-06-02 11:06 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, dri-devel, freedreno

On 28-05-21, 02:45, Dmitry Baryshkov wrote:
> On 21/05/2021 15:49, Vinod Koul wrote:
> > DSC needs some configuration from device tree, add support to read and
> > store these params and add DSC structures in msm_drv
> > 
> > Signed-off-by: Vinod Koul <vkoul@kernel.org>
> > ---
> >   drivers/gpu/drm/msm/dsi/dsi_host.c | 170 +++++++++++++++++++++++++++++
> >   drivers/gpu/drm/msm/msm_drv.h      |  32 ++++++
> >   2 files changed, 202 insertions(+)
> > 
> 
> 
> [skipped]
> 
> 
> >   		DRM_DEV_ERROR(dev, "%s: invalid lane configuration %d\n",
> > diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
> > index 2668941df529..26661dd43936 100644
> > --- a/drivers/gpu/drm/msm/msm_drv.h
> > +++ b/drivers/gpu/drm/msm/msm_drv.h
> > @@ -30,6 +30,7 @@
> >   #include <drm/drm_plane_helper.h>
> >   #include <drm/drm_probe_helper.h>
> >   #include <drm/drm_fb_helper.h>
> > +#include <drm/drm_dsc.h>
> >   #include <drm/msm_drm.h>
> >   #include <drm/drm_gem.h>
> > @@ -70,6 +71,16 @@ enum msm_mdp_plane_property {
> >   #define MSM_GPU_MAX_RINGS 4
> >   #define MAX_H_TILES_PER_DISPLAY 2
> > +/**
> > + * enum msm_display_compression_type - compression method used for pixel stream
> > + * @MSM_DISPLAY_COMPRESSION_NONE:	Pixel data is not compressed
> > + * @MSM_DISPLAY_COMPRESSION_DSC:	DSC compresison is used
> > + */
> > +enum msm_display_compression_type {
> > +	MSM_DISPLAY_COMPRESSION_NONE,
> > +	MSM_DISPLAY_COMPRESSION_DSC,
> > +};
> > +
> 
> Seems to be unused

Yeah this was started from downstream which used this and I seem to have
not cleared this up, thanks for pointing. Will remove..

-- 
~Vinod

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

* Re: [RFC PATCH 03/13] drm/msm/dsi: add support for dsc data
  2021-05-28 10:29     ` Dmitry Baryshkov
@ 2021-06-02 11:17       ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-06-02 11:17 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Rob Clark, linux-arm-msm, Bjorn Andersson, David Airlie,
	Daniel Vetter, Jonathan Marek, Abhinav Kumar, linux-kernel,
	dri-devel, freedreno

On 28-05-21, 13:29, Dmitry Baryshkov wrote:
> On 21/05/2021 15:49, Vinod Koul wrote:
> > DSC needs some configuration from device tree, add support to read and
> > store these params and add DSC structures in msm_drv
> > 
> > Signed-off-by: Vinod Koul <vkoul@kernel.org>
> > ---
> >   drivers/gpu/drm/msm/dsi/dsi_host.c | 170 +++++++++++++++++++++++++++++
> >   drivers/gpu/drm/msm/msm_drv.h      |  32 ++++++
> >   2 files changed, 202 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
> > index 8a10e4343281..864d3c655e73 100644
> > --- a/drivers/gpu/drm/msm/dsi/dsi_host.c
> > +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
> > @@ -156,6 +156,7 @@ struct msm_dsi_host {
> >   	struct regmap *sfpb;
> >   	struct drm_display_mode *mode;
> > +	struct msm_display_dsc_config *dsc;
> >   	/* connected device info */
> >   	struct device_node *device_node;
> > @@ -1744,6 +1745,168 @@ static int dsi_host_parse_lane_data(struct msm_dsi_host *msm_host,
> >   	return -EINVAL;
> >   }
> > +static u32 dsi_dsc_rc_buf_thresh[DSC_NUM_BUF_RANGES - 1] = {
> > +	0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, 0x62,
> > +	0x69, 0x70, 0x77, 0x79, 0x7b, 0x7d, 0x7e
> > +};
> 
> I think we should move this table to a generic place. AMD and Intel DSC code
> uses the same table, shifted by 6 (and both of those drivers shift it before
> writing to the HW). Intel modifies this table for 6bpp case. AMD seems to
> use it as is.
> 
> > +
> > +/* only 8bpc, 8bpp added */
> > +static char min_qp[DSC_NUM_BUF_RANGES] = {
> > +	0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 13
> > +};
> > +
> > +static char max_qp[DSC_NUM_BUF_RANGES] = {
> > +	4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 11, 12, 13, 13, 15
> > +};
> > +
> > +static char bpg_offset[DSC_NUM_BUF_RANGES] = {
> > +	2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12
> > +};
> 
> And these parameters seem to be generic too. Intel DSC code contains them in
> a bit different form. Should we probably move them to the drm_dsc.c and use
> the tables the generic location?
> 
> AMD drivers uses a bit different values at the first glance, so let's stick
> with Intel version.

Yeah I think this is a good suggestion. I did look into and had this in
my todo. Yes drm_dsc.c would be apt for the move..

-- 
~Vinod

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

* Re: [RFC PATCH 03/13] drm/msm/dsi: add support for dsc data
@ 2021-06-02 11:17       ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-06-02 11:17 UTC (permalink / raw)
  To: Dmitry Baryshkov
  Cc: Jonathan Marek, David Airlie, linux-arm-msm, linux-kernel,
	Abhinav Kumar, Bjorn Andersson, dri-devel, freedreno

On 28-05-21, 13:29, Dmitry Baryshkov wrote:
> On 21/05/2021 15:49, Vinod Koul wrote:
> > DSC needs some configuration from device tree, add support to read and
> > store these params and add DSC structures in msm_drv
> > 
> > Signed-off-by: Vinod Koul <vkoul@kernel.org>
> > ---
> >   drivers/gpu/drm/msm/dsi/dsi_host.c | 170 +++++++++++++++++++++++++++++
> >   drivers/gpu/drm/msm/msm_drv.h      |  32 ++++++
> >   2 files changed, 202 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
> > index 8a10e4343281..864d3c655e73 100644
> > --- a/drivers/gpu/drm/msm/dsi/dsi_host.c
> > +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
> > @@ -156,6 +156,7 @@ struct msm_dsi_host {
> >   	struct regmap *sfpb;
> >   	struct drm_display_mode *mode;
> > +	struct msm_display_dsc_config *dsc;
> >   	/* connected device info */
> >   	struct device_node *device_node;
> > @@ -1744,6 +1745,168 @@ static int dsi_host_parse_lane_data(struct msm_dsi_host *msm_host,
> >   	return -EINVAL;
> >   }
> > +static u32 dsi_dsc_rc_buf_thresh[DSC_NUM_BUF_RANGES - 1] = {
> > +	0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, 0x62,
> > +	0x69, 0x70, 0x77, 0x79, 0x7b, 0x7d, 0x7e
> > +};
> 
> I think we should move this table to a generic place. AMD and Intel DSC code
> uses the same table, shifted by 6 (and both of those drivers shift it before
> writing to the HW). Intel modifies this table for 6bpp case. AMD seems to
> use it as is.
> 
> > +
> > +/* only 8bpc, 8bpp added */
> > +static char min_qp[DSC_NUM_BUF_RANGES] = {
> > +	0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 13
> > +};
> > +
> > +static char max_qp[DSC_NUM_BUF_RANGES] = {
> > +	4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 11, 12, 13, 13, 15
> > +};
> > +
> > +static char bpg_offset[DSC_NUM_BUF_RANGES] = {
> > +	2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12
> > +};
> 
> And these parameters seem to be generic too. Intel DSC code contains them in
> a bit different form. Should we probably move them to the drm_dsc.c and use
> the tables the generic location?
> 
> AMD drivers uses a bit different values at the first glance, so let's stick
> with Intel version.

Yeah I think this is a good suggestion. I did look into and had this in
my todo. Yes drm_dsc.c would be apt for the move..

-- 
~Vinod

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

* Re: [Freedreno] [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support
  2021-06-02 11:01           ` Vinod Koul
@ 2021-06-03 23:40             ` abhinavk
  -1 siblings, 0 replies; 91+ messages in thread
From: abhinavk @ 2021-06-03 23:40 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Rob Clark, DTML, Jonathan Marek, Jeffrey Hugo, David Airlie, MSM,
	lkml, Bjorn Andersson, Rob Herring, open list:DRM PANEL DRIVERS,
	Daniel Vetter, Dmitry Baryshkov, freedreno

On 2021-06-02 04:01, Vinod Koul wrote:
> On 27-05-21, 16:30, Rob Clark wrote:
>> On Wed, May 26, 2021 at 8:00 AM Jeffrey Hugo 
>> <jeffrey.l.hugo@gmail.com> wrote:
>> > On Tue, May 25, 2021 at 11:46 PM Vinod Koul <vkoul@kernel.org> wrote:
> 
>> > Frankly, I don't like the MSM ACPI solution that I've seen on the laptops.
>> > The ACPI assumes the entire MDSS (including DSI parts) and GPU is one
>> > device, and ultimately handled by one driver.  That driver needs to
>> > get a value from UEFI (set by the bootloader) that is the "panel id".
>> > Then the driver calls into ACPI (I think its _ROM, but I might be
>> > mistaken, doing this from memory) with that id.  It gets back a binary
>> > blob which is mostly an xml file (format is publicly documented) that
>> > contains the panel timings and such.
>> 
>> tbh, I kinda suspect that having a single "gpu" device (which also
>> includes venus, in addition to display, IIRC) in the ACPI tables is a
>> windowsism, trying to make things look to userspace like a single "GPU
>> card" in the x86 world.. but either way, I think the ACPI tables on
>> the windows arm laptops which use dsi->bridge->edp is too much of a
>> lost cause to even consider here.  Possibly ACPI boot on these devices
>> would be more feasible on newer devices which have direct eDP out of
>> the SoC without requiring external bridge/panel glue.
> 
> yeah that is always a very different world. although it might make 
> sense
> to use information in tables and try to deduce information about the
> system can be helpful...
> 
>> I'd worry more about what makes sense in a DT world, when it comes to
>> DT bindings.
> 
> And do you have thoughts on that..?

At the moment, I will comment on the bindings first and my idea on how 
to proceed.
The bindings mentioned here: 
https://lore.kernel.org/dri-devel/20210521124946.3617862-3-vkoul@kernel.org/ 
seem to be just
taken directly from downstream which was not the plan.

I think all of these should be part of the generic panel bindings as 
none of these are QC specific:

@@ -188,6 +195,14 @@ Example:
  		qcom,master-dsi;
  		qcom,sync-dual-dsi;

+		qcom,mdss-dsc-enabled;
+		qcom,mdss-slice-height = <16>;
+		qcom,mdss-slice-width = <540>;
+		qcom,mdss-slice-per-pkt = <1>;
+		qcom,mdss-bit-per-component = <8>;
+		qcom,mdss-bit-per-pixel = <8>;
+		qcom,mdss-block-prediction-enable;
+

How about having a panel-dsc.yaml which will have these properties and 
have a panel-dsc node to have this information?

I would like to hear the feedback on this proposal then the series can 
be reworked.

Thanks

Abhinav

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

* Re: [Freedreno] [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support
@ 2021-06-03 23:40             ` abhinavk
  0 siblings, 0 replies; 91+ messages in thread
From: abhinavk @ 2021-06-03 23:40 UTC (permalink / raw)
  To: Vinod Koul
  Cc: DTML, Jonathan Marek, Jeffrey Hugo, David Airlie, MSM, lkml,
	open list:DRM PANEL DRIVERS, Bjorn Andersson, Rob Herring,
	Dmitry Baryshkov, freedreno

On 2021-06-02 04:01, Vinod Koul wrote:
> On 27-05-21, 16:30, Rob Clark wrote:
>> On Wed, May 26, 2021 at 8:00 AM Jeffrey Hugo 
>> <jeffrey.l.hugo@gmail.com> wrote:
>> > On Tue, May 25, 2021 at 11:46 PM Vinod Koul <vkoul@kernel.org> wrote:
> 
>> > Frankly, I don't like the MSM ACPI solution that I've seen on the laptops.
>> > The ACPI assumes the entire MDSS (including DSI parts) and GPU is one
>> > device, and ultimately handled by one driver.  That driver needs to
>> > get a value from UEFI (set by the bootloader) that is the "panel id".
>> > Then the driver calls into ACPI (I think its _ROM, but I might be
>> > mistaken, doing this from memory) with that id.  It gets back a binary
>> > blob which is mostly an xml file (format is publicly documented) that
>> > contains the panel timings and such.
>> 
>> tbh, I kinda suspect that having a single "gpu" device (which also
>> includes venus, in addition to display, IIRC) in the ACPI tables is a
>> windowsism, trying to make things look to userspace like a single "GPU
>> card" in the x86 world.. but either way, I think the ACPI tables on
>> the windows arm laptops which use dsi->bridge->edp is too much of a
>> lost cause to even consider here.  Possibly ACPI boot on these devices
>> would be more feasible on newer devices which have direct eDP out of
>> the SoC without requiring external bridge/panel glue.
> 
> yeah that is always a very different world. although it might make 
> sense
> to use information in tables and try to deduce information about the
> system can be helpful...
> 
>> I'd worry more about what makes sense in a DT world, when it comes to
>> DT bindings.
> 
> And do you have thoughts on that..?

At the moment, I will comment on the bindings first and my idea on how 
to proceed.
The bindings mentioned here: 
https://lore.kernel.org/dri-devel/20210521124946.3617862-3-vkoul@kernel.org/ 
seem to be just
taken directly from downstream which was not the plan.

I think all of these should be part of the generic panel bindings as 
none of these are QC specific:

@@ -188,6 +195,14 @@ Example:
  		qcom,master-dsi;
  		qcom,sync-dual-dsi;

+		qcom,mdss-dsc-enabled;
+		qcom,mdss-slice-height = <16>;
+		qcom,mdss-slice-width = <540>;
+		qcom,mdss-slice-per-pkt = <1>;
+		qcom,mdss-bit-per-component = <8>;
+		qcom,mdss-bit-per-pixel = <8>;
+		qcom,mdss-block-prediction-enable;
+

How about having a panel-dsc.yaml which will have these properties and 
have a panel-dsc node to have this information?

I would like to hear the feedback on this proposal then the series can 
be reworked.

Thanks

Abhinav

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

* Re: [Freedreno] [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support
  2021-06-02 11:01           ` Vinod Koul
@ 2021-06-04  2:36             ` Rob Clark
  -1 siblings, 0 replies; 91+ messages in thread
From: Rob Clark @ 2021-06-04  2:36 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Jeffrey Hugo, DTML, Jonathan Marek, David Airlie, MSM, lkml,
	Abhinav Kumar, Bjorn Andersson, Rob Herring,
	open list:DRM PANEL DRIVERS, Daniel Vetter, Dmitry Baryshkov,
	freedreno

On Wed, Jun 2, 2021 at 4:01 AM Vinod Koul <vkoul@kernel.org> wrote:
>
> On 27-05-21, 16:30, Rob Clark wrote:
> > On Wed, May 26, 2021 at 8:00 AM Jeffrey Hugo <jeffrey.l.hugo@gmail.com> wrote:
> > > On Tue, May 25, 2021 at 11:46 PM Vinod Koul <vkoul@kernel.org> wrote:
>
> > > Frankly, I don't like the MSM ACPI solution that I've seen on the laptops.
> > > The ACPI assumes the entire MDSS (including DSI parts) and GPU is one
> > > device, and ultimately handled by one driver.  That driver needs to
> > > get a value from UEFI (set by the bootloader) that is the "panel id".
> > > Then the driver calls into ACPI (I think its _ROM, but I might be
> > > mistaken, doing this from memory) with that id.  It gets back a binary
> > > blob which is mostly an xml file (format is publicly documented) that
> > > contains the panel timings and such.
> >
> > tbh, I kinda suspect that having a single "gpu" device (which also
> > includes venus, in addition to display, IIRC) in the ACPI tables is a
> > windowsism, trying to make things look to userspace like a single "GPU
> > card" in the x86 world.. but either way, I think the ACPI tables on
> > the windows arm laptops which use dsi->bridge->edp is too much of a
> > lost cause to even consider here.  Possibly ACPI boot on these devices
> > would be more feasible on newer devices which have direct eDP out of
> > the SoC without requiring external bridge/panel glue.
>
> yeah that is always a very different world. although it might make sense
> to use information in tables and try to deduce information about the
> system can be helpful...
>
> > I'd worry more about what makes sense in a DT world, when it comes to
> > DT bindings.
>
> And do you have thoughts on that..?

Only that I wouldn't get too hung up on existing snapdragon ACPI
tables.. not sure if there is prior art as far as ACPI tables for this
on x86 systems, if so that *might* be a thing to consider, but
otherwise it does sound a bit like we want less qcom specific bindings
here.  But other than that I'll leave it to folks who spend more time
thinking about bindings.. left to my own devices I'd come up with a
point solution and go back to working on mesa, so that probably isn't
the opinion you want to follow ;-)

BR,
-R

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

* Re: [Freedreno] [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support
@ 2021-06-04  2:36             ` Rob Clark
  0 siblings, 0 replies; 91+ messages in thread
From: Rob Clark @ 2021-06-04  2:36 UTC (permalink / raw)
  To: Vinod Koul
  Cc: DTML, Jonathan Marek, Jeffrey Hugo, David Airlie, MSM, lkml,
	Abhinav Kumar, Bjorn Andersson, Rob Herring,
	open list:DRM PANEL DRIVERS, Dmitry Baryshkov, freedreno

On Wed, Jun 2, 2021 at 4:01 AM Vinod Koul <vkoul@kernel.org> wrote:
>
> On 27-05-21, 16:30, Rob Clark wrote:
> > On Wed, May 26, 2021 at 8:00 AM Jeffrey Hugo <jeffrey.l.hugo@gmail.com> wrote:
> > > On Tue, May 25, 2021 at 11:46 PM Vinod Koul <vkoul@kernel.org> wrote:
>
> > > Frankly, I don't like the MSM ACPI solution that I've seen on the laptops.
> > > The ACPI assumes the entire MDSS (including DSI parts) and GPU is one
> > > device, and ultimately handled by one driver.  That driver needs to
> > > get a value from UEFI (set by the bootloader) that is the "panel id".
> > > Then the driver calls into ACPI (I think its _ROM, but I might be
> > > mistaken, doing this from memory) with that id.  It gets back a binary
> > > blob which is mostly an xml file (format is publicly documented) that
> > > contains the panel timings and such.
> >
> > tbh, I kinda suspect that having a single "gpu" device (which also
> > includes venus, in addition to display, IIRC) in the ACPI tables is a
> > windowsism, trying to make things look to userspace like a single "GPU
> > card" in the x86 world.. but either way, I think the ACPI tables on
> > the windows arm laptops which use dsi->bridge->edp is too much of a
> > lost cause to even consider here.  Possibly ACPI boot on these devices
> > would be more feasible on newer devices which have direct eDP out of
> > the SoC without requiring external bridge/panel glue.
>
> yeah that is always a very different world. although it might make sense
> to use information in tables and try to deduce information about the
> system can be helpful...
>
> > I'd worry more about what makes sense in a DT world, when it comes to
> > DT bindings.
>
> And do you have thoughts on that..?

Only that I wouldn't get too hung up on existing snapdragon ACPI
tables.. not sure if there is prior art as far as ACPI tables for this
on x86 systems, if so that *might* be a thing to consider, but
otherwise it does sound a bit like we want less qcom specific bindings
here.  But other than that I'll leave it to folks who spend more time
thinking about bindings.. left to my own devices I'd come up with a
point solution and go back to working on mesa, so that probably isn't
the opinion you want to follow ;-)

BR,
-R

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

* Re: [Freedreno] [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support
  2021-06-03 23:40             ` abhinavk
@ 2021-06-17  8:06               ` Vinod Koul
  -1 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-06-17  8:06 UTC (permalink / raw)
  To: abhinavk
  Cc: Rob Clark, DTML, Jonathan Marek, Jeffrey Hugo, David Airlie, MSM,
	lkml, Bjorn Andersson, Rob Herring, open list:DRM PANEL DRIVERS,
	Daniel Vetter, Dmitry Baryshkov, freedreno

On 03-06-21, 16:40, abhinavk@codeaurora.org wrote:
> On 2021-06-02 04:01, Vinod Koul wrote:
> > On 27-05-21, 16:30, Rob Clark wrote:
> > 
> > yeah that is always a very different world. although it might make sense
> > to use information in tables and try to deduce information about the
> > system can be helpful...
> > 
> > > I'd worry more about what makes sense in a DT world, when it comes to
> > > DT bindings.
> > 
> > And do you have thoughts on that..?
> 
> At the moment, I will comment on the bindings first and my idea on how to
> proceed.
> The bindings mentioned here:
> https://lore.kernel.org/dri-devel/20210521124946.3617862-3-vkoul@kernel.org/
> seem to be just
> taken directly from downstream which was not the plan.
> 
> I think all of these should be part of the generic panel bindings as none of
> these are QC specific:

Okay so we have discussed this w/ Bjorn and Abhinav and here are the
conclusions and recommendations for binding

1. the properties are generic and not msm specific
2. The host supports multiple formats but the one we choose depends
mostly upon panel. Notably host runs the config which the panel supports.

So the recommendations is to add a table of dsc properties in the panel
driver. No DT binding here.

I should also note that for DP we should be able to calculate these
values from EDID like the i915 driver seems to do

With this I will drop the binding patch and move dsc properties to panel
driver

Thanks

-- 
~Vinod

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

* Re: [Freedreno] [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support
@ 2021-06-17  8:06               ` Vinod Koul
  0 siblings, 0 replies; 91+ messages in thread
From: Vinod Koul @ 2021-06-17  8:06 UTC (permalink / raw)
  To: abhinavk
  Cc: DTML, Jonathan Marek, Jeffrey Hugo, David Airlie, MSM, lkml,
	open list:DRM PANEL DRIVERS, Bjorn Andersson, Rob Clark,
	Rob Herring, Dmitry Baryshkov, freedreno

On 03-06-21, 16:40, abhinavk@codeaurora.org wrote:
> On 2021-06-02 04:01, Vinod Koul wrote:
> > On 27-05-21, 16:30, Rob Clark wrote:
> > 
> > yeah that is always a very different world. although it might make sense
> > to use information in tables and try to deduce information about the
> > system can be helpful...
> > 
> > > I'd worry more about what makes sense in a DT world, when it comes to
> > > DT bindings.
> > 
> > And do you have thoughts on that..?
> 
> At the moment, I will comment on the bindings first and my idea on how to
> proceed.
> The bindings mentioned here:
> https://lore.kernel.org/dri-devel/20210521124946.3617862-3-vkoul@kernel.org/
> seem to be just
> taken directly from downstream which was not the plan.
> 
> I think all of these should be part of the generic panel bindings as none of
> these are QC specific:

Okay so we have discussed this w/ Bjorn and Abhinav and here are the
conclusions and recommendations for binding

1. the properties are generic and not msm specific
2. The host supports multiple formats but the one we choose depends
mostly upon panel. Notably host runs the config which the panel supports.

So the recommendations is to add a table of dsc properties in the panel
driver. No DT binding here.

I should also note that for DP we should be able to calculate these
values from EDID like the i915 driver seems to do

With this I will drop the binding patch and move dsc properties to panel
driver

Thanks

-- 
~Vinod

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

end of thread, other threads:[~2021-06-17  8:06 UTC | newest]

Thread overview: 91+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-21 12:49 [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support Vinod Koul
2021-05-21 12:49 ` Vinod Koul
2021-05-21 12:49 ` [RFC PATCH 01/13] drm/dsc: Add dsc pps header init function Vinod Koul
2021-05-21 12:49   ` Vinod Koul
2021-05-21 15:29   ` Daniel Vetter
2021-05-21 15:29     ` Daniel Vetter
2021-05-24  7:26     ` Vinod Koul
2021-05-21 12:49 ` [RFC PATCH 02/13] dt-bindings: msm/dsi: Document Display Stream Compression (DSC) parameters Vinod Koul
2021-05-21 12:49   ` Vinod Koul
2021-05-21 13:18   ` Rob Herring
2021-05-21 13:18     ` Rob Herring
2021-05-21 13:23     ` Vinod Koul
2021-05-21 13:23       ` Vinod Koul
2021-05-21 14:42   ` Bjorn Andersson
2021-05-21 14:42     ` Bjorn Andersson
2021-05-24  7:30     ` Vinod Koul
2021-05-24  7:30       ` Vinod Koul
2021-05-24 15:08       ` Bjorn Andersson
2021-05-24 15:08         ` Bjorn Andersson
2021-05-26  5:32         ` Vinod Koul
2021-05-26  5:32           ` Vinod Koul
2021-05-21 12:49 ` [RFC PATCH 03/13] drm/msm/disp/dpu1: Add support for DSC Vinod Koul
2021-05-21 12:49   ` Vinod Koul
2021-05-27 23:49   ` Dmitry Baryshkov
2021-05-27 23:49     ` Dmitry Baryshkov
2021-05-21 12:49 ` [RFC PATCH 03/13] drm/msm/dsi: add support for dsc data Vinod Koul
2021-05-21 12:49   ` Vinod Koul
2021-05-27 23:45   ` Dmitry Baryshkov
2021-05-27 23:45     ` Dmitry Baryshkov
2021-06-02 11:06     ` Vinod Koul
2021-06-02 11:06       ` Vinod Koul
2021-05-28 10:29   ` Dmitry Baryshkov
2021-05-28 10:29     ` Dmitry Baryshkov
2021-06-02 11:17     ` Vinod Koul
2021-06-02 11:17       ` Vinod Koul
2021-05-21 12:49 ` [RFC PATCH 04/13] drm/msm/disp/dpu1: Add support for DSC in pingpong block Vinod Koul
2021-05-21 12:49   ` Vinod Koul
2021-05-21 12:49 ` [RFC PATCH 04/13] drm/msm/disp/dpu1: Add support for DSC Vinod Koul
2021-05-21 12:49   ` Vinod Koul
2021-05-28 10:31   ` Dmitry Baryshkov
2021-05-28 10:31     ` Dmitry Baryshkov
2021-05-21 12:49 ` [RFC PATCH 05/13] drm/msm/disp/dpu1: Add support for DSC in pingpong block Vinod Koul
2021-05-21 12:49   ` Vinod Koul
2021-05-21 12:49 ` [RFC PATCH 05/13] drm/msm/dsi: add support for dsc data Vinod Koul
2021-05-21 12:49   ` Vinod Koul
2021-05-21 12:49 ` [RFC PATCH 06/13] drm/msm/disp/dpu1: Add DSC support in RM Vinod Koul
2021-05-21 12:49   ` Vinod Koul
2021-05-28 10:33   ` Dmitry Baryshkov
2021-05-28 10:33     ` Dmitry Baryshkov
2021-05-21 12:49 ` [RFC PATCH 07/13] drm/msm/disp/dpu1: Add DSC for SDM845 to hw_catalog Vinod Koul
2021-05-21 12:49   ` Vinod Koul
2021-05-21 12:49 ` [RFC PATCH 08/13] drm/msm/disp/dpu1: Add DSC support in hw_ctl Vinod Koul
2021-05-21 12:49   ` Vinod Koul
2021-05-21 12:49 ` [RFC PATCH 09/13] drm/msm/disp/dpu1: Don't use DSC with mode_3d Vinod Koul
2021-05-21 12:49   ` Vinod Koul
2021-05-28 10:36   ` Dmitry Baryshkov
2021-05-28 10:36     ` Dmitry Baryshkov
2021-05-21 12:49 ` [RFC PATCH 09/13] drm/msm/disp/dpu1: Dont " Vinod Koul
2021-05-21 12:49   ` Vinod Koul
2021-05-21 12:49 ` [RFC PATCH 10/13] drm/msm/disp/dpu1: Add support for DSC in encoder Vinod Koul
2021-05-21 12:49   ` Vinod Koul
2021-05-21 12:49 ` [RFC PATCH 11/13] drm/msm/disp/dpu1: Add support for DSC in topology Vinod Koul
2021-05-21 12:49   ` Vinod Koul
2021-05-28 10:39   ` Dmitry Baryshkov
2021-05-28 10:39     ` Dmitry Baryshkov
2021-05-28 22:23     ` abhinavk
2021-05-28 22:23       ` abhinavk
2021-05-28 22:29       ` Dmitry Baryshkov
2021-05-28 22:29         ` Dmitry Baryshkov
2021-05-21 12:49 ` [RFC PATCH 12/13] drm/msm/dsi: Add support for DSC configuration Vinod Koul
2021-05-21 12:49   ` Vinod Koul
2021-05-21 12:49 ` [RFC PATCH 13/13] drm/msm/dsi: Pass DSC params to drm_panel Vinod Koul
2021-05-21 12:49   ` Vinod Koul
2021-05-21 14:09 ` [Freedreno] [RFC PATCH 00/13] drm/msm: Add Display Stream Compression Support Jeffrey Hugo
2021-05-21 14:09   ` Jeffrey Hugo
2021-05-26  5:46   ` Vinod Koul
2021-05-26  5:46     ` Vinod Koul
2021-05-26 15:00     ` Jeffrey Hugo
2021-05-26 15:00       ` Jeffrey Hugo
2021-05-27 23:30       ` Rob Clark
2021-05-27 23:30         ` Rob Clark
2021-06-02 11:01         ` Vinod Koul
2021-06-02 11:01           ` Vinod Koul
2021-06-03 23:40           ` abhinavk
2021-06-03 23:40             ` abhinavk
2021-06-17  8:06             ` Vinod Koul
2021-06-17  8:06               ` Vinod Koul
2021-06-04  2:36           ` Rob Clark
2021-06-04  2:36             ` Rob Clark
2021-06-02 10:56       ` Vinod Koul
2021-06-02 10:56         ` Vinod Koul

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.