* [PATCH v5 0/2] Add support for DSC and FEC for cadence MHDP8546 bridge
@ 2025-09-15 10:30 Harikrishna Shenoy
2025-09-15 10:30 ` [PATCH v5 1/2] dt-bindings: drm/bridge: MHDP8546 bridge binding changes for DSC Harikrishna Shenoy
2025-09-15 10:30 ` [PATCH v5 2/2] drm: bridge: cdns-mhdp8546: Add support for DSC and FEC Harikrishna Shenoy
0 siblings, 2 replies; 9+ messages in thread
From: Harikrishna Shenoy @ 2025-09-15 10:30 UTC (permalink / raw)
To: andrzej.hajda, neil.armstrong, rfoss, Laurent.pinchart, jonas,
jernej.skrabec, airlied, simona, maarten.lankhorst, mripard,
tzimmermann, robh, krzk+dt, conor+dt, sjakhade, yamonkar, lumag,
dianders, jani.nikula, luca.ceresoli, andy.yan, dri-devel,
devicetree, linux-kernel, devarsht, u-kumar1, s-jain1,
tomi.valkeinen
Cc: h-shenoy
Hi all,
This patch series extends the Cadence MHDP8546 DisplayPort bridge
driver to support Display Stream Compression (DSC) and Forward Error
Correction (FEC).
DSC acts as an encoder block: when the sink reports DSC capability,
the DPI input stream to the MHDP8546 TX is compressed, and the sink
decodes the stream for display.
The first patch updates the DT binding to add register-space for DSC.
The second patch implements the corresponding driver changes to enable
DSC and FEC when advertised by the sink and configured via DT.
Link: https://www.ti.com/lit/zip/spruil1
TRM File: SPRUIL_DRA829_TDA4VM_Technical Reference Manual.pdf
(Figure 12-1115 and DSC related sections)
Changelog v4 -> v5:
-Defining reg-names item list in iF conditional, added
description for reg-names.
-Verified the bindings with cdns,mhdp8546 compatible.
-Add code for enabling DSC in bridge driver.
Log link-
<https://gist.github.com/h-shenoy/0318e2c6e7df539e6bdd39b77e5a8f05>
Link to v4:
<https://lore.kernel.org/all/20250909054622.1439487-1-h-shenoy@ti.com>
Swapnil Jakhade (2):
dt-bindings: drm/bridge: MHDP8546 bridge binding changes for DSC
drm: bridge: cdns-mhdp8546: Add support for DSC and FEC
.../display/bridge/cdns,mhdp8546.yaml | 24 +-
drivers/gpu/drm/bridge/cadence/Makefile | 2 +-
.../drm/bridge/cadence/cdns-mhdp8546-core.c | 367 ++++++++-
.../drm/bridge/cadence/cdns-mhdp8546-core.h | 68 ++
.../drm/bridge/cadence/cdns-mhdp8546-dsc.c | 695 ++++++++++++++++++
.../drm/bridge/cadence/cdns-mhdp8546-dsc.h | 285 +++++++
6 files changed, 1406 insertions(+), 35 deletions(-)
create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.c
create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.h
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v5 1/2] dt-bindings: drm/bridge: MHDP8546 bridge binding changes for DSC
2025-09-15 10:30 [PATCH v5 0/2] Add support for DSC and FEC for cadence MHDP8546 bridge Harikrishna Shenoy
@ 2025-09-15 10:30 ` Harikrishna Shenoy
2025-09-18 1:30 ` Krzysztof Kozlowski
2025-09-15 10:30 ` [PATCH v5 2/2] drm: bridge: cdns-mhdp8546: Add support for DSC and FEC Harikrishna Shenoy
1 sibling, 1 reply; 9+ messages in thread
From: Harikrishna Shenoy @ 2025-09-15 10:30 UTC (permalink / raw)
To: andrzej.hajda, neil.armstrong, rfoss, Laurent.pinchart, jonas,
jernej.skrabec, airlied, simona, maarten.lankhorst, mripard,
tzimmermann, robh, krzk+dt, conor+dt, sjakhade, yamonkar, lumag,
dianders, jani.nikula, luca.ceresoli, andy.yan, dri-devel,
devicetree, linux-kernel, devarsht, u-kumar1, s-jain1,
tomi.valkeinen
Cc: h-shenoy
From: Swapnil Jakhade <sjakhade@cadence.com>
Add binding changes for DSC(Display Stream Compression) in the MHDP8546
DPI/DP bridge.
Signed-off-by: Swapnil Jakhade <sjakhade@cadence.com>
Signed-off-by: Harikrishna Shenoy <h-shenoy@ti.com>
---
.../display/bridge/cdns,mhdp8546.yaml | 24 ++++++++++++-------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8546.yaml b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8546.yaml
index c2b369456e4e..2a05a7d5847f 100644
--- a/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8546.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8546.yaml
@@ -27,13 +27,12 @@ properties:
Register block for DSS_EDP0_INTG_CFG_VP registers in case of TI J7 SoCs.
- description:
Register block of mhdptx sapb registers.
+ - description:
+ Register block for mhdptx DSC encoder registers.
reg-names:
- minItems: 1
- items:
- - const: mhdptx
- - const: j721e-intg
- - const: mhdptx-sapb
+ description:
+ Names corresponding to entries in the reg property.
clocks:
maxItems: 1
@@ -100,18 +99,25 @@ allOf:
properties:
reg:
minItems: 2
- maxItems: 3
+ maxItems: 4
reg-names:
minItems: 2
- maxItems: 3
+ items:
+ - const: mhdptx
+ - const: j721e-intg
+ - const: mhdptx-sapb
+ - const: dsc
else:
properties:
reg:
minItems: 1
- maxItems: 2
+ maxItems: 3
reg-names:
minItems: 1
- maxItems: 2
+ items:
+ - const: mhdptx
+ - const: mhdptx-sapb
+ - const: dsc
required:
- compatible
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v5 2/2] drm: bridge: cdns-mhdp8546: Add support for DSC and FEC
2025-09-15 10:30 [PATCH v5 0/2] Add support for DSC and FEC for cadence MHDP8546 bridge Harikrishna Shenoy
2025-09-15 10:30 ` [PATCH v5 1/2] dt-bindings: drm/bridge: MHDP8546 bridge binding changes for DSC Harikrishna Shenoy
@ 2025-09-15 10:30 ` Harikrishna Shenoy
2025-09-15 11:06 ` Dmitry Baryshkov
2025-09-19 19:38 ` kernel test robot
1 sibling, 2 replies; 9+ messages in thread
From: Harikrishna Shenoy @ 2025-09-15 10:30 UTC (permalink / raw)
To: andrzej.hajda, neil.armstrong, rfoss, Laurent.pinchart, jonas,
jernej.skrabec, airlied, simona, maarten.lankhorst, mripard,
tzimmermann, robh, krzk+dt, conor+dt, sjakhade, yamonkar, lumag,
dianders, jani.nikula, luca.ceresoli, andy.yan, dri-devel,
devicetree, linux-kernel, devarsht, u-kumar1, s-jain1,
tomi.valkeinen
Cc: h-shenoy
From: Swapnil Jakhade <sjakhade@cadence.com>
Enable support for Display Stream Compression (DSC) in independent
mode with a single stream, along with Forward Error Correction (FEC)
in the Cadence MHDP8546 DisplayPort controller driver.
FEC is required when DSC is enabled to ensure reliable transmission
of the compressed stream.
Signed-off-by: Swapnil Jakhade <sjakhade@cadence.com>
Signed-off-by: Harikrishna Shenoy <h-shenoy@ti.com>
---
drivers/gpu/drm/bridge/cadence/Makefile | 2 +-
.../drm/bridge/cadence/cdns-mhdp8546-core.c | 367 ++++++++-
.../drm/bridge/cadence/cdns-mhdp8546-core.h | 68 ++
.../drm/bridge/cadence/cdns-mhdp8546-dsc.c | 695 ++++++++++++++++++
.../drm/bridge/cadence/cdns-mhdp8546-dsc.h | 285 +++++++
5 files changed, 1392 insertions(+), 25 deletions(-)
create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.c
create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.h
diff --git a/drivers/gpu/drm/bridge/cadence/Makefile b/drivers/gpu/drm/bridge/cadence/Makefile
index c95fd5b81d13..7957fbdc1b78 100644
--- a/drivers/gpu/drm/bridge/cadence/Makefile
+++ b/drivers/gpu/drm/bridge/cadence/Makefile
@@ -3,5 +3,5 @@ obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o
cdns-dsi-y := cdns-dsi-core.o
cdns-dsi-$(CONFIG_DRM_CDNS_DSI_J721E) += cdns-dsi-j721e.o
obj-$(CONFIG_DRM_CDNS_MHDP8546) += cdns-mhdp8546.o
-cdns-mhdp8546-y := cdns-mhdp8546-core.o cdns-mhdp8546-hdcp.o
+cdns-mhdp8546-y := cdns-mhdp8546-core.o cdns-mhdp8546-hdcp.o cdns-mhdp8546-dsc.o
cdns-mhdp8546-$(CONFIG_DRM_CDNS_MHDP8546_J721E) += cdns-mhdp8546-j721e.o
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
index a614d1384f71..df8bbf8919b2 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
@@ -50,6 +50,7 @@
#include <linux/unaligned.h>
#include "cdns-mhdp8546-core.h"
+#include "cdns-mhdp8546-dsc.h"
#include "cdns-mhdp8546-hdcp.h"
#include "cdns-mhdp8546-j721e.h"
@@ -545,6 +546,116 @@ int cdns_mhdp_adjust_lt(struct cdns_mhdp_device *mhdp, unsigned int nlanes,
return ret;
}
+static int cdns_mhdp_wait_for_fec(struct cdns_mhdp_device *mhdp,
+ bool expected_status)
+{
+ u32 fec_status;
+ unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+
+ cdns_mhdp_reg_read(mhdp, CDNS_DP_FEC_STATUS, &fec_status);
+ while (((fec_status & CDNS_DP_FEC_BUSY) != expected_status) &&
+ time_before(jiffies, timeout)) {
+ cdns_mhdp_reg_read(mhdp, CDNS_DP_FEC_STATUS, &fec_status);
+ cpu_relax();
+ }
+
+ if (time_after_eq(jiffies, timeout)) {
+ DRM_DEV_ERROR(mhdp->dev, "Timeout while waiting for FEC\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int cdns_mhdp_fec_sink_support(struct cdns_mhdp_device *mhdp)
+{
+ int ret;
+ u16 dpcd_buffer;
+
+ ret = drm_dp_dpcd_read(&mhdp->aux, DP_FEC_CAPABILITY, &dpcd_buffer, 1);
+ if (ret < 0)
+ goto err;
+
+ if (!(dpcd_buffer & DP_FEC_CAPABLE)) {
+ ret = -EOPNOTSUPP;
+ DRM_DEV_ERROR(mhdp->dev, "sink does not support FEC: %d\n", ret);
+ goto err;
+ }
+
+ if (ret > 0)
+ return 0;
+err:
+ return ret;
+}
+
+static int cdns_mhdp_fec_sink_set_ready(struct cdns_mhdp_device *mhdp,
+ bool enable)
+{
+ int ret;
+ u8 dpcd_buffer;
+
+ ret = drm_dp_dpcd_read(&mhdp->aux, DP_FEC_CONFIGURATION, &dpcd_buffer, 1);
+ if (ret < 0)
+ goto err;
+
+ if (enable)
+ dpcd_buffer |= DP_FEC_READY;
+ else
+ dpcd_buffer &= ~DP_FEC_READY;
+
+ ret = drm_dp_dpcd_write(&mhdp->aux, DP_FEC_CONFIGURATION, &dpcd_buffer, 1);
+
+ if (ret > 0)
+ return 0;
+err:
+ DRM_DEV_ERROR(mhdp->dev, "cannot set sink FEC ready: %d\n", ret);
+ return ret;
+}
+
+static int cdns_mhdp_fec_set_ready(struct cdns_mhdp_device *mhdp, bool enable)
+{
+ int ret;
+
+ ret = cdns_mhdp_fec_sink_support(mhdp);
+ if (ret)
+ goto err;
+
+ ret = cdns_mhdp_fec_sink_set_ready(mhdp, enable);
+ if (ret)
+ goto err;
+
+ ret = cdns_mhdp_reg_write_bit(mhdp, CDNS_DP_FEC_CTRL, 1, 1, enable);
+ if (ret)
+ goto err;
+
+err:
+ return ret;
+}
+
+static int cdns_mhdp_fec_enable(struct cdns_mhdp_device *mhdp, bool enable)
+{
+ int ret;
+ u32 resp;
+
+ ret = cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &resp);
+ if (ret < 0)
+ goto err;
+
+ if (!(resp & CDNS_DP_NO_VIDEO_MODE)) {
+ ret = -EIO;
+ goto err;
+ }
+
+ ret = cdns_mhdp_reg_write_bit(mhdp, CDNS_DP_FEC_CTRL, 0, 1, enable);
+ if (ret)
+ goto err;
+
+ return cdns_mhdp_wait_for_fec(mhdp, enable);
+err:
+ DRM_DEV_ERROR(mhdp->dev, "set fec enable failed: %d\n", ret);
+ return ret;
+}
+
/**
* cdns_mhdp_link_configure() - configure a DisplayPort link
* @aux: DisplayPort AUX channel
@@ -1407,6 +1518,13 @@ static int cdns_mhdp_link_up(struct cdns_mhdp_device *mhdp)
amp[1] = DP_SET_ANSI_8B10B;
drm_dp_dpcd_write(&mhdp->aux, DP_DOWNSPREAD_CTRL, amp, 2);
+ if (cdns_mhdp_fec_set_ready(mhdp, true)) {
+ mhdp->fec_enabled = false;
+ dev_info(mhdp->dev, "Cannot set FEC ready.\n");
+ } else {
+ mhdp->fec_enabled = true;
+ }
+
if (mhdp->host.fast_link & mhdp->sink.fast_link) {
dev_err(mhdp->dev, "fastlink not supported\n");
return -EOPNOTSUPP;
@@ -1494,10 +1612,14 @@ static int cdns_mhdp_connector_detect(struct drm_connector *conn,
return cdns_mhdp_detect(mhdp);
}
-static u32 cdns_mhdp_get_bpp(struct cdns_mhdp_display_fmt *fmt)
+static u32 cdns_mhdp_get_bpp(struct cdns_mhdp_device *mhdp)
{
+ struct cdns_mhdp_display_fmt *fmt = &mhdp->display_fmt;
u32 bpp;
+ if (mhdp->dsc_params.compression_enable)
+ return mhdp->dsc_params.compressed_bpp;
+
if (fmt->y_only)
return fmt->bpc;
@@ -1533,7 +1655,7 @@ bool cdns_mhdp_bandwidth_ok(struct cdns_mhdp_device *mhdp,
* units of the rate parameter.
*/
- bpp = cdns_mhdp_get_bpp(&mhdp->display_fmt);
+ bpp = cdns_mhdp_get_bpp(mhdp);
req_bw = mode->clock * bpp / 8;
max_bw = lanes * rate;
if (req_bw > max_bw) {
@@ -1693,6 +1815,74 @@ static int cdns_mhdp_attach(struct drm_bridge *bridge,
return ret;
}
+static int cdns_mhdp_dsc_set_stream_compressed(struct cdns_mhdp_device *mhdp,
+ int stream_id, bool compressed)
+{
+ u32 reg_val;
+ int ret;
+
+ ret = cdns_mhdp_reg_read(mhdp, CDNS_DP_VB_ID(stream_id), ®_val);
+ if (ret < 0)
+ return ret;
+
+ if (compressed)
+ reg_val |= CDNS_DP_VB_ID_COMPRESSED;
+ else
+ reg_val &= ~CDNS_DP_VB_ID_COMPRESSED;
+
+ return cdns_mhdp_reg_write(mhdp, CDNS_DP_VB_ID(stream_id), reg_val);
+}
+
+static int cdns_mhdp_dsc_wait_for_completion(struct cdns_mhdp_device *mhdp,
+ u8 event_bit, int stream_id)
+{
+ u32 dsc_ctrl;
+ int ret;
+ unsigned long timeout;
+
+ ret = cdns_mhdp_reg_write_bit(mhdp, CDNS_DP_DSC_CTRL(stream_id),
+ event_bit, 1, true);
+ if (ret)
+ return ret;
+
+ timeout = jiffies + msecs_to_jiffies(1000);
+
+ do {
+ cdns_mhdp_reg_read(mhdp, CDNS_DP_DSC_CTRL(stream_id), &dsc_ctrl);
+ cpu_relax();
+ } while (((dsc_ctrl & (1 << event_bit)) != 0) && time_before(jiffies, timeout));
+
+ if (time_after_eq(jiffies, timeout)) {
+ DRM_DEV_ERROR(mhdp->dev, "Timeout while waiting for event %d\n", event_bit);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int cdns_mhdp_dsc_reset(struct cdns_mhdp_device *mhdp)
+{
+ /* Setting reset bit in any stream resets entire DSC. Stream 0 may always be used for it. */
+ return cdns_mhdp_dsc_wait_for_completion(mhdp, CDNS_DP_DSC_CTRL_SW_RST_BIT, 0);
+}
+
+static int cdns_mhdp_dsc_update(struct cdns_mhdp_device *mhdp, int stream_id)
+{
+ return cdns_mhdp_dsc_wait_for_completion(mhdp, CDNS_DP_DSC_CTRL_REG_UPDATE_BIT,
+ stream_id);
+}
+
+static int cdns_mhdp_dsc_enable(struct cdns_mhdp_device *mhdp, int stream_id, bool enable)
+{
+ return cdns_mhdp_reg_write_bit(mhdp, CDNS_DP_DSC_CTRL(stream_id),
+ CDNS_DP_DSC_CTRL_EN_BIT, 1, enable ? 1 : 0);
+}
+
+static int cdns_mhdp_dsc_sink_enable(struct cdns_mhdp_device *mhdp, bool enable)
+{
+ return drm_dp_dpcd_writeb(&mhdp->aux, DP_DSC_ENABLE, enable) != 1;
+}
+
static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
const struct drm_display_mode *mode)
{
@@ -1702,7 +1892,7 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
front_porch, back_porch, msa_h0, msa_v0, hsync, vsync,
dp_vertical_1;
u8 stream_id = mhdp->stream_id;
- u32 bpp, bpc, pxlfmt, framer;
+ u32 bpp, bpc, pxlfmt, framer, dp_byte_count;
int ret;
pxlfmt = mhdp->display_fmt.color_format;
@@ -1716,7 +1906,7 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
pxlfmt == DRM_COLOR_FORMAT_YCBCR422) && mode->crtc_vdisplay >= 720)
misc0 = DP_YCBCR_COEFFICIENTS_ITU709;
- bpp = cdns_mhdp_get_bpp(&mhdp->display_fmt);
+ bpp = cdns_mhdp_get_bpp(mhdp);
switch (pxlfmt) {
case DRM_COLOR_FORMAT_RGB444:
@@ -1765,6 +1955,9 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
bnd_hsync2vsync |= CDNS_IP_DET_INTERLACE_FORMAT;
+ if (mhdp->dsc_params.compression_enable)
+ bnd_hsync2vsync |= CDNS_IP_VIF_ALIGNMENT_LSB;
+
cdns_mhdp_reg_write(mhdp, CDNS_BND_HSYNC2VSYNC(stream_id),
bnd_hsync2vsync);
@@ -1792,8 +1985,14 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
CDNS_DP_FRONT_PORCH(front_porch) |
CDNS_DP_BACK_PORCH(back_porch));
- cdns_mhdp_reg_write(mhdp, CDNS_DP_BYTE_COUNT(stream_id),
- mode->crtc_hdisplay * bpp / 8);
+ if (mhdp->dsc_params.compression_enable) {
+ dp_byte_count = (((mhdp->dsc_config.slice_chunk_size / mhdp->link.num_lanes) + 1) <<
+ CDNS_DP_BYTE_COUNT_BYTES_IN_CHUNK_SHIFT) |
+ ((mhdp->dsc_config.slice_chunk_size / mhdp->link.num_lanes) + 1);
+ } else {
+ dp_byte_count = (mode->crtc_hdisplay * bpp / 8);
+ }
+ cdns_mhdp_reg_write(mhdp, CDNS_DP_BYTE_COUNT(stream_id), dp_byte_count);
msa_h0 = mode->crtc_htotal - mode->crtc_hsync_start;
cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_HORIZONTAL_0(stream_id),
@@ -1852,6 +2051,9 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
(mode->flags & DRM_MODE_FLAG_INTERLACE) ?
CDNS_DP_VB_ID_INTERLACED : 0);
+ if (mhdp->dsc_params.compression_enable)
+ cdns_mhdp_dsc_set_stream_compressed(mhdp, stream_id, true);
+
ret = cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &framer);
if (ret < 0) {
dev_err(mhdp->dev,
@@ -1860,7 +2062,6 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
return;
}
framer |= CDNS_DP_FRAMER_EN;
- framer &= ~CDNS_DP_NO_VIDEO_MODE;
cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, framer);
}
@@ -1869,20 +2070,67 @@ static void cdns_mhdp_sst_enable(struct cdns_mhdp_device *mhdp,
{
u32 rate, vs, required_bandwidth, available_bandwidth;
s32 line_thresh1, line_thresh2, line_thresh = 0;
- int pxlclock = mode->crtc_clock;
+ int ret, pxlclock = mode->crtc_clock;
+ u32 vs_f, framer, pxl_repr;
u32 tu_size = 64;
u32 bpp;
/* Get rate in MSymbols per second per lane */
rate = mhdp->link.rate / 1000;
- bpp = cdns_mhdp_get_bpp(&mhdp->display_fmt);
+ if (mhdp->fec_enabled) {
+ if (cdns_mhdp_fec_enable(mhdp, true))
+ mhdp->fec_enabled = false;
+ } else {
+ cdns_mhdp_fec_enable(mhdp, false);
+ }
+
+ if (mhdp->dsc_supported && !cdns_mhdp_dsc_sink_support(mhdp)) {
+ ret = cdns_mhdp_dsc_reset(mhdp);
+ if (ret)
+ dev_err(mhdp->dev, "DSC reset failed. ret = %d\n", ret);
+
+ mhdp->dsc_params.compressed_bpp = 8;
+ mhdp->dsc_params.slice_count = 10;
+
+ ret = cdns_mhdp_compute_dsc_params(mhdp);
+ if (ret < 0) {
+ mhdp->dsc_params.compression_enable = false;
+ dev_err(mhdp->dev, "DSC params computation failed. ret = %d\n", ret);
+ } else {
+ mhdp->dsc_params.compression_enable = true;
+ /* Write config for stream 0 */
+ cdns_mhdp_dsc_write_enc_config(mhdp, 0, mode);
+ cdns_mhdp_dsc_update(mhdp, 0);
+ cdns_mhdp_dsc_write_config(mhdp);
+ }
+ } else {
+ if (mhdp->dsc_params.compression_enable) {
+ cdns_mhdp_dsc_sink_enable(mhdp, false);
+ cdns_mhdp_dsc_set_stream_compressed(mhdp, 0, false);
+ }
+ mhdp->dsc_params.compression_enable = false;
+ }
+
+ /* Enable DSC for stream 0 */
+ if (mhdp->dsc_params.compression_enable) {
+ cdns_mhdp_dsc_enable(mhdp, 0, true);
+
+ if (cdns_mhdp_dsc_sink_enable(mhdp, true))
+ dev_err(mhdp->dev, "Cannot enable DSC in sink.\n");
+ cdns_mhdp_dsc_send_pps_sdp(mhdp, 0);
+ }
+
+ bpp = cdns_mhdp_get_bpp(mhdp);
required_bandwidth = pxlclock * bpp / 8;
available_bandwidth = mhdp->link.num_lanes * rate;
- vs = tu_size * required_bandwidth / available_bandwidth;
- vs /= 1000;
+ vs_f = tu_size * required_bandwidth / available_bandwidth;
+ if (mhdp->fec_enabled)
+ vs_f = (vs_f * 1024) / 1000; //2.4%
+ vs = vs_f / 1000;
+ vs_f = vs_f % 1000;
if (vs == tu_size)
vs = tu_size - 1;
@@ -1907,6 +2155,70 @@ static void cdns_mhdp_sst_enable(struct cdns_mhdp_device *mhdp,
0 : tu_size - vs));
cdns_mhdp_configure_video(mhdp, mode);
+
+ if (mhdp->dsc_params.compression_enable) {
+ cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_PXL_REPR(0), &pxl_repr);
+ pxl_repr &= ~CDNS_DP_FRAMER_PXL_REPR_M;
+ pxl_repr &= ~CDNS_DP_FRAMER_PXL_REPR_DIFF;
+ pxl_repr |= (((vs_f / 10) << CDNS_DP_FRAMER_PXL_REPR_M_SHIFT)
+ & CDNS_DP_FRAMER_PXL_REPR_M) |
+ (((100 - (vs_f / 10)) << CDNS_DP_FRAMER_PXL_REPR_DIFF_SHIFT)
+ & CDNS_DP_FRAMER_PXL_REPR_DIFF);
+ cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_PXL_REPR(0), pxl_repr);
+ }
+
+ /* Enable video mode */
+ cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &framer);
+ framer &= ~CDNS_DP_NO_VIDEO_MODE;
+ cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, framer);
+}
+
+static int cdns_mhdp_configure_car(struct cdns_mhdp_device *mhdp, bool enable)
+{
+ u32 dptx_car, source_pkt_car;
+ int ret;
+
+ ret = cdns_mhdp_reg_read(mhdp, CDNS_DPTX_CAR, &dptx_car);
+ if (ret < 0) {
+ dev_err(mhdp->dev, "Failed to read CDNS_DPTX_CAR %d\n", ret);
+ goto out;
+ }
+
+ ret = cdns_mhdp_reg_read(mhdp, CDNS_SOURCE_PKT_CAR, &source_pkt_car);
+ if (ret < 0) {
+ dev_err(mhdp->dev, "Failed to read CDNS_SOURCE_PKT_CAR %d\n", ret);
+ goto out;
+ }
+
+ if (enable) {
+ dev_dbg(mhdp->dev, "%s: Enable clocks for VIF and PIF\n", __func__);
+
+ /* Enable VIF clock for stream 0 */
+ cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR,
+ dptx_car | CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN);
+
+ /* Enable PKT clock */
+ cdns_mhdp_reg_write(mhdp, CDNS_SOURCE_PKT_CAR,
+ source_pkt_car | CDNS_PKT_DATA_CLK_EN
+ | CDNS_PKT_DATA_RSTN
+ | CDNS_PKT_SYS_CLK_EN
+ | CDNS_PKT_SYS_RSTN);
+ } else {
+ dev_dbg(mhdp->dev, "%s: Disable clocks for VIF and PIF\n", __func__);
+
+ /* Disable VIF clock for stream 0 */
+ cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR,
+ dptx_car & ~(CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN));
+
+ /* Disable PKT clock */
+ cdns_mhdp_reg_write(mhdp, CDNS_SOURCE_PKT_CAR,
+ source_pkt_car & ~(CDNS_PKT_DATA_CLK_EN
+ | CDNS_PKT_DATA_RSTN
+ | CDNS_PKT_SYS_CLK_EN
+ | CDNS_PKT_SYS_RSTN));
+ }
+out:
+ return ret;
}
static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge,
@@ -1919,8 +2231,7 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge,
struct drm_connector_state *conn_state;
struct drm_bridge_state *new_state;
const struct drm_display_mode *mode;
- u32 resp;
- int ret;
+ int ret = 0;
dev_dbg(mhdp->dev, "bridge enable\n");
@@ -1935,16 +2246,13 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge,
if (mhdp->info && mhdp->info->ops && mhdp->info->ops->enable)
mhdp->info->ops->enable(mhdp);
- /* Enable VIF clock for stream 0 */
- ret = cdns_mhdp_reg_read(mhdp, CDNS_DPTX_CAR, &resp);
+ /* Enable clocks for video and packet interfaces */
+ ret = cdns_mhdp_configure_car(mhdp, true);
if (ret < 0) {
- dev_err(mhdp->dev, "Failed to read CDNS_DPTX_CAR %d\n", ret);
+ dev_err(mhdp->dev, "Failed to enable clocks %d\n", ret);
goto out;
}
- cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR,
- resp | CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN);
-
connector = drm_atomic_get_new_connector_for_encoder(state,
bridge->encoder);
if (WARN_ON(!connector))
@@ -2020,10 +2328,8 @@ static void cdns_mhdp_atomic_disable(struct drm_bridge *bridge,
cdns_mhdp_link_down(mhdp);
- /* Disable VIF clock for stream 0 */
- cdns_mhdp_reg_read(mhdp, CDNS_DPTX_CAR, &resp);
- cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR,
- resp & ~(CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN));
+ /* Disable clocks for video and packet interfaces */
+ cdns_mhdp_configure_car(mhdp, false);
if (mhdp->info && mhdp->info->ops && mhdp->info->ops->disable)
mhdp->info->ops->disable(mhdp);
@@ -2119,7 +2425,7 @@ static int cdns_mhdp_atomic_check(struct drm_bridge *bridge,
struct drm_connector_state *conn_state)
{
struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge);
- const struct drm_display_mode *mode = &crtc_state->adjusted_mode;
+ struct drm_display_mode *mode = &crtc_state->adjusted_mode;
mutex_lock(&mhdp->link_mutex);
@@ -2139,6 +2445,10 @@ static int cdns_mhdp_atomic_check(struct drm_bridge *bridge,
if (mhdp->info)
bridge_state->input_bus_cfg.flags = *mhdp->info->input_bus_flags;
+ //TODO For DSC. Might need proper handling. 1920x1080 mode doesn't work without this.
+ mode->flags |= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
+ mode->flags &= ~(DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC);
+
mutex_unlock(&mhdp->link_mutex);
return 0;
}
@@ -2426,6 +2736,15 @@ static int cdns_mhdp_probe(struct platform_device *pdev)
mhdp->hdcp_supported = true;
}
+ mhdp->dsc_regs = devm_platform_ioremap_resource_byname(pdev, "dsc");
+ if (IS_ERR(mhdp->dsc_regs)) {
+ mhdp->dsc_supported = false;
+ dev_info(dev,
+ "Failed to get DSC memory resource, DSC not supported\n");
+ } else {
+ mhdp->dsc_supported = true;
+ }
+
mhdp->phy = devm_of_phy_get_by_index(dev, pdev->dev.of_node, 0);
if (IS_ERR(mhdp->phy)) {
dev_err(dev, "no PHY configured\n");
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
index bad2fc0c7306..c8f8071776d7 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
@@ -16,6 +16,7 @@
#include <linux/spinlock.h>
#include <drm/display/drm_dp_helper.h>
+#include <drm/display/drm_dsc.h>
#include <drm/drm_bridge.h>
#include <drm/drm_connector.h>
@@ -66,18 +67,30 @@ struct phy;
#define CDNS_VIF_CLK_EN BIT(0)
#define CDNS_VIF_CLK_RSTN BIT(1)
+#define CDNS_SOURCE_PKT_CAR 0x00918
+#define CDNS_PKT_DATA_CLK_EN BIT(0)
+#define CDNS_PKT_DATA_RSTN BIT(1)
+#define CDNS_PKT_SYS_CLK_EN BIT(2)
+#define CDNS_PKT_SYS_RSTN BIT(3)
+
#define CDNS_SOURCE_VIDEO_IF(s) (0x00b00 + ((s) * 0x20))
#define CDNS_BND_HSYNC2VSYNC(s) (CDNS_SOURCE_VIDEO_IF(s) + \
0x00)
#define CDNS_IP_DTCT_WIN GENMASK(11, 0)
#define CDNS_IP_DET_INTERLACE_FORMAT BIT(12)
#define CDNS_IP_BYPASS_V_INTERFACE BIT(13)
+#define CDNS_IP_VIF_ALIGNMENT_LSB BIT(14)
#define CDNS_HSYNC2VSYNC_POL_CTRL(s) (CDNS_SOURCE_VIDEO_IF(s) + \
0x10)
#define CDNS_H2V_HSYNC_POL_ACTIVE_LOW BIT(1)
#define CDNS_H2V_VSYNC_POL_ACTIVE_LOW BIT(2)
+#define CDNS_DP_DSC_CTRL(s) (CDNS_SOURCE_VIDEO_IF(s) + 0x14)
+#define CDNS_DP_DSC_CTRL_EN_BIT 0
+#define CDNS_DP_DSC_CTRL_SW_RST_BIT 1
+#define CDNS_DP_DSC_CTRL_REG_UPDATE_BIT 2
+
#define CDNS_DPTX_PHY_CONFIG 0x02000
#define CDNS_PHY_TRAINING_EN BIT(0)
#define CDNS_PHY_TRAINING_TYPE(x) (((x) & GENMASK(3, 0)) << 1)
@@ -121,6 +134,10 @@ struct phy;
#define CDNS_DP_ENHNCD 0x02304
+#define CDNS_DP_FEC_CTRL 0x02310
+#define CDNS_DP_FEC_STATUS 0x02314
+#define CDNS_DP_FEC_BUSY BIT(0)
+
#define CDNS_DPTX_STREAM(s) (0x03000 + (s) * 0x80)
#define CDNS_DP_MSA_HORIZONTAL_0(s) (CDNS_DPTX_STREAM(s) + 0x00)
#define CDNS_DP_MSAH0_H_TOTAL(x) (x)
@@ -178,6 +195,10 @@ struct phy;
#define CDNS_DP_FRAMER_YCBCR422 BIT(2)
#define CDNS_DP_FRAMER_YCBCR420 BIT(3)
#define CDNS_DP_FRAMER_Y_ONLY BIT(4)
+#define CDNS_DP_FRAMER_PXL_REPR_M GENMASK(22, 16)
+#define CDNS_DP_FRAMER_PXL_REPR_DIFF GENMASK(30, 24)
+#define CDNS_DP_FRAMER_PXL_REPR_M_SHIFT 16
+#define CDNS_DP_FRAMER_PXL_REPR_DIFF_SHIFT 24
#define CDNS_DP_FRAMER_SP(s) (CDNS_DPTX_STREAM(s) + 0x50)
#define CDNS_DP_FRAMER_VSYNC_POL_LOW BIT(0)
@@ -198,6 +219,38 @@ struct phy;
#define CDNS_DP_BYTE_COUNT(s) (CDNS_DPTX_STREAM(s) + 0x7c)
#define CDNS_DP_BYTE_COUNT_BYTES_IN_CHUNK_SHIFT 16
+#define CDNS_SOURCE_PACKET_IF(s) (0x30800 + ((s) * 0x40))
+#define CDNS_SOURCE_PIF_WR_ADDR(s) (CDNS_SOURCE_PACKET_IF(s) + 0x00)
+
+#define CDNS_SOURCE_PIF_WR_REQ(s) (CDNS_SOURCE_PACKET_IF(s) + 0x04)
+#define SOURCE_PIF_WR_REQ_HOST_WR BIT(0)
+
+#define CDNS_SOURCE_PIF_RD_ADDR(s) (CDNS_SOURCE_PACKET_IF(s) + 0x08)
+#define CDNS_SOURCE_PIF_RD_REQ(s) (CDNS_SOURCE_PACKET_IF(s) + 0x0c)
+#define CDNS_SOURCE_PIF_DATA_WR(s) (CDNS_SOURCE_PACKET_IF(s) + 0x10)
+#define CDNS_SOURCE_PIF_DATA_RD(s) (CDNS_SOURCE_PACKET_IF(s) + 0x14)
+#define CDNS_SOURCE_PIF_FIFO1_FLUSH(s) (CDNS_SOURCE_PACKET_IF(s) + 0x18)
+#define CDNS_SOURCE_PIF_FIFO2_FLUSH(s) (CDNS_SOURCE_PACKET_IF(s) + 0x1c)
+#define CDNS_SOURCE_PIF_STATUS(s) (CDNS_SOURCE_PACKET_IF(s) + 0x20)
+#define CDNS_SOURCE_PIF_INT_SOURCE(s) (CDNS_SOURCE_PACKET_IF(s) + 0x24)
+#define CDNS_SOURCE_PIF_INT_MASK(s) (CDNS_SOURCE_PACKET_IF(s) + 0x28)
+
+#define CDNS_SOURCE_PIF_PKT_ALLOC_REG(s) (CDNS_SOURCE_PACKET_IF(s) + 0x2c)
+#define SOURCE_PIF_PKT_ALLOC_REG_ACTIVE_IDLE_TYPE BIT(17)
+#define SOURCE_PIF_PKT_ALLOC_REG_TYPE_VALID BIT(16)
+#define SOURCE_PIF_PKT_ALLOC_REG_PACKET_TYPE GENMASK(15, 8)
+#define SOURCE_PIF_PKT_ALLOC_REG_PACKET_TYPE_SHIFT 8
+#define SOURCE_PIF_PKT_ALLOC_REG_PKT_ALLOC_ADDR GENMASK(3, 0)
+
+#define CDNS_SOURCE_PIF_PKT_ALLOC_WR_EN(s) (CDNS_SOURCE_PACKET_IF(s) + 0x30)
+#define SOURCE_PIF_PKT_ALLOC_WR_EN_EN BIT(0)
+
+#define CDNS_SOURCE_PIF_SW_RST(s) (CDNS_SOURCE_PACKET_IF(s) + 0x34)
+#define CDNS_SOURCE_PIF_PPS_HEADER(s) (CDNS_SOURCE_PACKET_IF(s) + 0x38)
+
+#define CDNS_SOURCE_PIF_PPS(s) (CDNS_SOURCE_PACKET_IF(s) + 0x3c)
+#define SOURCE_PIF_PPS_PPS BIT(0)
+
/* mailbox */
#define MAILBOX_RETRY_US 1000
#define MAILBOX_TIMEOUT_US 2000000
@@ -354,6 +407,7 @@ struct cdns_mhdp_hdcp {
struct cdns_mhdp_device {
void __iomem *regs;
void __iomem *sapb_regs;
+ void __iomem *dsc_regs;
void __iomem *j721e_regs;
struct device *dev;
@@ -412,6 +466,20 @@ struct cdns_mhdp_device {
struct cdns_mhdp_hdcp hdcp;
bool hdcp_supported;
+
+ struct drm_dsc_config dsc_config;
+
+ /* Display Stream Compression state */
+ bool dsc_supported;
+ struct {
+ bool compression_enable;
+ bool dsc_split;
+ u16 compressed_bpp;
+ u8 slice_count;
+ u8 dsc_cap[DP_DSC_RECEIVER_CAP_SIZE];
+ } dsc_params;
+
+ bool fec_enabled;
};
#define connector_to_mhdp(x) container_of(x, struct cdns_mhdp_device, connector)
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.c
new file mode 100644
index 000000000000..e540e8f2dd4a
--- /dev/null
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.c
@@ -0,0 +1,695 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Cadence Design Systems, Inc.
+ *
+ * Author: Swapnil Jakhade <sjakhade@cadence.com>
+ */
+
+#include "cdns-mhdp8546-core.h"
+#include "cdns-mhdp8546-dsc.h"
+
+void cdns_mhdp_dsc_write_config(struct cdns_mhdp_device *mhdp)
+{
+ u32 main_conf = 0;
+
+ main_conf = CDNS_DP_COM_MAIN_CONF_INPUT_MODE |
+ CDNS_DP_COM_MAIN_CONF_AUTO_DB_UPDATE;
+
+ if (mhdp->dsc_params.dsc_split) {
+ main_conf |= CDNS_DP_COM_MAIN_CONF_MUX_MODE |
+ CDNS_DP_COM_MAIN_CONF_SPLIT_PANEL;
+ }
+
+ writel(main_conf, mhdp->dsc_regs + CDNS_DP_COM_MAIN_CONF);
+}
+
+static u8 cdns_mhdp_dsc_compute_initial_lines(struct cdns_mhdp_device *mhdp)
+{
+ struct drm_dsc_config *dsc_cfg = &mhdp->dsc_config;
+ unsigned long k1, real_bpp;
+ u8 initial_lines;
+
+ real_bpp = (unsigned long)dsc_cfg->bits_per_pixel / 16;
+
+ if (dsc_cfg->bits_per_component == 8)
+ k1 = 296;
+ else
+ k1 = 320;
+
+ if (mhdp->dsc_params.dsc_split) {
+ initial_lines = (u8)DIV_ROUND_UP
+ ((k1 + (unsigned long)dsc_cfg->initial_xmit_delay +
+ ((((unsigned long)dsc_cfg->slice_chunk_size * 8) + 144) /
+ real_bpp)), (unsigned long)dsc_cfg->slice_width);
+ } else {
+ initial_lines = (u8)DIV_ROUND_UP
+ ((k1 + (unsigned long)dsc_cfg->initial_xmit_delay +
+ ((DIV_ROUND_UP(((1 - (real_bpp / 48)) *
+ ((unsigned long)dsc_cfg->slice_chunk_size * 8)), 1) + 144) /
+ real_bpp)), (unsigned long)dsc_cfg->slice_width);
+ }
+
+ return initial_lines;
+}
+
+static void write_enc_main_conf(struct cdns_mhdp_device *mhdp, int stream_id)
+{
+ u32 reg_val = 0;
+
+ if (mhdp->dsc_config.convert_rgb)
+ reg_val |= CDNS_DP_ENC_MAIN_CONF_CONVERT_RGB;
+
+ reg_val |= (mhdp->dsc_config.line_buf_depth <<
+ CDNS_DP_ENC_MAIN_CONF_LINEBUF_DEPTH_SHIFT) &
+ CDNS_DP_ENC_MAIN_CONF_LINEBUF_DEPTH;
+
+ reg_val |= (mhdp->dsc_config.bits_per_pixel <<
+ CDNS_DP_ENC_MAIN_CONF_BITS_PER_PIXEL_SHIFT) &
+ CDNS_DP_ENC_MAIN_CONF_BITS_PER_PIXEL;
+
+ if (mhdp->dsc_config.block_pred_enable)
+ reg_val |= CDNS_DP_ENC_MAIN_CONF_BLOCK_PRED_EN;
+
+ reg_val |= CDNS_DP_ENC_MAIN_CONF_VIDEO_MODE;
+
+ reg_val |= (cdns_mhdp_dsc_compute_initial_lines(mhdp) <<
+ CDNS_DP_ENC_MAIN_CONF_INITIAL_LINES_SHIFT) &
+ CDNS_DP_ENC_MAIN_CONF_INITIAL_LINES;
+
+ if (mhdp->dsc_config.bits_per_component == 10)
+ reg_val |= 0x1;
+ else if (mhdp->dsc_config.bits_per_component != 8)
+ dev_err(mhdp->dev, "Unsupported bits_per_component = %d\n",
+ mhdp->dsc_config.bits_per_component);
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_MAIN_CONF(stream_id));
+}
+
+static void write_enc_picture_size(struct cdns_mhdp_device *mhdp, int stream_id)
+{
+ u32 reg_val = 0;
+
+ reg_val = (mhdp->dsc_config.pic_width &
+ CDNS_DP_ENC_PICTURE_SIZE_WIDTH);
+
+ reg_val |= (mhdp->dsc_config.pic_height <<
+ CDNS_DP_ENC_PICTURE_SIZE_HEIGHT_SHIFT) &
+ CDNS_DP_ENC_PICTURE_SIZE_HEIGHT;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_PICTURE_SIZE(stream_id));
+}
+
+static void write_enc_slice_size(struct cdns_mhdp_device *mhdp, int stream_id)
+{
+ u32 reg_val = 0;
+
+ reg_val = (mhdp->dsc_config.slice_width &
+ CDNS_DP_ENC_SLICE_SIZE_WIDTH);
+
+ reg_val |= (mhdp->dsc_config.slice_height <<
+ CDNS_DP_ENC_SLICE_SIZE_HEIGHT_SHIFT) &
+ CDNS_DP_ENC_SLICE_SIZE_HEIGHT;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_SLICE_SIZE(stream_id));
+}
+
+static void write_enc_misc_size(struct cdns_mhdp_device *mhdp, int stream_id)
+{
+ u32 reg_val = 0;
+
+ reg_val = ((mhdp->dsc_config.slice_width + 2) % 3) &
+ CDNS_DP_ENC_MISC_SIZE_LAST_GRP_SIZE;
+
+ reg_val |= (DSC_OUTPUT_BUFFER_MAX_ADDRESS <<
+ CDNS_DP_ENC_MISC_SIZE_OB_MAX_ADDR_SHIFT) &
+ CDNS_DP_ENC_MISC_SIZE_OB_MAX_ADDR;
+
+ reg_val |= (mhdp->dsc_config.slice_chunk_size <<
+ CDNS_DP_ENC_MISC_SIZE_CHUNK_SIZE_SHIFT) &
+ CDNS_DP_ENC_MISC_SIZE_CHUNK_SIZE;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_MISC_SIZE(stream_id));
+}
+
+static void write_enc_hrd_delays(struct cdns_mhdp_device *mhdp, int stream_id)
+{
+ u32 reg_val = 0;
+
+ reg_val = (mhdp->dsc_config.initial_xmit_delay &
+ CDNS_DP_ENC_HRD_DELAYS_INIT_XMIT_DELAY);
+
+ reg_val |= (mhdp->dsc_config.initial_dec_delay <<
+ CDNS_DP_ENC_HRD_DELAYS_INIT_DEC_DELAY_SHIFT) &
+ CDNS_DP_ENC_HRD_DELAYS_INIT_DEC_DELAY;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_HRD_DELAYS(stream_id));
+}
+
+static void write_enc_rc_scale(struct cdns_mhdp_device *mhdp, int stream_id)
+{
+ u32 reg_val = 0;
+
+ reg_val = (mhdp->dsc_config.initial_scale_value &
+ CDNS_DP_ENC_RC_SCALE_INIT_SCALE_VALUE);
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_SCALE(stream_id));
+}
+
+static void write_enc_rc_scale_inc_dec(struct cdns_mhdp_device *mhdp, int stream_id)
+{
+ u32 reg_val = 0;
+
+ reg_val = (mhdp->dsc_config.scale_increment_interval &
+ CDNS_DP_ENC_RC_SCALE_INC_INTERVAL);
+
+ reg_val |= (mhdp->dsc_config.scale_decrement_interval <<
+ CDNS_DP_ENC_RC_SCALE_DEC_INTERVAL_SHIFT) &
+ CDNS_DP_ENC_RC_SCALE_DEC_INTERVAL;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_SCALE_INC_DEC(stream_id));
+}
+
+static void write_enc_rc_offsets(struct cdns_mhdp_device *mhdp, int stream_id)
+{
+ u32 reg_val;
+
+ reg_val = (mhdp->dsc_config.first_line_bpg_offset &
+ CDNS_DP_ENC_RC_OFFSETS_1_FL_BPG_OFFSET);
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_OFFSETS_1(stream_id));
+
+ reg_val = (mhdp->dsc_config.nfl_bpg_offset &
+ CDNS_DP_ENC_RC_OFFSETS_2_NFL_BPG_OFFSET);
+
+ reg_val |= (mhdp->dsc_config.slice_bpg_offset <<
+ CDNS_DP_ENC_RC_OFFSETS_2_SL_BPG_OFFSET_SHIFT) &
+ CDNS_DP_ENC_RC_OFFSETS_2_SL_BPG_OFFSET;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_OFFSETS_2(stream_id));
+
+ reg_val = (mhdp->dsc_config.initial_offset &
+ CDNS_DP_ENC_RC_OFFSETS_3_INIT_OFFSET);
+
+ reg_val |= (mhdp->dsc_config.final_offset <<
+ CDNS_DP_ENC_RC_OFFSETS_3_FINAL_OFFSET_SHIFT) &
+ CDNS_DP_ENC_RC_OFFSETS_3_FINAL_OFFSET;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_OFFSETS_3(stream_id));
+}
+
+static void write_enc_flatness_detection(struct cdns_mhdp_device *mhdp, int stream_id)
+{
+ u32 reg_val;
+
+ reg_val = (mhdp->dsc_config.flatness_min_qp &
+ CDNS_DP_ENC_FLATNESS_DETECTION_MIN_QP);
+
+ reg_val |= (mhdp->dsc_config.flatness_max_qp <<
+ CDNS_DP_ENC_FLATNESS_DETECTION_MAX_QP_SHIFT) &
+ CDNS_DP_ENC_FLATNESS_DETECTION_MAX_QP;
+
+ reg_val |= (drm_dsc_flatness_det_thresh(&mhdp->dsc_config) <<
+ CDNS_DP_ENC_FLATNESS_DETECTION_THRESH_SHIFT) &
+ CDNS_DP_ENC_FLATNESS_DETECTION_THRESH;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_FLATNESS_DETECTION(stream_id));
+}
+
+static void write_enc_rc_model_size(struct cdns_mhdp_device *mhdp, int stream_id)
+{
+ u32 reg_val;
+
+ reg_val = (mhdp->dsc_config.rc_model_size &
+ CDNS_DP_ENC_RC_MODEL_SIZE_RC_MODEL_SIZE);
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_MODEL_SIZE(stream_id));
+}
+
+static void write_enc_rc_config(struct cdns_mhdp_device *mhdp, int stream_id)
+{
+ u32 reg_val;
+
+ reg_val = (mhdp->dsc_config.rc_edge_factor &
+ CDNS_DP_ENC_RC_CONFIG_EDGE_FACTOR);
+
+ reg_val |= (mhdp->dsc_config.rc_quant_incr_limit0 <<
+ CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_0_SHIFT) &
+ CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_0;
+
+ reg_val |= (mhdp->dsc_config.rc_quant_incr_limit1 <<
+ CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_1_SHIFT) &
+ CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_1;
+
+ reg_val |= (mhdp->dsc_config.rc_tgt_offset_high <<
+ CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_HI_SHIFT) &
+ CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_HI;
+
+ reg_val |= (mhdp->dsc_config.rc_tgt_offset_low <<
+ CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_LO_SHIFT) &
+ CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_LO;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_CONFIG(stream_id));
+}
+
+static void write_enc_rc_buf_thresh(struct cdns_mhdp_device *mhdp, int stream_id)
+{
+ u32 reg_val;
+ int index = 0;
+
+ reg_val = (mhdp->dsc_config.rc_buf_thresh[index++] &
+ CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_0);
+
+ reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
+ CDNS_DP_ENC_RC_BUF_THRESH_THRESH_1_SHIFT) &
+ CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_1;
+
+ reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
+ CDNS_DP_ENC_RC_BUF_THRESH_THRESH_2_SHIFT) &
+ CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_2;
+
+ reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
+ CDNS_DP_ENC_RC_BUF_THRESH_THRESH_3_SHIFT) &
+ CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_3;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_BUF_THRESH_0(stream_id));
+
+ reg_val = (mhdp->dsc_config.rc_buf_thresh[index++] &
+ CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_4);
+
+ reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
+ CDNS_DP_ENC_RC_BUF_THRESH_THRESH_1_SHIFT) &
+ CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_5;
+
+ reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
+ CDNS_DP_ENC_RC_BUF_THRESH_THRESH_2_SHIFT) &
+ CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_6;
+
+ reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
+ CDNS_DP_ENC_RC_BUF_THRESH_THRESH_3_SHIFT) &
+ CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_7;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_BUF_THRESH_1(stream_id));
+
+ reg_val = (mhdp->dsc_config.rc_buf_thresh[index++] &
+ CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_8);
+
+ reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
+ CDNS_DP_ENC_RC_BUF_THRESH_THRESH_1_SHIFT) &
+ CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_9;
+
+ reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
+ CDNS_DP_ENC_RC_BUF_THRESH_THRESH_2_SHIFT) &
+ CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_10;
+
+ reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
+ CDNS_DP_ENC_RC_BUF_THRESH_THRESH_3_SHIFT) &
+ CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_11;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_BUF_THRESH_2(stream_id));
+
+ reg_val = (mhdp->dsc_config.rc_buf_thresh[index++] &
+ CDNS_DP_ENC_RC_BUF_THRESH_3_THRESH_12);
+
+ reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
+ CDNS_DP_ENC_RC_BUF_THRESH_THRESH_1_SHIFT) &
+ CDNS_DP_ENC_RC_BUF_THRESH_3_THRESH_13;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_BUF_THRESH_3(stream_id));
+}
+
+static void write_enc_rc_min_qp(struct cdns_mhdp_device *mhdp, int stream_id)
+{
+ u32 reg_val;
+ int index = 0;
+
+ reg_val = (mhdp->dsc_config.rc_range_params[index++].range_min_qp &
+ CDNS_DP_ENC_RC_MIN_QP_0_RANGE_0);
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
+ CDNS_DP_ENC_RC_MIN_QP_0_RANGE_1;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
+ CDNS_DP_ENC_RC_MIN_QP_0_RANGE_2;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
+ CDNS_DP_ENC_RC_MIN_QP_0_RANGE_3;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
+ CDNS_DP_ENC_RC_MIN_QP_0_RANGE_4;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_MIN_QP_0(stream_id));
+
+ reg_val = (mhdp->dsc_config.rc_range_params[index++].range_min_qp &
+ CDNS_DP_ENC_RC_MIN_QP_1_RANGE_5);
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
+ CDNS_DP_ENC_RC_MIN_QP_1_RANGE_6;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
+ CDNS_DP_ENC_RC_MIN_QP_1_RANGE_7;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
+ CDNS_DP_ENC_RC_MIN_QP_1_RANGE_8;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
+ CDNS_DP_ENC_RC_MIN_QP_1_RANGE_9;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_MIN_QP_1(stream_id));
+
+ reg_val = (mhdp->dsc_config.rc_range_params[index++].range_min_qp &
+ CDNS_DP_ENC_RC_MIN_QP_2_RANGE_10);
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
+ CDNS_DP_ENC_RC_MIN_QP_2_RANGE_11;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
+ CDNS_DP_ENC_RC_MIN_QP_2_RANGE_12;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
+ CDNS_DP_ENC_RC_MIN_QP_2_RANGE_13;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
+ CDNS_DP_ENC_RC_MIN_QP_2_RANGE_14;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_MIN_QP_2(stream_id));
+}
+
+static void write_enc_rc_max_qp(struct cdns_mhdp_device *mhdp, int stream_id)
+{
+ u32 reg_val;
+ int index = 0;
+
+ reg_val = (mhdp->dsc_config.rc_range_params[index++].range_max_qp &
+ CDNS_DP_ENC_RC_MAX_QP_0_RANGE_0);
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
+ CDNS_DP_ENC_RC_MAX_QP_0_RANGE_1;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
+ CDNS_DP_ENC_RC_MAX_QP_0_RANGE_2;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
+ CDNS_DP_ENC_RC_MAX_QP_0_RANGE_3;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
+ CDNS_DP_ENC_RC_MAX_QP_0_RANGE_4;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_MAX_QP_0(stream_id));
+
+ reg_val = (mhdp->dsc_config.rc_range_params[index++].range_max_qp &
+ CDNS_DP_ENC_RC_MAX_QP_1_RANGE_5);
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
+ CDNS_DP_ENC_RC_MAX_QP_1_RANGE_6;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
+ CDNS_DP_ENC_RC_MAX_QP_1_RANGE_7;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
+ CDNS_DP_ENC_RC_MAX_QP_1_RANGE_8;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
+ CDNS_DP_ENC_RC_MAX_QP_1_RANGE_9;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_MAX_QP_1(stream_id));
+
+ reg_val = (mhdp->dsc_config.rc_range_params[index++].range_max_qp &
+ CDNS_DP_ENC_RC_MAX_QP_2_RANGE_10);
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
+ CDNS_DP_ENC_RC_MAX_QP_2_RANGE_11;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
+ CDNS_DP_ENC_RC_MAX_QP_2_RANGE_12;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
+ CDNS_DP_ENC_RC_MAX_QP_2_RANGE_13;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
+ CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
+ CDNS_DP_ENC_RC_MAX_QP_2_RANGE_14;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_MAX_QP_2(stream_id));
+}
+
+static void write_enc_rc_range_bpg(struct cdns_mhdp_device *mhdp, int stream_id)
+{
+ u32 reg_val;
+ int index = 0;
+
+ reg_val = (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset &
+ CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_0);
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
+ CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
+ CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_1;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
+ CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
+ CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_2;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
+ CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
+ CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_3;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
+ CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
+ CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_4;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0(stream_id));
+
+ reg_val = (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset &
+ CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_5);
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
+ CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
+ CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_6;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
+ CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
+ CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_7;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
+ CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
+ CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_8;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
+ CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
+ CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_9;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_1(stream_id));
+
+ reg_val = (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset &
+ CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_10);
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
+ CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
+ CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_11;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
+ CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
+ CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_12;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
+ CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
+ CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_13;
+
+ reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
+ CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
+ CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_14;
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_2(stream_id));
+}
+
+static void write_enc_dpi_ctrl(struct cdns_mhdp_device *mhdp, int stream_id,
+ const struct drm_display_mode *mode)
+{
+ u32 reg_val = 0;
+
+ reg_val = ((mode->crtc_htotal * cdns_mhdp_dsc_compute_initial_lines(mhdp)) &
+ CDNS_DP_ENC_DPI_CTRL_OUT_DELAY_CYCLES);
+
+ writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_DPI_CTRL_OUT_DELAY(stream_id));
+}
+
+void cdns_mhdp_dsc_write_enc_config(struct cdns_mhdp_device *mhdp, int stream_id,
+ const struct drm_display_mode *mode)
+{
+ write_enc_main_conf(mhdp, stream_id);
+ write_enc_picture_size(mhdp, stream_id);
+ write_enc_slice_size(mhdp, stream_id);
+ write_enc_misc_size(mhdp, stream_id);
+ write_enc_hrd_delays(mhdp, stream_id);
+ write_enc_rc_scale(mhdp, stream_id);
+ write_enc_rc_scale_inc_dec(mhdp, stream_id);
+ write_enc_rc_offsets(mhdp, stream_id);
+ write_enc_flatness_detection(mhdp, stream_id);
+ write_enc_rc_model_size(mhdp, stream_id);
+ write_enc_rc_config(mhdp, stream_id);
+ write_enc_rc_buf_thresh(mhdp, stream_id);
+ write_enc_rc_min_qp(mhdp, stream_id);
+ write_enc_rc_max_qp(mhdp, stream_id);
+ write_enc_rc_range_bpg(mhdp, stream_id);
+ write_enc_dpi_ctrl(mhdp, stream_id, mode);
+}
+
+int cdns_mhdp_dsc_sink_support(struct cdns_mhdp_device *mhdp)
+{
+ int ret;
+
+ ret = drm_dp_dpcd_read(&mhdp->aux, DP_DSC_SUPPORT, &mhdp->dsc_params.dsc_cap,
+ DP_DSC_RECEIVER_CAP_SIZE);
+ if (ret != DP_DSC_RECEIVER_CAP_SIZE) {
+ DRM_DEV_ERROR(mhdp->dev, "cannot read sink DSC DPCD: %d\n", ret);
+ goto err;
+ }
+ if (!(mhdp->dsc_params.dsc_cap[0] & DP_DSC_DECOMPRESSION_IS_SUPPORTED)) {
+ ret = -EOPNOTSUPP;
+ DRM_DEV_ERROR(mhdp->dev, "sink does not support DSC: %d\n", ret);
+ goto err;
+ }
+
+ ret = 0;
+err:
+ return ret;
+}
+
+int cdns_mhdp_compute_dsc_params(struct cdns_mhdp_device *mhdp)
+{
+ struct drm_bridge *bridge = &mhdp->bridge;
+ struct drm_dsc_config *dsc_cfg = &mhdp->dsc_config;
+ struct drm_crtc_state *crtc_state = bridge->encoder->crtc->state;
+ u8 *dsc_dpcd = (u8 *)&mhdp->dsc_params.dsc_cap;
+ int ret;
+
+ dsc_cfg->pic_width = crtc_state->adjusted_mode.crtc_hdisplay;
+ dsc_cfg->pic_height = crtc_state->adjusted_mode.crtc_vdisplay;
+
+ dsc_cfg->slice_width = dsc_cfg->pic_width;
+ dsc_cfg->slice_height = DIV_ROUND_UP(dsc_cfg->pic_height,
+ mhdp->dsc_params.slice_count);
+
+ dsc_cfg->dsc_version_major = (dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] &
+ DP_DSC_MAJOR_MASK) >> DP_DSC_MAJOR_SHIFT;
+ dsc_cfg->dsc_version_minor =
+ min(DSC_SUPPORTED_VERSION_MIN,
+ (dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] &
+ DP_DSC_MINOR_MASK) >> DP_DSC_MINOR_SHIFT);
+
+ dsc_cfg->convert_rgb =
+ dsc_dpcd[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT] & DP_DSC_RGB;
+
+ dsc_cfg->vbr_enable = false;
+
+ dsc_cfg->block_pred_enable =
+ dsc_dpcd[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] &
+ DP_DSC_BLK_PREDICTION_IS_SUPPORTED;
+
+ dsc_cfg->bits_per_pixel = mhdp->dsc_params.compressed_bpp << 4;
+
+ dsc_cfg->bits_per_component = mhdp->display_fmt.bpc;
+
+ if (mhdp->dsc_config.bits_per_component == 8)
+ dsc_cfg->line_buf_depth = min(9, drm_dp_dsc_sink_line_buf_depth(dsc_dpcd));
+ else if (mhdp->dsc_config.bits_per_component == 10)
+ dsc_cfg->line_buf_depth = min(11, drm_dp_dsc_sink_line_buf_depth(dsc_dpcd));
+
+ drm_dsc_set_const_params(dsc_cfg);
+ drm_dsc_set_rc_buf_thresh(dsc_cfg);
+
+ ret = drm_dsc_setup_rc_params(dsc_cfg, DRM_DSC_1_1_PRE_SCR);
+ if (ret) {
+ dev_err(mhdp->dev, "could not find DSC RC parameters");
+ return ret;
+ }
+
+ dsc_cfg->initial_scale_value = drm_dsc_initial_scale_value(dsc_cfg);
+ dsc_cfg->slice_count = mhdp->dsc_params.slice_count;
+
+ return drm_dsc_compute_rc_parameters(dsc_cfg);
+}
+
+static void cdns_mhdp_write_data_packet(struct cdns_mhdp_device *mhdp, u32 *buf,
+ int length, int stream_id)
+{
+ int i;
+ u32 reg_val;
+
+ for (i = 0; i < length; i++) {
+ reg_val = buf[i];
+ writel(reg_val, mhdp->regs + CDNS_SOURCE_PIF_DATA_WR(stream_id));
+ }
+}
+
+static void cdns_mhdp_write_pps_header(struct cdns_mhdp_device *mhdp, u32 *buf,
+ int stream_id)
+{
+ writel(SOURCE_PIF_PPS_PPS, mhdp->regs + CDNS_SOURCE_PIF_PPS(stream_id));
+ writel(*buf, mhdp->regs + CDNS_SOURCE_PIF_PPS_HEADER(stream_id));
+}
+
+static int cdns_mhdp_write_pps_infoframe(struct cdns_mhdp_device *mhdp, int stream_id,
+ struct drm_dsc_pps_infoframe *pps_infoframe)
+{
+ u32 reg_val;
+ u32 entry_id = 0;
+
+ writel(1, mhdp->regs + CDNS_SOURCE_PIF_FIFO1_FLUSH(stream_id));
+
+ cdns_mhdp_write_pps_header(mhdp, (u32 *)&pps_infoframe->pps_header, 0);
+ cdns_mhdp_write_data_packet(mhdp, (u32 *)&pps_infoframe->pps_payload,
+ DP_DSC_PPS_SIZE / 4, 0);
+
+ /* Entry ID */
+ writel(entry_id, mhdp->regs + CDNS_SOURCE_PIF_WR_ADDR(stream_id));
+
+ writel(SOURCE_PIF_WR_REQ_HOST_WR, mhdp->regs + CDNS_SOURCE_PIF_WR_REQ(stream_id));
+
+ reg_val = SOURCE_PIF_PKT_ALLOC_REG_ACTIVE_IDLE_TYPE |
+ SOURCE_PIF_PKT_ALLOC_REG_TYPE_VALID |
+ ((DP_SDP_PPS << SOURCE_PIF_PKT_ALLOC_REG_PACKET_TYPE_SHIFT) &
+ SOURCE_PIF_PKT_ALLOC_REG_PACKET_TYPE) |
+ (entry_id & SOURCE_PIF_PKT_ALLOC_REG_PKT_ALLOC_ADDR);
+
+ writel(reg_val, mhdp->regs + CDNS_SOURCE_PIF_PKT_ALLOC_REG(stream_id));
+
+ writel
+ (SOURCE_PIF_PKT_ALLOC_WR_EN_EN, mhdp->regs + CDNS_SOURCE_PIF_PKT_ALLOC_WR_EN(stream_id));
+
+ return 0;
+}
+
+int cdns_mhdp_dsc_send_pps_sdp(struct cdns_mhdp_device *mhdp, int stream_id)
+{
+ struct drm_dsc_config *dsc_cfg = &mhdp->dsc_config;
+ struct drm_dsc_pps_infoframe dp_dsc_pps_sdp;
+
+ drm_dsc_dp_pps_header_init(&dp_dsc_pps_sdp.pps_header);
+
+ drm_dsc_pps_payload_pack(&dp_dsc_pps_sdp.pps_payload, dsc_cfg);
+
+ return cdns_mhdp_write_pps_infoframe(mhdp, stream_id, &dp_dsc_pps_sdp);
+}
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.h
new file mode 100644
index 000000000000..c44d7e3d0002
--- /dev/null
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.h
@@ -0,0 +1,285 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) Cadence Design Systems, Inc.
+ *
+ * Author: Swapnil Jakhade <sjakhade@cadence.com>
+ */
+
+#ifndef CDNS_MHDP_DSC_H_
+#define CDNS_MHDP_DSC_H_
+
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/minmax.h>
+#include <drm/display/drm_dsc_helper.h>
+#include <drm/drm_bridge.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_print.h>
+
+#define DSC_SUPPORTED_VERSION_MIN 1
+
+#define DSC_OUTPUT_BUFFER_MAX_ADDRESS 3667U
+#define DP_DSC_PPS_SIZE 128
+
+#define CDNS_DP_COM_MAIN_CONF 0
+#define CDNS_DP_COM_MAIN_CONF_SPLIT_PANEL BIT(0)
+#define CDNS_DP_COM_MAIN_CONF_MUX_MODE BIT(1)
+#define CDNS_DP_COM_MAIN_CONF_MUX_SEL_OUT BIT(2)
+#define CDNS_DP_COM_MAIN_CONF_DE_RASTER_EN BIT(3)
+#define CDNS_DP_COM_MAIN_CONF_INPUT_MODE BIT(4)
+#define CDNS_DP_COM_MAIN_CONF_MUX_EOC_EN BIT(5)
+#define CDNS_DP_COM_MAIN_CONF_AUTO_DB_UPDATE BIT(6)
+
+#define CDNS_DP_ENC_MAIN_CONF(d) (0x120 + ((d) * 0x100))
+#define CDNS_DP_ENC_MAIN_CONF_INPUT_BPC GENMASK(1, 0)
+#define CDNS_DP_ENC_MAIN_CONF_CONVERT_RGB BIT(2)
+#define CDNS_DP_ENC_MAIN_CONF_ENABLE_422 BIT(3)
+#define CDNS_DP_ENC_MAIN_CONF_LINEBUF_DEPTH GENMASK(7, 4)
+#define CDNS_DP_ENC_MAIN_CONF_LINEBUF_DEPTH_SHIFT 4
+#define CDNS_DP_ENC_MAIN_CONF_BITS_PER_PIXEL GENMASK(17, 8)
+#define CDNS_DP_ENC_MAIN_CONF_BITS_PER_PIXEL_SHIFT 8
+#define CDNS_DP_ENC_MAIN_CONF_BLOCK_PRED_EN BIT(18)
+#define CDNS_DP_ENC_MAIN_CONF_VIDEO_MODE BIT(19)
+#define CDNS_DP_ENC_MAIN_CONF_ICH_RST_EOL BIT(20)
+#define CDNS_DP_ENC_MAIN_CONF_INITIAL_LINES GENMASK(31, 24)
+#define CDNS_DP_ENC_MAIN_CONF_INITIAL_LINES_SHIFT 24
+
+#define CDNS_DP_ENC_PICTURE_SIZE(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x4)
+#define CDNS_DP_ENC_PICTURE_SIZE_HEIGHT GENMASK(31, 16)
+#define CDNS_DP_ENC_PICTURE_SIZE_HEIGHT_SHIFT 16
+#define CDNS_DP_ENC_PICTURE_SIZE_WIDTH GENMASK(15, 0)
+
+#define CDNS_DP_ENC_SLICE_SIZE(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x8)
+#define CDNS_DP_ENC_SLICE_SIZE_HEIGHT GENMASK(31, 16)
+#define CDNS_DP_ENC_SLICE_SIZE_HEIGHT_SHIFT 16
+#define CDNS_DP_ENC_SLICE_SIZE_WIDTH GENMASK(15, 0)
+
+#define CDNS_DP_ENC_MISC_SIZE(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xc)
+#define CDNS_DP_ENC_MISC_SIZE_CHUNK_SIZE GENMASK(31, 16)
+#define CDNS_DP_ENC_MISC_SIZE_CHUNK_SIZE_SHIFT 16
+#define CDNS_DP_ENC_MISC_SIZE_OB_MAX_ADDR GENMASK(15, 2)
+#define CDNS_DP_ENC_MISC_SIZE_OB_MAX_ADDR_SHIFT 2
+#define CDNS_DP_ENC_MISC_SIZE_LAST_GRP_SIZE GENMASK(1, 0)
+
+#define CDNS_DP_ENC_HRD_DELAYS(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x10)
+#define CDNS_DP_ENC_HRD_DELAYS_INIT_DEC_DELAY GENMASK(31, 16)
+#define CDNS_DP_ENC_HRD_DELAYS_INIT_DEC_DELAY_SHIFT 16
+#define CDNS_DP_ENC_HRD_DELAYS_INIT_XMIT_DELAY GENMASK(9, 0)
+
+#define CDNS_DP_ENC_RC_SCALE(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x14)
+#define CDNS_DP_ENC_RC_SCALE_INIT_SCALE_VALUE GENMASK(5, 0)
+
+#define CDNS_DP_ENC_RC_SCALE_INC_DEC(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x18)
+#define CDNS_DP_ENC_RC_SCALE_DEC_INTERVAL GENMASK(27, 16)
+#define CDNS_DP_ENC_RC_SCALE_DEC_INTERVAL_SHIFT 16
+#define CDNS_DP_ENC_RC_SCALE_INC_INTERVAL GENMASK(15, 0)
+
+#define CDNS_DP_ENC_RC_OFFSETS_1(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x1c)
+#define CDNS_DP_ENC_RC_OFFSETS_1_FL_BPG_OFFSET GENMASK(4, 0)
+
+#define CDNS_DP_ENC_RC_OFFSETS_2(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x20)
+#define CDNS_DP_ENC_RC_OFFSETS_2_SL_BPG_OFFSET GENMASK(31, 16)
+#define CDNS_DP_ENC_RC_OFFSETS_2_SL_BPG_OFFSET_SHIFT 16
+#define CDNS_DP_ENC_RC_OFFSETS_2_NFL_BPG_OFFSET GENMASK(15, 0)
+
+#define CDNS_DP_ENC_RC_OFFSETS_3(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x24)
+#define CDNS_DP_ENC_RC_OFFSETS_3_FINAL_OFFSET GENMASK(31, 16)
+#define CDNS_DP_ENC_RC_OFFSETS_3_FINAL_OFFSET_SHIFT 16
+#define CDNS_DP_ENC_RC_OFFSETS_3_INIT_OFFSET GENMASK(15, 0)
+
+#define CDNS_DP_ENC_FLATNESS_DETECTION(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x28)
+#define CDNS_DP_ENC_FLATNESS_DETECTION_THRESH GENMASK(17, 10)
+#define CDNS_DP_ENC_FLATNESS_DETECTION_THRESH_SHIFT 10
+#define CDNS_DP_ENC_FLATNESS_DETECTION_MAX_QP GENMASK(9, 5)
+#define CDNS_DP_ENC_FLATNESS_DETECTION_MAX_QP_SHIFT 5
+#define CDNS_DP_ENC_FLATNESS_DETECTION_MIN_QP GENMASK(4, 0)
+
+#define CDNS_DP_ENC_RC_MODEL_SIZE(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x2c)
+#define CDNS_DP_ENC_RC_MODEL_SIZE_RC_MODEL_SIZE GENMASK(15, 0)
+
+#define CDNS_DP_ENC_RC_CONFIG(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x30)
+#define CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_LO GENMASK(27, 24)
+#define CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_LO_SHIFT 24
+#define CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_HI GENMASK(23, 20)
+#define CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_HI_SHIFT 20
+#define CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_1 GENMASK(17, 13)
+#define CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_1_SHIFT 13
+#define CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_0 GENMASK(12, 8)
+#define CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_0_SHIFT 8
+#define CDNS_DP_ENC_RC_CONFIG_EDGE_FACTOR GENMASK(3, 0)
+
+#define CDNS_DP_ENC_RC_BUF_THRESH_0(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x34)
+#define CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_3 GENMASK(31, 24)
+#define CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_2 GENMASK(23, 16)
+#define CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_1 GENMASK(15, 8)
+#define CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_0 GENMASK(7, 0)
+
+#define CDNS_DP_ENC_RC_BUF_THRESH_1(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x38)
+#define CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_7 GENMASK(31, 24)
+#define CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_6 GENMASK(23, 16)
+#define CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_5 GENMASK(15, 8)
+#define CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_4 GENMASK(7, 0)
+
+#define CDNS_DP_ENC_RC_BUF_THRESH_2(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x3c)
+#define CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_11 GENMASK(31, 24)
+#define CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_10 GENMASK(23, 16)
+#define CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_9 GENMASK(15, 8)
+#define CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_8 GENMASK(7, 0)
+
+#define CDNS_DP_ENC_RC_BUF_THRESH_3(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x40)
+#define CDNS_DP_ENC_RC_BUF_THRESH_3_THRESH_13 GENMASK(15, 8)
+#define CDNS_DP_ENC_RC_BUF_THRESH_3_THRESH_12 GENMASK(7, 0)
+
+#define CDNS_DP_ENC_RC_BUF_THRESH_THRESH_3_SHIFT 24
+#define CDNS_DP_ENC_RC_BUF_THRESH_THRESH_2_SHIFT 16
+#define CDNS_DP_ENC_RC_BUF_THRESH_THRESH_1_SHIFT 8
+
+#define CDNS_DP_ENC_RC_MIN_QP_0(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x44)
+#define CDNS_DP_ENC_RC_MIN_QP_0_RANGE_4 GENMASK(24, 20)
+#define CDNS_DP_ENC_RC_MIN_QP_0_RANGE_3 GENMASK(19, 15)
+#define CDNS_DP_ENC_RC_MIN_QP_0_RANGE_2 GENMASK(14, 10)
+#define CDNS_DP_ENC_RC_MIN_QP_0_RANGE_1 GENMASK(9, 5)
+#define CDNS_DP_ENC_RC_MIN_QP_0_RANGE_0 GENMASK(4, 0)
+
+#define CDNS_DP_ENC_RC_MIN_QP_1(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x48)
+#define CDNS_DP_ENC_RC_MIN_QP_1_RANGE_9 GENMASK(24, 20)
+#define CDNS_DP_ENC_RC_MIN_QP_1_RANGE_8 GENMASK(19, 15)
+#define CDNS_DP_ENC_RC_MIN_QP_1_RANGE_7 GENMASK(14, 10)
+#define CDNS_DP_ENC_RC_MIN_QP_1_RANGE_6 GENMASK(9, 5)
+#define CDNS_DP_ENC_RC_MIN_QP_1_RANGE_5 GENMASK(4, 0)
+
+#define CDNS_DP_ENC_RC_MIN_QP_2(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x4c)
+#define CDNS_DP_ENC_RC_MIN_QP_2_RANGE_14 GENMASK(24, 20)
+#define CDNS_DP_ENC_RC_MIN_QP_2_RANGE_13 GENMASK(19, 15)
+#define CDNS_DP_ENC_RC_MIN_QP_2_RANGE_12 GENMASK(14, 10)
+#define CDNS_DP_ENC_RC_MIN_QP_2_RANGE_11 GENMASK(9, 5)
+#define CDNS_DP_ENC_RC_MIN_QP_2_RANGE_10 GENMASK(4, 0)
+
+#define CDNS_DP_ENC_RC_MAX_QP_0(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x50)
+#define CDNS_DP_ENC_RC_MAX_QP_0_RANGE_4 GENMASK(24, 20)
+#define CDNS_DP_ENC_RC_MAX_QP_0_RANGE_3 GENMASK(19, 15)
+#define CDNS_DP_ENC_RC_MAX_QP_0_RANGE_2 GENMASK(14, 10)
+#define CDNS_DP_ENC_RC_MAX_QP_0_RANGE_1 GENMASK(9, 5)
+#define CDNS_DP_ENC_RC_MAX_QP_0_RANGE_0 GENMASK(4, 0)
+
+#define CDNS_DP_ENC_RC_MAX_QP_1(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x54)
+#define CDNS_DP_ENC_RC_MAX_QP_1_RANGE_9 GENMASK(24, 20)
+#define CDNS_DP_ENC_RC_MAX_QP_1_RANGE_8 GENMASK(19, 15)
+#define CDNS_DP_ENC_RC_MAX_QP_1_RANGE_7 GENMASK(14, 10)
+#define CDNS_DP_ENC_RC_MAX_QP_1_RANGE_6 GENMASK(9, 5)
+#define CDNS_DP_ENC_RC_MAX_QP_1_RANGE_5 GENMASK(4, 0)
+
+#define CDNS_DP_ENC_RC_MAX_QP_2(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x58)
+#define CDNS_DP_ENC_RC_MAX_QP_2_RANGE_14 GENMASK(24, 20)
+#define CDNS_DP_ENC_RC_MAX_QP_2_RANGE_13 GENMASK(19, 15)
+#define CDNS_DP_ENC_RC_MAX_QP_2_RANGE_12 GENMASK(14, 10)
+#define CDNS_DP_ENC_RC_MAX_QP_2_RANGE_11 GENMASK(9, 5)
+#define CDNS_DP_ENC_RC_MAX_QP_2_RANGE_10 GENMASK(4, 0)
+
+#define CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT 20
+#define CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT 15
+#define CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT 10
+#define CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT 5
+
+#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x5c)
+#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_4 GENMASK(24, 20)
+#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_3 GENMASK(19, 15)
+#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_2 GENMASK(14, 10)
+#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_1 GENMASK(9, 5)
+#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_0 GENMASK(4, 0)
+
+#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_1(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x60)
+#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_9 GENMASK(24, 20)
+#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_8 GENMASK(19, 15)
+#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_7 GENMASK(14, 10)
+#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_6 GENMASK(9, 5)
+#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_5 GENMASK(4, 0)
+
+#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_2(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x64)
+#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_14 GENMASK(24, 20)
+#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_13 GENMASK(19, 15)
+#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_12 GENMASK(14, 10)
+#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_11 GENMASK(9, 5)
+#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_10 GENMASK(4, 0)
+
+#define CDNS_DP_ENC_DPI_CTRL_OUT_DELAY(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x68)
+#define CDNS_DP_ENC_DPI_CTRL_OUT_DELAY_CYCLES GENMASK(15, 0)
+
+#define CDNS_DP_ENC_GENERAL_STATUS(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xa0)
+#define CDNS_DP_ENC_GENERAL_STATUS_OUT_BUFF_FULL_1 BIT(6)
+#define CDNS_DP_ENC_GENERAL_STATUS_OUT_BUFF_FULL_0 BIT(5)
+#define CDNS_DP_ENC_GENERAL_STATUS_OUT_BUFF_EMPTY_1 BIT(4)
+#define CDNS_DP_ENC_GENERAL_STATUS_OUT_BUFF_EMPTY_0 BIT(3)
+#define CDNS_DP_ENC_GENERAL_STATUS_FRAME_DONE BIT(2)
+#define CDNS_DP_ENC_GENERAL_STATUS_FRAME_STARTED BIT(1)
+#define CDNS_DP_ENC_GENERAL_STATUS_CE BIT(0)
+
+#define CDNS_DP_ENC_HSLICE_STATUS(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xa4)
+#define CDNS_DP_ENC_HSLICE_STATUS_ACTUAL_SLICE GENMASK(31, 16)
+#define CDNS_DP_ENC_HSLICE_STATUS_ACTUAL_LINE GENMASK(15, 0)
+
+#define CDNS_DP_ENC_OUT_STATUS(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xa8)
+#define CDNS_DP_ENC_OUT_STATUS_ACTUAL_SLICE GENMASK(31, 16)
+#define CDNS_DP_ENC_OUT_STATUS_ACTUAL_LINE GENMASK(15, 0)
+
+#define CDNS_DP_ENC_INT_STAT(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xac)
+#define CDNS_DP_ENC_INT_STAT_OUT_BUFF_FULL_1 BIT(10)
+#define CDNS_DP_ENC_INT_STAT_OUT_BUFF_FULL_0 BIT(9)
+#define CDNS_DP_ENC_INT_STAT_OUT_BUFF_EMPTY_1 BIT(8)
+#define CDNS_DP_ENC_INT_STAT_OUT_BUFF_EMPTY_0 BIT(7)
+#define CDNS_DP_ENC_INT_STAT_FRAME_DONE BIT(6)
+#define CDNS_DP_ENC_INT_STAT_FRAME_STARTED BIT(5)
+#define CDNS_DP_ENC_INT_STAT_CE BIT(4)
+#define CDNS_DP_ENC_INT_STAT_RC_BUFF_OVER_1 BIT(3)
+#define CDNS_DP_ENC_INT_STAT_RC_BUFF_OVER_0 BIT(2)
+#define CDNS_DP_ENC_INT_STAT_OUT_BUFF_UND_1 BIT(1)
+#define CDNS_DP_ENC_INT_STAT_OUT_BUFF_UND_0 BIT(0)
+
+#define CDNS_DP_ENC_INT_CLR(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xb0)
+#define CDNS_DP_ENC_INT_CLR_OUT_BUFF_FULL_1 BIT(10)
+#define CDNS_DP_ENC_INT_CLR_OUT_BUFF_FULL_0 BIT(9)
+#define CDNS_DP_ENC_INT_CLR_OUT_BUFF_EMPTY_1 BIT(8)
+#define CDNS_DP_ENC_INT_CLR_OUT_BUFF_EMPTY_0 BIT(7)
+#define CDNS_DP_ENC_INT_CLR_FRAME_DONE BIT(6)
+#define CDNS_DP_ENC_INT_CLR_FRAME_STARTED BIT(5)
+#define CDNS_DP_ENC_INT_CLR_CE BIT(4)
+#define CDNS_DP_ENC_INT_CLR_RC_BUFF_OVER_1 BIT(3)
+#define CDNS_DP_ENC_INT_CLR_RC_BUFF_OVER_0 BIT(2)
+#define CDNS_DP_ENC_INT_CLR_OUT_BUFF_UND_1 BIT(1)
+#define CDNS_DP_ENC_INT_CLR_OUT_BUFF_UND_0 BIT(0)
+
+#define CDNS_DP_ENC_INT_MASK(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xb4)
+#define CDNS_DP_ENC_INT_MASK_OUT_BUFF_FULL_1 BIT(10)
+#define CDNS_DP_ENC_INT_MASK_OUT_BUFF_FULL_0 BIT(9)
+#define CDNS_DP_ENC_INT_MASK_OUT_BUFF_EMPTY_1 BIT(8)
+#define CDNS_DP_ENC_INT_MASK_OUT_BUFF_EMPTY_0 BIT(7)
+#define CDNS_DP_ENC_INT_MASK_FRAME_DONE BIT(6)
+#define CDNS_DP_ENC_INT_MASK_FRAME_STARTED BIT(5)
+#define CDNS_DP_ENC_INT_MASK_CE BIT(4)
+#define CDNS_DP_ENC_INT_MASK_RC_BUFF_OVER_1 BIT(3)
+#define CDNS_DP_ENC_INT_MASK_RC_BUFF_OVER_0 BIT(2)
+#define CDNS_DP_ENC_INT_MASK_OUT_BUFF_UND_1 BIT(1)
+#define CDNS_DP_ENC_INT_MASK_OUT_BUFF_UND_0 BIT(0)
+
+#define CDNS_DP_ENC_INT_TEST(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xb8)
+#define CDNS_DP_ENC_INT_TEST_OUT_BUFF_FULL_1 BIT(10)
+#define CDNS_DP_ENC_INT_TEST_OUT_BUFF_FULL_0 BIT(9)
+#define CDNS_DP_ENC_INT_TEST_OUT_BUFF_EMPTY_1 BIT(8)
+#define CDNS_DP_ENC_INT_TEST_OUT_BUFF_EMPTY_0 BIT(7)
+#define CDNS_DP_ENC_INT_TEST_FRAME_DONE BIT(6)
+#define CDNS_DP_ENC_INT_TEST_FRAME_STARTED BIT(5)
+#define CDNS_DP_ENC_INT_TEST_CE BIT(4)
+#define CDNS_DP_ENC_INT_TEST_RC_BUFF_OVER_1 BIT(3)
+#define CDNS_DP_ENC_INT_TEST_RC_BUFF_OVER_0 BIT(2)
+#define CDNS_DP_ENC_INT_TEST_OUT_BUFF_UND_1 BIT(1)
+#define CDNS_DP_ENC_INT_TEST_OUT_BUFF_UND_0 BIT(0)
+
+void cdns_mhdp_dsc_write_config(struct cdns_mhdp_device *mhdp);
+void cdns_mhdp_dsc_write_enc_config(struct cdns_mhdp_device *mhdp, int stream_id,
+ const struct drm_display_mode *mode);
+int cdns_mhdp_dsc_sink_support(struct cdns_mhdp_device *mhdp);
+int cdns_mhdp_compute_dsc_params(struct cdns_mhdp_device *mhdp);
+int cdns_mhdp_dsc_send_pps_sdp(struct cdns_mhdp_device *mhdp, int stream_id);
+
+#endif /* MHDP_DSC_H_ */
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v5 2/2] drm: bridge: cdns-mhdp8546: Add support for DSC and FEC
2025-09-15 10:30 ` [PATCH v5 2/2] drm: bridge: cdns-mhdp8546: Add support for DSC and FEC Harikrishna Shenoy
@ 2025-09-15 11:06 ` Dmitry Baryshkov
2025-09-15 18:53 ` Dmitry Baryshkov
2025-09-30 12:41 ` Harikrishna Shenoy
2025-09-19 19:38 ` kernel test robot
1 sibling, 2 replies; 9+ messages in thread
From: Dmitry Baryshkov @ 2025-09-15 11:06 UTC (permalink / raw)
To: Harikrishna Shenoy
Cc: andrzej.hajda, neil.armstrong, rfoss, Laurent.pinchart, jonas,
jernej.skrabec, airlied, simona, maarten.lankhorst, mripard,
tzimmermann, robh, krzk+dt, conor+dt, sjakhade, yamonkar, lumag,
dianders, jani.nikula, luca.ceresoli, andy.yan, dri-devel,
devicetree, linux-kernel, devarsht, u-kumar1, s-jain1,
tomi.valkeinen
On Mon, Sep 15, 2025 at 04:00:41PM +0530, Harikrishna Shenoy wrote:
> From: Swapnil Jakhade <sjakhade@cadence.com>
>
> Enable support for Display Stream Compression (DSC) in independent
> mode with a single stream, along with Forward Error Correction (FEC)
> in the Cadence MHDP8546 DisplayPort controller driver.
>
> FEC is required when DSC is enabled to ensure reliable transmission
> of the compressed stream.
>
> Signed-off-by: Swapnil Jakhade <sjakhade@cadence.com>
> Signed-off-by: Harikrishna Shenoy <h-shenoy@ti.com>
> ---
> drivers/gpu/drm/bridge/cadence/Makefile | 2 +-
> .../drm/bridge/cadence/cdns-mhdp8546-core.c | 367 ++++++++-
> .../drm/bridge/cadence/cdns-mhdp8546-core.h | 68 ++
> .../drm/bridge/cadence/cdns-mhdp8546-dsc.c | 695 ++++++++++++++++++
> .../drm/bridge/cadence/cdns-mhdp8546-dsc.h | 285 +++++++
> 5 files changed, 1392 insertions(+), 25 deletions(-)
> create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.c
> create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.h
>
> diff --git a/drivers/gpu/drm/bridge/cadence/Makefile b/drivers/gpu/drm/bridge/cadence/Makefile
> index c95fd5b81d13..7957fbdc1b78 100644
> --- a/drivers/gpu/drm/bridge/cadence/Makefile
> +++ b/drivers/gpu/drm/bridge/cadence/Makefile
> @@ -3,5 +3,5 @@ obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o
> cdns-dsi-y := cdns-dsi-core.o
> cdns-dsi-$(CONFIG_DRM_CDNS_DSI_J721E) += cdns-dsi-j721e.o
> obj-$(CONFIG_DRM_CDNS_MHDP8546) += cdns-mhdp8546.o
> -cdns-mhdp8546-y := cdns-mhdp8546-core.o cdns-mhdp8546-hdcp.o
> +cdns-mhdp8546-y := cdns-mhdp8546-core.o cdns-mhdp8546-hdcp.o cdns-mhdp8546-dsc.o
> cdns-mhdp8546-$(CONFIG_DRM_CDNS_MHDP8546_J721E) += cdns-mhdp8546-j721e.o
> diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
> index a614d1384f71..df8bbf8919b2 100644
> --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
> +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
> @@ -50,6 +50,7 @@
> #include <linux/unaligned.h>
>
> #include "cdns-mhdp8546-core.h"
> +#include "cdns-mhdp8546-dsc.h"
> #include "cdns-mhdp8546-hdcp.h"
> #include "cdns-mhdp8546-j721e.h"
>
> @@ -545,6 +546,116 @@ int cdns_mhdp_adjust_lt(struct cdns_mhdp_device *mhdp, unsigned int nlanes,
> return ret;
> }
>
> +static int cdns_mhdp_wait_for_fec(struct cdns_mhdp_device *mhdp,
> + bool expected_status)
> +{
> + u32 fec_status;
> + unsigned long timeout = jiffies + msecs_to_jiffies(1000);
> +
> + cdns_mhdp_reg_read(mhdp, CDNS_DP_FEC_STATUS, &fec_status);
> + while (((fec_status & CDNS_DP_FEC_BUSY) != expected_status) &&
> + time_before(jiffies, timeout)) {
> + cdns_mhdp_reg_read(mhdp, CDNS_DP_FEC_STATUS, &fec_status);
> + cpu_relax();
> + }
> +
> + if (time_after_eq(jiffies, timeout)) {
> + DRM_DEV_ERROR(mhdp->dev, "Timeout while waiting for FEC\n");
> + return -ETIMEDOUT;
> + }
> +
> + return 0;
> +}
> +
> +static int cdns_mhdp_fec_sink_support(struct cdns_mhdp_device *mhdp)
> +{
> + int ret;
> + u16 dpcd_buffer;
> +
> + ret = drm_dp_dpcd_read(&mhdp->aux, DP_FEC_CAPABILITY, &dpcd_buffer, 1);
> + if (ret < 0)
> + goto err;
Only since DP 1.4 if I'm not mistaken.
> +
> + if (!(dpcd_buffer & DP_FEC_CAPABLE)) {
> + ret = -EOPNOTSUPP;
> + DRM_DEV_ERROR(mhdp->dev, "sink does not support FEC: %d\n", ret);
This is too loud.
> + goto err;
> + }
> +
> + if (ret > 0)
> + return 0;
> +err:
> + return ret;
> +}
Consider extracting a common helper and using it here and in the Intel
DP driver. Also please use new DPCD helpers which return 0 instead of
size.
> +
> +static int cdns_mhdp_fec_sink_set_ready(struct cdns_mhdp_device *mhdp,
> + bool enable)
> +{
> + int ret;
> + u8 dpcd_buffer;
> +
> + ret = drm_dp_dpcd_read(&mhdp->aux, DP_FEC_CONFIGURATION, &dpcd_buffer, 1);
> + if (ret < 0)
> + goto err;
No need to read it back, it's controlled by DPTX and you don't set
anything else.
> +
> + if (enable)
> + dpcd_buffer |= DP_FEC_READY;
> + else
> + dpcd_buffer &= ~DP_FEC_READY;
> +
> + ret = drm_dp_dpcd_write(&mhdp->aux, DP_FEC_CONFIGURATION, &dpcd_buffer, 1);
> +
> + if (ret > 0)
> + return 0;
> +err:
> + DRM_DEV_ERROR(mhdp->dev, "cannot set sink FEC ready: %d\n", ret);
> + return ret;
> +}
> +
> +static int cdns_mhdp_fec_set_ready(struct cdns_mhdp_device *mhdp, bool enable)
> +{
> + int ret;
> +
> + ret = cdns_mhdp_fec_sink_support(mhdp);
> + if (ret)
> + goto err;
> +
> + ret = cdns_mhdp_fec_sink_set_ready(mhdp, enable);
> + if (ret)
> + goto err;
> +
> + ret = cdns_mhdp_reg_write_bit(mhdp, CDNS_DP_FEC_CTRL, 1, 1, enable);
> + if (ret)
> + goto err;
> +
> +err:
> + return ret;
> +}
> +
> +static int cdns_mhdp_fec_enable(struct cdns_mhdp_device *mhdp, bool enable)
> +{
> + int ret;
> + u32 resp;
> +
> + ret = cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &resp);
> + if (ret < 0)
> + goto err;
> +
> + if (!(resp & CDNS_DP_NO_VIDEO_MODE)) {
> + ret = -EIO;
> + goto err;
> + }
> +
> + ret = cdns_mhdp_reg_write_bit(mhdp, CDNS_DP_FEC_CTRL, 0, 1, enable);
> + if (ret)
> + goto err;
> +
> + return cdns_mhdp_wait_for_fec(mhdp, enable);
> +err:
> + DRM_DEV_ERROR(mhdp->dev, "set fec enable failed: %d\n", ret);
> + return ret;
> +}
> +
> /**
> * cdns_mhdp_link_configure() - configure a DisplayPort link
> * @aux: DisplayPort AUX channel
> @@ -1407,6 +1518,13 @@ static int cdns_mhdp_link_up(struct cdns_mhdp_device *mhdp)
> amp[1] = DP_SET_ANSI_8B10B;
> drm_dp_dpcd_write(&mhdp->aux, DP_DOWNSPREAD_CTRL, amp, 2);
>
> + if (cdns_mhdp_fec_set_ready(mhdp, true)) {
> + mhdp->fec_enabled = false;
> + dev_info(mhdp->dev, "Cannot set FEC ready.\n");
If DPRX doesn't support FEC, we've just got several messages for no
particular reason. It's an optional feature.
> + } else {
> + mhdp->fec_enabled = true;
> + }
> +
> if (mhdp->host.fast_link & mhdp->sink.fast_link) {
> dev_err(mhdp->dev, "fastlink not supported\n");
> return -EOPNOTSUPP;
> @@ -1494,10 +1612,14 @@ static int cdns_mhdp_connector_detect(struct drm_connector *conn,
> return cdns_mhdp_detect(mhdp);
> }
>
> -static u32 cdns_mhdp_get_bpp(struct cdns_mhdp_display_fmt *fmt)
> +static u32 cdns_mhdp_get_bpp(struct cdns_mhdp_device *mhdp)
> {
> + struct cdns_mhdp_display_fmt *fmt = &mhdp->display_fmt;
> u32 bpp;
>
> + if (mhdp->dsc_params.compression_enable)
> + return mhdp->dsc_params.compressed_bpp;
> +
> if (fmt->y_only)
> return fmt->bpc;
>
> @@ -1533,7 +1655,7 @@ bool cdns_mhdp_bandwidth_ok(struct cdns_mhdp_device *mhdp,
> * units of the rate parameter.
> */
>
> - bpp = cdns_mhdp_get_bpp(&mhdp->display_fmt);
> + bpp = cdns_mhdp_get_bpp(mhdp);
> req_bw = mode->clock * bpp / 8;
> max_bw = lanes * rate;
> if (req_bw > max_bw) {
> @@ -1693,6 +1815,74 @@ static int cdns_mhdp_attach(struct drm_bridge *bridge,
> return ret;
> }
>
> +static int cdns_mhdp_dsc_set_stream_compressed(struct cdns_mhdp_device *mhdp,
> + int stream_id, bool compressed)
> +{
> + u32 reg_val;
> + int ret;
> +
> + ret = cdns_mhdp_reg_read(mhdp, CDNS_DP_VB_ID(stream_id), ®_val);
> + if (ret < 0)
> + return ret;
> +
> + if (compressed)
> + reg_val |= CDNS_DP_VB_ID_COMPRESSED;
> + else
> + reg_val &= ~CDNS_DP_VB_ID_COMPRESSED;
> +
> + return cdns_mhdp_reg_write(mhdp, CDNS_DP_VB_ID(stream_id), reg_val);
> +}
> +
> +static int cdns_mhdp_dsc_wait_for_completion(struct cdns_mhdp_device *mhdp,
> + u8 event_bit, int stream_id)
> +{
> + u32 dsc_ctrl;
> + int ret;
> + unsigned long timeout;
> +
> + ret = cdns_mhdp_reg_write_bit(mhdp, CDNS_DP_DSC_CTRL(stream_id),
> + event_bit, 1, true);
> + if (ret)
> + return ret;
> +
> + timeout = jiffies + msecs_to_jiffies(1000);
> +
> + do {
> + cdns_mhdp_reg_read(mhdp, CDNS_DP_DSC_CTRL(stream_id), &dsc_ctrl);
> + cpu_relax();
> + } while (((dsc_ctrl & (1 << event_bit)) != 0) && time_before(jiffies, timeout));
> +
> + if (time_after_eq(jiffies, timeout)) {
> + DRM_DEV_ERROR(mhdp->dev, "Timeout while waiting for event %d\n", event_bit);
> + return -ETIMEDOUT;
> + }
> +
> + return 0;
> +}
> +
> +static int cdns_mhdp_dsc_reset(struct cdns_mhdp_device *mhdp)
> +{
> + /* Setting reset bit in any stream resets entire DSC. Stream 0 may always be used for it. */
> + return cdns_mhdp_dsc_wait_for_completion(mhdp, CDNS_DP_DSC_CTRL_SW_RST_BIT, 0);
> +}
> +
> +static int cdns_mhdp_dsc_update(struct cdns_mhdp_device *mhdp, int stream_id)
> +{
> + return cdns_mhdp_dsc_wait_for_completion(mhdp, CDNS_DP_DSC_CTRL_REG_UPDATE_BIT,
> + stream_id);
> +}
> +
> +static int cdns_mhdp_dsc_enable(struct cdns_mhdp_device *mhdp, int stream_id, bool enable)
> +{
> + return cdns_mhdp_reg_write_bit(mhdp, CDNS_DP_DSC_CTRL(stream_id),
> + CDNS_DP_DSC_CTRL_EN_BIT, 1, enable ? 1 : 0);
> +}
> +
> +static int cdns_mhdp_dsc_sink_enable(struct cdns_mhdp_device *mhdp, bool enable)
> +{
> + return drm_dp_dpcd_writeb(&mhdp->aux, DP_DSC_ENABLE, enable) != 1;
> +}
> +
> static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
> const struct drm_display_mode *mode)
> {
> @@ -1702,7 +1892,7 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
> front_porch, back_porch, msa_h0, msa_v0, hsync, vsync,
> dp_vertical_1;
> u8 stream_id = mhdp->stream_id;
> - u32 bpp, bpc, pxlfmt, framer;
> + u32 bpp, bpc, pxlfmt, framer, dp_byte_count;
> int ret;
>
> pxlfmt = mhdp->display_fmt.color_format;
> @@ -1716,7 +1906,7 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
> pxlfmt == DRM_COLOR_FORMAT_YCBCR422) && mode->crtc_vdisplay >= 720)
> misc0 = DP_YCBCR_COEFFICIENTS_ITU709;
>
> - bpp = cdns_mhdp_get_bpp(&mhdp->display_fmt);
> + bpp = cdns_mhdp_get_bpp(mhdp);
>
> switch (pxlfmt) {
> case DRM_COLOR_FORMAT_RGB444:
> @@ -1765,6 +1955,9 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
> if (mode->flags & DRM_MODE_FLAG_INTERLACE)
> bnd_hsync2vsync |= CDNS_IP_DET_INTERLACE_FORMAT;
>
> + if (mhdp->dsc_params.compression_enable)
> + bnd_hsync2vsync |= CDNS_IP_VIF_ALIGNMENT_LSB;
> +
> cdns_mhdp_reg_write(mhdp, CDNS_BND_HSYNC2VSYNC(stream_id),
> bnd_hsync2vsync);
>
> @@ -1792,8 +1985,14 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
> CDNS_DP_FRONT_PORCH(front_porch) |
> CDNS_DP_BACK_PORCH(back_porch));
>
> - cdns_mhdp_reg_write(mhdp, CDNS_DP_BYTE_COUNT(stream_id),
> - mode->crtc_hdisplay * bpp / 8);
> + if (mhdp->dsc_params.compression_enable) {
> + dp_byte_count = (((mhdp->dsc_config.slice_chunk_size / mhdp->link.num_lanes) + 1) <<
> + CDNS_DP_BYTE_COUNT_BYTES_IN_CHUNK_SHIFT) |
> + ((mhdp->dsc_config.slice_chunk_size / mhdp->link.num_lanes) + 1);
> + } else {
> + dp_byte_count = (mode->crtc_hdisplay * bpp / 8);
> + }
> + cdns_mhdp_reg_write(mhdp, CDNS_DP_BYTE_COUNT(stream_id), dp_byte_count);
>
> msa_h0 = mode->crtc_htotal - mode->crtc_hsync_start;
> cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_HORIZONTAL_0(stream_id),
> @@ -1852,6 +2051,9 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
> (mode->flags & DRM_MODE_FLAG_INTERLACE) ?
> CDNS_DP_VB_ID_INTERLACED : 0);
>
> + if (mhdp->dsc_params.compression_enable)
> + cdns_mhdp_dsc_set_stream_compressed(mhdp, stream_id, true);
> +
> ret = cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &framer);
> if (ret < 0) {
> dev_err(mhdp->dev,
> @@ -1860,7 +2062,6 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
> return;
> }
> framer |= CDNS_DP_FRAMER_EN;
> - framer &= ~CDNS_DP_NO_VIDEO_MODE;
> cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, framer);
> }
>
> @@ -1869,20 +2070,67 @@ static void cdns_mhdp_sst_enable(struct cdns_mhdp_device *mhdp,
> {
> u32 rate, vs, required_bandwidth, available_bandwidth;
> s32 line_thresh1, line_thresh2, line_thresh = 0;
> - int pxlclock = mode->crtc_clock;
> + int ret, pxlclock = mode->crtc_clock;
> + u32 vs_f, framer, pxl_repr;
> u32 tu_size = 64;
> u32 bpp;
>
> /* Get rate in MSymbols per second per lane */
> rate = mhdp->link.rate / 1000;
>
> - bpp = cdns_mhdp_get_bpp(&mhdp->display_fmt);
> + if (mhdp->fec_enabled) {
> + if (cdns_mhdp_fec_enable(mhdp, true))
> + mhdp->fec_enabled = false;
> + } else {
> + cdns_mhdp_fec_enable(mhdp, false);
> + }
> +
> + if (mhdp->dsc_supported && !cdns_mhdp_dsc_sink_support(mhdp)) {
Should be happening only if FEC is supported and enabled.
> + ret = cdns_mhdp_dsc_reset(mhdp);
> + if (ret)
> + dev_err(mhdp->dev, "DSC reset failed. ret = %d\n", ret);
> +
> + mhdp->dsc_params.compressed_bpp = 8;
> + mhdp->dsc_params.slice_count = 10;
Why is it 10?
> +
> + ret = cdns_mhdp_compute_dsc_params(mhdp);
> + if (ret < 0) {
> + mhdp->dsc_params.compression_enable = false;
> + dev_err(mhdp->dev, "DSC params computation failed. ret = %d\n", ret);
> + } else {
> + mhdp->dsc_params.compression_enable = true;
> + /* Write config for stream 0 */
> + cdns_mhdp_dsc_write_enc_config(mhdp, 0, mode);
> + cdns_mhdp_dsc_update(mhdp, 0);
> + cdns_mhdp_dsc_write_config(mhdp);
> + }
> + } else {
> + if (mhdp->dsc_params.compression_enable) {
> + cdns_mhdp_dsc_sink_enable(mhdp, false);
> + cdns_mhdp_dsc_set_stream_compressed(mhdp, 0, false);
> + }
> + mhdp->dsc_params.compression_enable = false;
> + }
> +
> + /* Enable DSC for stream 0 */
> + if (mhdp->dsc_params.compression_enable) {
> + cdns_mhdp_dsc_enable(mhdp, 0, true);
> +
> + if (cdns_mhdp_dsc_sink_enable(mhdp, true))
> + dev_err(mhdp->dev, "Cannot enable DSC in sink.\n");
> + cdns_mhdp_dsc_send_pps_sdp(mhdp, 0);
> + }
> +
> + bpp = cdns_mhdp_get_bpp(mhdp);
>
> required_bandwidth = pxlclock * bpp / 8;
> available_bandwidth = mhdp->link.num_lanes * rate;
>
> - vs = tu_size * required_bandwidth / available_bandwidth;
> - vs /= 1000;
> + vs_f = tu_size * required_bandwidth / available_bandwidth;
> + if (mhdp->fec_enabled)
> + vs_f = (vs_f * 1024) / 1000; //2.4%
> + vs = vs_f / 1000;
> + vs_f = vs_f % 1000;
>
> if (vs == tu_size)
> vs = tu_size - 1;
> @@ -1907,6 +2155,70 @@ static void cdns_mhdp_sst_enable(struct cdns_mhdp_device *mhdp,
> 0 : tu_size - vs));
>
> cdns_mhdp_configure_video(mhdp, mode);
> +
> + if (mhdp->dsc_params.compression_enable) {
> + cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_PXL_REPR(0), &pxl_repr);
> + pxl_repr &= ~CDNS_DP_FRAMER_PXL_REPR_M;
> + pxl_repr &= ~CDNS_DP_FRAMER_PXL_REPR_DIFF;
> + pxl_repr |= (((vs_f / 10) << CDNS_DP_FRAMER_PXL_REPR_M_SHIFT)
> + & CDNS_DP_FRAMER_PXL_REPR_M) |
> + (((100 - (vs_f / 10)) << CDNS_DP_FRAMER_PXL_REPR_DIFF_SHIFT)
> + & CDNS_DP_FRAMER_PXL_REPR_DIFF);
> + cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_PXL_REPR(0), pxl_repr);
> + }
> +
> + /* Enable video mode */
> + cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &framer);
> + framer &= ~CDNS_DP_NO_VIDEO_MODE;
> + cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, framer);
> +}
> +
> +static int cdns_mhdp_configure_car(struct cdns_mhdp_device *mhdp, bool enable)
> +{
> + u32 dptx_car, source_pkt_car;
> + int ret;
> +
> + ret = cdns_mhdp_reg_read(mhdp, CDNS_DPTX_CAR, &dptx_car);
> + if (ret < 0) {
> + dev_err(mhdp->dev, "Failed to read CDNS_DPTX_CAR %d\n", ret);
> + goto out;
> + }
> +
> + ret = cdns_mhdp_reg_read(mhdp, CDNS_SOURCE_PKT_CAR, &source_pkt_car);
> + if (ret < 0) {
> + dev_err(mhdp->dev, "Failed to read CDNS_SOURCE_PKT_CAR %d\n", ret);
> + goto out;
> + }
> +
> + if (enable) {
> + dev_dbg(mhdp->dev, "%s: Enable clocks for VIF and PIF\n", __func__);
> +
> + /* Enable VIF clock for stream 0 */
> + cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR,
> + dptx_car | CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN);
> +
> + /* Enable PKT clock */
> + cdns_mhdp_reg_write(mhdp, CDNS_SOURCE_PKT_CAR,
> + source_pkt_car | CDNS_PKT_DATA_CLK_EN
> + | CDNS_PKT_DATA_RSTN
> + | CDNS_PKT_SYS_CLK_EN
> + | CDNS_PKT_SYS_RSTN);
> + } else {
> + dev_dbg(mhdp->dev, "%s: Disable clocks for VIF and PIF\n", __func__);
> +
> + /* Disable VIF clock for stream 0 */
> + cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR,
> + dptx_car & ~(CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN));
> +
> + /* Disable PKT clock */
> + cdns_mhdp_reg_write(mhdp, CDNS_SOURCE_PKT_CAR,
> + source_pkt_car & ~(CDNS_PKT_DATA_CLK_EN
> + | CDNS_PKT_DATA_RSTN
> + | CDNS_PKT_SYS_CLK_EN
> + | CDNS_PKT_SYS_RSTN));
> + }
> +out:
> + return ret;
> }
>
> static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge,
> @@ -1919,8 +2231,7 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge,
> struct drm_connector_state *conn_state;
> struct drm_bridge_state *new_state;
> const struct drm_display_mode *mode;
> - u32 resp;
> - int ret;
> + int ret = 0;
>
> dev_dbg(mhdp->dev, "bridge enable\n");
>
> @@ -1935,16 +2246,13 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge,
> if (mhdp->info && mhdp->info->ops && mhdp->info->ops->enable)
> mhdp->info->ops->enable(mhdp);
>
> - /* Enable VIF clock for stream 0 */
> - ret = cdns_mhdp_reg_read(mhdp, CDNS_DPTX_CAR, &resp);
> + /* Enable clocks for video and packet interfaces */
> + ret = cdns_mhdp_configure_car(mhdp, true);
> if (ret < 0) {
> - dev_err(mhdp->dev, "Failed to read CDNS_DPTX_CAR %d\n", ret);
> + dev_err(mhdp->dev, "Failed to enable clocks %d\n", ret);
> goto out;
> }
>
> - cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR,
> - resp | CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN);
> -
> connector = drm_atomic_get_new_connector_for_encoder(state,
> bridge->encoder);
> if (WARN_ON(!connector))
> @@ -2020,10 +2328,8 @@ static void cdns_mhdp_atomic_disable(struct drm_bridge *bridge,
>
> cdns_mhdp_link_down(mhdp);
>
> - /* Disable VIF clock for stream 0 */
> - cdns_mhdp_reg_read(mhdp, CDNS_DPTX_CAR, &resp);
> - cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR,
> - resp & ~(CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN));
> + /* Disable clocks for video and packet interfaces */
> + cdns_mhdp_configure_car(mhdp, false);
>
> if (mhdp->info && mhdp->info->ops && mhdp->info->ops->disable)
> mhdp->info->ops->disable(mhdp);
> @@ -2119,7 +2425,7 @@ static int cdns_mhdp_atomic_check(struct drm_bridge *bridge,
> struct drm_connector_state *conn_state)
> {
> struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge);
> - const struct drm_display_mode *mode = &crtc_state->adjusted_mode;
> + struct drm_display_mode *mode = &crtc_state->adjusted_mode;
>
> mutex_lock(&mhdp->link_mutex);
>
> @@ -2139,6 +2445,10 @@ static int cdns_mhdp_atomic_check(struct drm_bridge *bridge,
> if (mhdp->info)
> bridge_state->input_bus_cfg.flags = *mhdp->info->input_bus_flags;
>
> + //TODO For DSC. Might need proper handling. 1920x1080 mode doesn't work without this.
> + mode->flags |= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
> + mode->flags &= ~(DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC);
> +
> mutex_unlock(&mhdp->link_mutex);
> return 0;
> }
> @@ -2426,6 +2736,15 @@ static int cdns_mhdp_probe(struct platform_device *pdev)
> mhdp->hdcp_supported = true;
> }
>
> + mhdp->dsc_regs = devm_platform_ioremap_resource_byname(pdev, "dsc");
> + if (IS_ERR(mhdp->dsc_regs)) {
> + mhdp->dsc_supported = false;
> + dev_info(dev,
> + "Failed to get DSC memory resource, DSC not supported\n");
> + } else {
> + mhdp->dsc_supported = true;
> + }
> +
> mhdp->phy = devm_of_phy_get_by_index(dev, pdev->dev.of_node, 0);
> if (IS_ERR(mhdp->phy)) {
> dev_err(dev, "no PHY configured\n");
> diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
> index bad2fc0c7306..c8f8071776d7 100644
> --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
> +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
> @@ -16,6 +16,7 @@
> #include <linux/spinlock.h>
>
> #include <drm/display/drm_dp_helper.h>
> +#include <drm/display/drm_dsc.h>
> #include <drm/drm_bridge.h>
> #include <drm/drm_connector.h>
>
> @@ -66,18 +67,30 @@ struct phy;
> #define CDNS_VIF_CLK_EN BIT(0)
> #define CDNS_VIF_CLK_RSTN BIT(1)
>
> +#define CDNS_SOURCE_PKT_CAR 0x00918
> +#define CDNS_PKT_DATA_CLK_EN BIT(0)
> +#define CDNS_PKT_DATA_RSTN BIT(1)
> +#define CDNS_PKT_SYS_CLK_EN BIT(2)
> +#define CDNS_PKT_SYS_RSTN BIT(3)
> +
> #define CDNS_SOURCE_VIDEO_IF(s) (0x00b00 + ((s) * 0x20))
> #define CDNS_BND_HSYNC2VSYNC(s) (CDNS_SOURCE_VIDEO_IF(s) + \
> 0x00)
> #define CDNS_IP_DTCT_WIN GENMASK(11, 0)
> #define CDNS_IP_DET_INTERLACE_FORMAT BIT(12)
> #define CDNS_IP_BYPASS_V_INTERFACE BIT(13)
> +#define CDNS_IP_VIF_ALIGNMENT_LSB BIT(14)
>
> #define CDNS_HSYNC2VSYNC_POL_CTRL(s) (CDNS_SOURCE_VIDEO_IF(s) + \
> 0x10)
> #define CDNS_H2V_HSYNC_POL_ACTIVE_LOW BIT(1)
> #define CDNS_H2V_VSYNC_POL_ACTIVE_LOW BIT(2)
>
> +#define CDNS_DP_DSC_CTRL(s) (CDNS_SOURCE_VIDEO_IF(s) + 0x14)
> +#define CDNS_DP_DSC_CTRL_EN_BIT 0
> +#define CDNS_DP_DSC_CTRL_SW_RST_BIT 1
> +#define CDNS_DP_DSC_CTRL_REG_UPDATE_BIT 2
> +
> #define CDNS_DPTX_PHY_CONFIG 0x02000
> #define CDNS_PHY_TRAINING_EN BIT(0)
> #define CDNS_PHY_TRAINING_TYPE(x) (((x) & GENMASK(3, 0)) << 1)
> @@ -121,6 +134,10 @@ struct phy;
>
> #define CDNS_DP_ENHNCD 0x02304
>
> +#define CDNS_DP_FEC_CTRL 0x02310
> +#define CDNS_DP_FEC_STATUS 0x02314
> +#define CDNS_DP_FEC_BUSY BIT(0)
> +
> #define CDNS_DPTX_STREAM(s) (0x03000 + (s) * 0x80)
> #define CDNS_DP_MSA_HORIZONTAL_0(s) (CDNS_DPTX_STREAM(s) + 0x00)
> #define CDNS_DP_MSAH0_H_TOTAL(x) (x)
> @@ -178,6 +195,10 @@ struct phy;
> #define CDNS_DP_FRAMER_YCBCR422 BIT(2)
> #define CDNS_DP_FRAMER_YCBCR420 BIT(3)
> #define CDNS_DP_FRAMER_Y_ONLY BIT(4)
> +#define CDNS_DP_FRAMER_PXL_REPR_M GENMASK(22, 16)
> +#define CDNS_DP_FRAMER_PXL_REPR_DIFF GENMASK(30, 24)
> +#define CDNS_DP_FRAMER_PXL_REPR_M_SHIFT 16
> +#define CDNS_DP_FRAMER_PXL_REPR_DIFF_SHIFT 24
>
> #define CDNS_DP_FRAMER_SP(s) (CDNS_DPTX_STREAM(s) + 0x50)
> #define CDNS_DP_FRAMER_VSYNC_POL_LOW BIT(0)
> @@ -198,6 +219,38 @@ struct phy;
> #define CDNS_DP_BYTE_COUNT(s) (CDNS_DPTX_STREAM(s) + 0x7c)
> #define CDNS_DP_BYTE_COUNT_BYTES_IN_CHUNK_SHIFT 16
>
> +#define CDNS_SOURCE_PACKET_IF(s) (0x30800 + ((s) * 0x40))
> +#define CDNS_SOURCE_PIF_WR_ADDR(s) (CDNS_SOURCE_PACKET_IF(s) + 0x00)
> +
> +#define CDNS_SOURCE_PIF_WR_REQ(s) (CDNS_SOURCE_PACKET_IF(s) + 0x04)
> +#define SOURCE_PIF_WR_REQ_HOST_WR BIT(0)
> +
> +#define CDNS_SOURCE_PIF_RD_ADDR(s) (CDNS_SOURCE_PACKET_IF(s) + 0x08)
> +#define CDNS_SOURCE_PIF_RD_REQ(s) (CDNS_SOURCE_PACKET_IF(s) + 0x0c)
> +#define CDNS_SOURCE_PIF_DATA_WR(s) (CDNS_SOURCE_PACKET_IF(s) + 0x10)
> +#define CDNS_SOURCE_PIF_DATA_RD(s) (CDNS_SOURCE_PACKET_IF(s) + 0x14)
> +#define CDNS_SOURCE_PIF_FIFO1_FLUSH(s) (CDNS_SOURCE_PACKET_IF(s) + 0x18)
> +#define CDNS_SOURCE_PIF_FIFO2_FLUSH(s) (CDNS_SOURCE_PACKET_IF(s) + 0x1c)
> +#define CDNS_SOURCE_PIF_STATUS(s) (CDNS_SOURCE_PACKET_IF(s) + 0x20)
> +#define CDNS_SOURCE_PIF_INT_SOURCE(s) (CDNS_SOURCE_PACKET_IF(s) + 0x24)
> +#define CDNS_SOURCE_PIF_INT_MASK(s) (CDNS_SOURCE_PACKET_IF(s) + 0x28)
> +
> +#define CDNS_SOURCE_PIF_PKT_ALLOC_REG(s) (CDNS_SOURCE_PACKET_IF(s) + 0x2c)
> +#define SOURCE_PIF_PKT_ALLOC_REG_ACTIVE_IDLE_TYPE BIT(17)
> +#define SOURCE_PIF_PKT_ALLOC_REG_TYPE_VALID BIT(16)
> +#define SOURCE_PIF_PKT_ALLOC_REG_PACKET_TYPE GENMASK(15, 8)
> +#define SOURCE_PIF_PKT_ALLOC_REG_PACKET_TYPE_SHIFT 8
> +#define SOURCE_PIF_PKT_ALLOC_REG_PKT_ALLOC_ADDR GENMASK(3, 0)
> +
> +#define CDNS_SOURCE_PIF_PKT_ALLOC_WR_EN(s) (CDNS_SOURCE_PACKET_IF(s) + 0x30)
> +#define SOURCE_PIF_PKT_ALLOC_WR_EN_EN BIT(0)
> +
> +#define CDNS_SOURCE_PIF_SW_RST(s) (CDNS_SOURCE_PACKET_IF(s) + 0x34)
> +#define CDNS_SOURCE_PIF_PPS_HEADER(s) (CDNS_SOURCE_PACKET_IF(s) + 0x38)
> +
> +#define CDNS_SOURCE_PIF_PPS(s) (CDNS_SOURCE_PACKET_IF(s) + 0x3c)
> +#define SOURCE_PIF_PPS_PPS BIT(0)
> +
> /* mailbox */
> #define MAILBOX_RETRY_US 1000
> #define MAILBOX_TIMEOUT_US 2000000
> @@ -354,6 +407,7 @@ struct cdns_mhdp_hdcp {
> struct cdns_mhdp_device {
> void __iomem *regs;
> void __iomem *sapb_regs;
> + void __iomem *dsc_regs;
> void __iomem *j721e_regs;
>
> struct device *dev;
> @@ -412,6 +466,20 @@ struct cdns_mhdp_device {
>
> struct cdns_mhdp_hdcp hdcp;
> bool hdcp_supported;
> +
> + struct drm_dsc_config dsc_config;
> +
> + /* Display Stream Compression state */
> + bool dsc_supported;
> + struct {
> + bool compression_enable;
> + bool dsc_split;
> + u16 compressed_bpp;
> + u8 slice_count;
> + u8 dsc_cap[DP_DSC_RECEIVER_CAP_SIZE];
> + } dsc_params;
> +
> + bool fec_enabled;
> };
>
> #define connector_to_mhdp(x) container_of(x, struct cdns_mhdp_device, connector)
> diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.c
> new file mode 100644
> index 000000000000..e540e8f2dd4a
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.c
> @@ -0,0 +1,695 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) Cadence Design Systems, Inc.
> + *
> + * Author: Swapnil Jakhade <sjakhade@cadence.com>
> + */
> +
> +#include "cdns-mhdp8546-core.h"
> +#include "cdns-mhdp8546-dsc.h"
> +
> +void cdns_mhdp_dsc_write_config(struct cdns_mhdp_device *mhdp)
> +{
> + u32 main_conf = 0;
> +
> + main_conf = CDNS_DP_COM_MAIN_CONF_INPUT_MODE |
> + CDNS_DP_COM_MAIN_CONF_AUTO_DB_UPDATE;
> +
> + if (mhdp->dsc_params.dsc_split) {
> + main_conf |= CDNS_DP_COM_MAIN_CONF_MUX_MODE |
> + CDNS_DP_COM_MAIN_CONF_SPLIT_PANEL;
> + }
> +
> + writel(main_conf, mhdp->dsc_regs + CDNS_DP_COM_MAIN_CONF);
> +}
> +
> +static u8 cdns_mhdp_dsc_compute_initial_lines(struct cdns_mhdp_device *mhdp)
> +{
> + struct drm_dsc_config *dsc_cfg = &mhdp->dsc_config;
> + unsigned long k1, real_bpp;
> + u8 initial_lines;
> +
> + real_bpp = (unsigned long)dsc_cfg->bits_per_pixel / 16;
> +
> + if (dsc_cfg->bits_per_component == 8)
> + k1 = 296;
> + else
> + k1 = 320;
> +
> + if (mhdp->dsc_params.dsc_split) {
> + initial_lines = (u8)DIV_ROUND_UP
> + ((k1 + (unsigned long)dsc_cfg->initial_xmit_delay +
> + ((((unsigned long)dsc_cfg->slice_chunk_size * 8) + 144) /
> + real_bpp)), (unsigned long)dsc_cfg->slice_width);
> + } else {
> + initial_lines = (u8)DIV_ROUND_UP
> + ((k1 + (unsigned long)dsc_cfg->initial_xmit_delay +
> + ((DIV_ROUND_UP(((1 - (real_bpp / 48)) *
> + ((unsigned long)dsc_cfg->slice_chunk_size * 8)), 1) + 144) /
> + real_bpp)), (unsigned long)dsc_cfg->slice_width);
> + }
Is there a way to make it possible to comprehend?
> +
> + return initial_lines;
> +}
> +
> +static void write_enc_main_conf(struct cdns_mhdp_device *mhdp, int stream_id)
> +{
> + u32 reg_val = 0;
> +
> + if (mhdp->dsc_config.convert_rgb)
> + reg_val |= CDNS_DP_ENC_MAIN_CONF_CONVERT_RGB;
> +
> + reg_val |= (mhdp->dsc_config.line_buf_depth <<
> + CDNS_DP_ENC_MAIN_CONF_LINEBUF_DEPTH_SHIFT) &
> + CDNS_DP_ENC_MAIN_CONF_LINEBUF_DEPTH;
> +
> + reg_val |= (mhdp->dsc_config.bits_per_pixel <<
> + CDNS_DP_ENC_MAIN_CONF_BITS_PER_PIXEL_SHIFT) &
> + CDNS_DP_ENC_MAIN_CONF_BITS_PER_PIXEL;
> +
> + if (mhdp->dsc_config.block_pred_enable)
> + reg_val |= CDNS_DP_ENC_MAIN_CONF_BLOCK_PRED_EN;
> +
> + reg_val |= CDNS_DP_ENC_MAIN_CONF_VIDEO_MODE;
> +
> + reg_val |= (cdns_mhdp_dsc_compute_initial_lines(mhdp) <<
> + CDNS_DP_ENC_MAIN_CONF_INITIAL_LINES_SHIFT) &
> + CDNS_DP_ENC_MAIN_CONF_INITIAL_LINES;
> +
> + if (mhdp->dsc_config.bits_per_component == 10)
> + reg_val |= 0x1;
> + else if (mhdp->dsc_config.bits_per_component != 8)
> + dev_err(mhdp->dev, "Unsupported bits_per_component = %d\n",
> + mhdp->dsc_config.bits_per_component);
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_MAIN_CONF(stream_id));
> +}
> +
> +static void write_enc_picture_size(struct cdns_mhdp_device *mhdp, int stream_id)
> +{
> + u32 reg_val = 0;
> +
> + reg_val = (mhdp->dsc_config.pic_width &
> + CDNS_DP_ENC_PICTURE_SIZE_WIDTH);
> +
> + reg_val |= (mhdp->dsc_config.pic_height <<
> + CDNS_DP_ENC_PICTURE_SIZE_HEIGHT_SHIFT) &
> + CDNS_DP_ENC_PICTURE_SIZE_HEIGHT;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_PICTURE_SIZE(stream_id));
> +}
> +
> +static void write_enc_slice_size(struct cdns_mhdp_device *mhdp, int stream_id)
> +{
> + u32 reg_val = 0;
> +
> + reg_val = (mhdp->dsc_config.slice_width &
> + CDNS_DP_ENC_SLICE_SIZE_WIDTH);
> +
> + reg_val |= (mhdp->dsc_config.slice_height <<
> + CDNS_DP_ENC_SLICE_SIZE_HEIGHT_SHIFT) &
> + CDNS_DP_ENC_SLICE_SIZE_HEIGHT;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_SLICE_SIZE(stream_id));
> +}
> +
> +static void write_enc_misc_size(struct cdns_mhdp_device *mhdp, int stream_id)
> +{
> + u32 reg_val = 0;
> +
> + reg_val = ((mhdp->dsc_config.slice_width + 2) % 3) &
> + CDNS_DP_ENC_MISC_SIZE_LAST_GRP_SIZE;
> +
> + reg_val |= (DSC_OUTPUT_BUFFER_MAX_ADDRESS <<
> + CDNS_DP_ENC_MISC_SIZE_OB_MAX_ADDR_SHIFT) &
> + CDNS_DP_ENC_MISC_SIZE_OB_MAX_ADDR;
> +
> + reg_val |= (mhdp->dsc_config.slice_chunk_size <<
> + CDNS_DP_ENC_MISC_SIZE_CHUNK_SIZE_SHIFT) &
> + CDNS_DP_ENC_MISC_SIZE_CHUNK_SIZE;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_MISC_SIZE(stream_id));
> +}
> +
> +static void write_enc_hrd_delays(struct cdns_mhdp_device *mhdp, int stream_id)
> +{
> + u32 reg_val = 0;
> +
> + reg_val = (mhdp->dsc_config.initial_xmit_delay &
> + CDNS_DP_ENC_HRD_DELAYS_INIT_XMIT_DELAY);
> +
> + reg_val |= (mhdp->dsc_config.initial_dec_delay <<
> + CDNS_DP_ENC_HRD_DELAYS_INIT_DEC_DELAY_SHIFT) &
> + CDNS_DP_ENC_HRD_DELAYS_INIT_DEC_DELAY;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_HRD_DELAYS(stream_id));
> +}
> +
> +static void write_enc_rc_scale(struct cdns_mhdp_device *mhdp, int stream_id)
> +{
> + u32 reg_val = 0;
> +
> + reg_val = (mhdp->dsc_config.initial_scale_value &
> + CDNS_DP_ENC_RC_SCALE_INIT_SCALE_VALUE);
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_SCALE(stream_id));
> +}
> +
> +static void write_enc_rc_scale_inc_dec(struct cdns_mhdp_device *mhdp, int stream_id)
> +{
> + u32 reg_val = 0;
> +
> + reg_val = (mhdp->dsc_config.scale_increment_interval &
> + CDNS_DP_ENC_RC_SCALE_INC_INTERVAL);
> +
> + reg_val |= (mhdp->dsc_config.scale_decrement_interval <<
> + CDNS_DP_ENC_RC_SCALE_DEC_INTERVAL_SHIFT) &
> + CDNS_DP_ENC_RC_SCALE_DEC_INTERVAL;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_SCALE_INC_DEC(stream_id));
> +}
> +
> +static void write_enc_rc_offsets(struct cdns_mhdp_device *mhdp, int stream_id)
> +{
> + u32 reg_val;
> +
> + reg_val = (mhdp->dsc_config.first_line_bpg_offset &
> + CDNS_DP_ENC_RC_OFFSETS_1_FL_BPG_OFFSET);
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_OFFSETS_1(stream_id));
> +
> + reg_val = (mhdp->dsc_config.nfl_bpg_offset &
> + CDNS_DP_ENC_RC_OFFSETS_2_NFL_BPG_OFFSET);
> +
> + reg_val |= (mhdp->dsc_config.slice_bpg_offset <<
> + CDNS_DP_ENC_RC_OFFSETS_2_SL_BPG_OFFSET_SHIFT) &
> + CDNS_DP_ENC_RC_OFFSETS_2_SL_BPG_OFFSET;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_OFFSETS_2(stream_id));
> +
> + reg_val = (mhdp->dsc_config.initial_offset &
> + CDNS_DP_ENC_RC_OFFSETS_3_INIT_OFFSET);
> +
> + reg_val |= (mhdp->dsc_config.final_offset <<
> + CDNS_DP_ENC_RC_OFFSETS_3_FINAL_OFFSET_SHIFT) &
> + CDNS_DP_ENC_RC_OFFSETS_3_FINAL_OFFSET;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_OFFSETS_3(stream_id));
> +}
> +
> +static void write_enc_flatness_detection(struct cdns_mhdp_device *mhdp, int stream_id)
> +{
> + u32 reg_val;
> +
> + reg_val = (mhdp->dsc_config.flatness_min_qp &
> + CDNS_DP_ENC_FLATNESS_DETECTION_MIN_QP);
> +
> + reg_val |= (mhdp->dsc_config.flatness_max_qp <<
> + CDNS_DP_ENC_FLATNESS_DETECTION_MAX_QP_SHIFT) &
> + CDNS_DP_ENC_FLATNESS_DETECTION_MAX_QP;
> +
> + reg_val |= (drm_dsc_flatness_det_thresh(&mhdp->dsc_config) <<
> + CDNS_DP_ENC_FLATNESS_DETECTION_THRESH_SHIFT) &
> + CDNS_DP_ENC_FLATNESS_DETECTION_THRESH;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_FLATNESS_DETECTION(stream_id));
> +}
> +
> +static void write_enc_rc_model_size(struct cdns_mhdp_device *mhdp, int stream_id)
> +{
> + u32 reg_val;
> +
> + reg_val = (mhdp->dsc_config.rc_model_size &
> + CDNS_DP_ENC_RC_MODEL_SIZE_RC_MODEL_SIZE);
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_MODEL_SIZE(stream_id));
> +}
> +
> +static void write_enc_rc_config(struct cdns_mhdp_device *mhdp, int stream_id)
> +{
> + u32 reg_val;
> +
> + reg_val = (mhdp->dsc_config.rc_edge_factor &
> + CDNS_DP_ENC_RC_CONFIG_EDGE_FACTOR);
> +
> + reg_val |= (mhdp->dsc_config.rc_quant_incr_limit0 <<
> + CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_0_SHIFT) &
> + CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_0;
> +
> + reg_val |= (mhdp->dsc_config.rc_quant_incr_limit1 <<
> + CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_1_SHIFT) &
> + CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_1;
> +
> + reg_val |= (mhdp->dsc_config.rc_tgt_offset_high <<
> + CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_HI_SHIFT) &
> + CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_HI;
> +
> + reg_val |= (mhdp->dsc_config.rc_tgt_offset_low <<
> + CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_LO_SHIFT) &
> + CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_LO;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_CONFIG(stream_id));
> +}
> +
> +static void write_enc_rc_buf_thresh(struct cdns_mhdp_device *mhdp, int stream_id)
> +{
> + u32 reg_val;
> + int index = 0;
> +
> + reg_val = (mhdp->dsc_config.rc_buf_thresh[index++] &
> + CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_0);
> +
> + reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
> + CDNS_DP_ENC_RC_BUF_THRESH_THRESH_1_SHIFT) &
> + CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_1;
> +
> + reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
> + CDNS_DP_ENC_RC_BUF_THRESH_THRESH_2_SHIFT) &
> + CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_2;
> +
> + reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
> + CDNS_DP_ENC_RC_BUF_THRESH_THRESH_3_SHIFT) &
> + CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_3;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_BUF_THRESH_0(stream_id));
> +
> + reg_val = (mhdp->dsc_config.rc_buf_thresh[index++] &
> + CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_4);
> +
> + reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
> + CDNS_DP_ENC_RC_BUF_THRESH_THRESH_1_SHIFT) &
> + CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_5;
> +
> + reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
> + CDNS_DP_ENC_RC_BUF_THRESH_THRESH_2_SHIFT) &
> + CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_6;
> +
> + reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
> + CDNS_DP_ENC_RC_BUF_THRESH_THRESH_3_SHIFT) &
> + CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_7;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_BUF_THRESH_1(stream_id));
> +
> + reg_val = (mhdp->dsc_config.rc_buf_thresh[index++] &
> + CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_8);
> +
> + reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
> + CDNS_DP_ENC_RC_BUF_THRESH_THRESH_1_SHIFT) &
> + CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_9;
> +
> + reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
> + CDNS_DP_ENC_RC_BUF_THRESH_THRESH_2_SHIFT) &
> + CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_10;
> +
> + reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
> + CDNS_DP_ENC_RC_BUF_THRESH_THRESH_3_SHIFT) &
> + CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_11;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_BUF_THRESH_2(stream_id));
> +
> + reg_val = (mhdp->dsc_config.rc_buf_thresh[index++] &
> + CDNS_DP_ENC_RC_BUF_THRESH_3_THRESH_12);
> +
> + reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
> + CDNS_DP_ENC_RC_BUF_THRESH_THRESH_1_SHIFT) &
> + CDNS_DP_ENC_RC_BUF_THRESH_3_THRESH_13;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_BUF_THRESH_3(stream_id));
> +}
> +
> +static void write_enc_rc_min_qp(struct cdns_mhdp_device *mhdp, int stream_id)
> +{
> + u32 reg_val;
> + int index = 0;
> +
> + reg_val = (mhdp->dsc_config.rc_range_params[index++].range_min_qp &
> + CDNS_DP_ENC_RC_MIN_QP_0_RANGE_0);
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
> + CDNS_DP_ENC_RC_MIN_QP_0_RANGE_1;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
> + CDNS_DP_ENC_RC_MIN_QP_0_RANGE_2;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
> + CDNS_DP_ENC_RC_MIN_QP_0_RANGE_3;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
> + CDNS_DP_ENC_RC_MIN_QP_0_RANGE_4;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_MIN_QP_0(stream_id));
> +
> + reg_val = (mhdp->dsc_config.rc_range_params[index++].range_min_qp &
> + CDNS_DP_ENC_RC_MIN_QP_1_RANGE_5);
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
> + CDNS_DP_ENC_RC_MIN_QP_1_RANGE_6;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
> + CDNS_DP_ENC_RC_MIN_QP_1_RANGE_7;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
> + CDNS_DP_ENC_RC_MIN_QP_1_RANGE_8;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
> + CDNS_DP_ENC_RC_MIN_QP_1_RANGE_9;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_MIN_QP_1(stream_id));
> +
> + reg_val = (mhdp->dsc_config.rc_range_params[index++].range_min_qp &
> + CDNS_DP_ENC_RC_MIN_QP_2_RANGE_10);
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
> + CDNS_DP_ENC_RC_MIN_QP_2_RANGE_11;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
> + CDNS_DP_ENC_RC_MIN_QP_2_RANGE_12;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
> + CDNS_DP_ENC_RC_MIN_QP_2_RANGE_13;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
> + CDNS_DP_ENC_RC_MIN_QP_2_RANGE_14;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_MIN_QP_2(stream_id));
> +}
> +
> +static void write_enc_rc_max_qp(struct cdns_mhdp_device *mhdp, int stream_id)
> +{
> + u32 reg_val;
> + int index = 0;
> +
> + reg_val = (mhdp->dsc_config.rc_range_params[index++].range_max_qp &
> + CDNS_DP_ENC_RC_MAX_QP_0_RANGE_0);
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
> + CDNS_DP_ENC_RC_MAX_QP_0_RANGE_1;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
> + CDNS_DP_ENC_RC_MAX_QP_0_RANGE_2;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
> + CDNS_DP_ENC_RC_MAX_QP_0_RANGE_3;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
> + CDNS_DP_ENC_RC_MAX_QP_0_RANGE_4;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_MAX_QP_0(stream_id));
> +
> + reg_val = (mhdp->dsc_config.rc_range_params[index++].range_max_qp &
> + CDNS_DP_ENC_RC_MAX_QP_1_RANGE_5);
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
> + CDNS_DP_ENC_RC_MAX_QP_1_RANGE_6;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
> + CDNS_DP_ENC_RC_MAX_QP_1_RANGE_7;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
> + CDNS_DP_ENC_RC_MAX_QP_1_RANGE_8;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
> + CDNS_DP_ENC_RC_MAX_QP_1_RANGE_9;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_MAX_QP_1(stream_id));
> +
> + reg_val = (mhdp->dsc_config.rc_range_params[index++].range_max_qp &
> + CDNS_DP_ENC_RC_MAX_QP_2_RANGE_10);
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
> + CDNS_DP_ENC_RC_MAX_QP_2_RANGE_11;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
> + CDNS_DP_ENC_RC_MAX_QP_2_RANGE_12;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
> + CDNS_DP_ENC_RC_MAX_QP_2_RANGE_13;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
> + CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
> + CDNS_DP_ENC_RC_MAX_QP_2_RANGE_14;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_MAX_QP_2(stream_id));
> +}
> +
> +static void write_enc_rc_range_bpg(struct cdns_mhdp_device *mhdp, int stream_id)
> +{
> + u32 reg_val;
> + int index = 0;
> +
> + reg_val = (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset &
> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_0);
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
> + CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_1;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
> + CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_2;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
> + CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_3;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
> + CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_4;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0(stream_id));
> +
> + reg_val = (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset &
> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_5);
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
> + CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_6;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
> + CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_7;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
> + CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_8;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
> + CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_9;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_1(stream_id));
> +
> + reg_val = (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset &
> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_10);
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
> + CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_11;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
> + CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_12;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
> + CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_13;
> +
> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
> + CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_14;
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_2(stream_id));
> +}
> +
> +static void write_enc_dpi_ctrl(struct cdns_mhdp_device *mhdp, int stream_id,
> + const struct drm_display_mode *mode)
> +{
> + u32 reg_val = 0;
> +
> + reg_val = ((mode->crtc_htotal * cdns_mhdp_dsc_compute_initial_lines(mhdp)) &
> + CDNS_DP_ENC_DPI_CTRL_OUT_DELAY_CYCLES);
> +
> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_DPI_CTRL_OUT_DELAY(stream_id));
> +}
> +
> +void cdns_mhdp_dsc_write_enc_config(struct cdns_mhdp_device *mhdp, int stream_id,
> + const struct drm_display_mode *mode)
> +{
> + write_enc_main_conf(mhdp, stream_id);
> + write_enc_picture_size(mhdp, stream_id);
> + write_enc_slice_size(mhdp, stream_id);
> + write_enc_misc_size(mhdp, stream_id);
> + write_enc_hrd_delays(mhdp, stream_id);
> + write_enc_rc_scale(mhdp, stream_id);
> + write_enc_rc_scale_inc_dec(mhdp, stream_id);
> + write_enc_rc_offsets(mhdp, stream_id);
> + write_enc_flatness_detection(mhdp, stream_id);
> + write_enc_rc_model_size(mhdp, stream_id);
> + write_enc_rc_config(mhdp, stream_id);
> + write_enc_rc_buf_thresh(mhdp, stream_id);
> + write_enc_rc_min_qp(mhdp, stream_id);
> + write_enc_rc_max_qp(mhdp, stream_id);
> + write_enc_rc_range_bpg(mhdp, stream_id);
> + write_enc_dpi_ctrl(mhdp, stream_id, mode);
> +}
> +
> +int cdns_mhdp_dsc_sink_support(struct cdns_mhdp_device *mhdp)
> +{
> + int ret;
> +
> + ret = drm_dp_dpcd_read(&mhdp->aux, DP_DSC_SUPPORT, &mhdp->dsc_params.dsc_cap,
> + DP_DSC_RECEIVER_CAP_SIZE);
> + if (ret != DP_DSC_RECEIVER_CAP_SIZE) {
> + DRM_DEV_ERROR(mhdp->dev, "cannot read sink DSC DPCD: %d\n", ret);
> + goto err;
> + }
> + if (!(mhdp->dsc_params.dsc_cap[0] & DP_DSC_DECOMPRESSION_IS_SUPPORTED)) {
> + ret = -EOPNOTSUPP;
> + DRM_DEV_ERROR(mhdp->dev, "sink does not support DSC: %d\n", ret);
> + goto err;
> + }
> +
> + ret = 0;
> +err:
> + return ret;
> +}
> +
> +int cdns_mhdp_compute_dsc_params(struct cdns_mhdp_device *mhdp)
> +{
> + struct drm_bridge *bridge = &mhdp->bridge;
> + struct drm_dsc_config *dsc_cfg = &mhdp->dsc_config;
> + struct drm_crtc_state *crtc_state = bridge->encoder->crtc->state;
> + u8 *dsc_dpcd = (u8 *)&mhdp->dsc_params.dsc_cap;
> + int ret;
> +
> + dsc_cfg->pic_width = crtc_state->adjusted_mode.crtc_hdisplay;
> + dsc_cfg->pic_height = crtc_state->adjusted_mode.crtc_vdisplay;
> +
> + dsc_cfg->slice_width = dsc_cfg->pic_width;
> + dsc_cfg->slice_height = DIV_ROUND_UP(dsc_cfg->pic_height,
> + mhdp->dsc_params.slice_count);
> +
> + dsc_cfg->dsc_version_major = (dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] &
> + DP_DSC_MAJOR_MASK) >> DP_DSC_MAJOR_SHIFT;
> + dsc_cfg->dsc_version_minor =
> + min(DSC_SUPPORTED_VERSION_MIN,
> + (dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] &
> + DP_DSC_MINOR_MASK) >> DP_DSC_MINOR_SHIFT);
> +
> + dsc_cfg->convert_rgb =
> + dsc_dpcd[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT] & DP_DSC_RGB;
> +
> + dsc_cfg->vbr_enable = false;
> +
> + dsc_cfg->block_pred_enable =
> + dsc_dpcd[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] &
> + DP_DSC_BLK_PREDICTION_IS_SUPPORTED;
> +
> + dsc_cfg->bits_per_pixel = mhdp->dsc_params.compressed_bpp << 4;
> +
> + dsc_cfg->bits_per_component = mhdp->display_fmt.bpc;
> +
> + if (mhdp->dsc_config.bits_per_component == 8)
> + dsc_cfg->line_buf_depth = min(9, drm_dp_dsc_sink_line_buf_depth(dsc_dpcd));
> + else if (mhdp->dsc_config.bits_per_component == 10)
> + dsc_cfg->line_buf_depth = min(11, drm_dp_dsc_sink_line_buf_depth(dsc_dpcd));
> +
> + drm_dsc_set_const_params(dsc_cfg);
> + drm_dsc_set_rc_buf_thresh(dsc_cfg);
> +
> + ret = drm_dsc_setup_rc_params(dsc_cfg, DRM_DSC_1_1_PRE_SCR);
> + if (ret) {
> + dev_err(mhdp->dev, "could not find DSC RC parameters");
> + return ret;
> + }
> +
> + dsc_cfg->initial_scale_value = drm_dsc_initial_scale_value(dsc_cfg);
> + dsc_cfg->slice_count = mhdp->dsc_params.slice_count;
> +
> + return drm_dsc_compute_rc_parameters(dsc_cfg);
> +}
Please consider extracting code common with Intel driver.
> +
> +static void cdns_mhdp_write_data_packet(struct cdns_mhdp_device *mhdp, u32 *buf,
> + int length, int stream_id)
> +{
> + int i;
> + u32 reg_val;
> +
> + for (i = 0; i < length; i++) {
> + reg_val = buf[i];
> + writel(reg_val, mhdp->regs + CDNS_SOURCE_PIF_DATA_WR(stream_id));
> + }
> +}
> +
> +static void cdns_mhdp_write_pps_header(struct cdns_mhdp_device *mhdp, u32 *buf,
> + int stream_id)
> +{
> + writel(SOURCE_PIF_PPS_PPS, mhdp->regs + CDNS_SOURCE_PIF_PPS(stream_id));
> + writel(*buf, mhdp->regs + CDNS_SOURCE_PIF_PPS_HEADER(stream_id));
> +}
> +
> +static int cdns_mhdp_write_pps_infoframe(struct cdns_mhdp_device *mhdp, int stream_id,
> + struct drm_dsc_pps_infoframe *pps_infoframe)
> +{
> + u32 reg_val;
> + u32 entry_id = 0;
> +
> + writel(1, mhdp->regs + CDNS_SOURCE_PIF_FIFO1_FLUSH(stream_id));
> +
> + cdns_mhdp_write_pps_header(mhdp, (u32 *)&pps_infoframe->pps_header, 0);
> + cdns_mhdp_write_data_packet(mhdp, (u32 *)&pps_infoframe->pps_payload,
> + DP_DSC_PPS_SIZE / 4, 0);
sizeof(foo) / 4
> +
> + /* Entry ID */
> + writel(entry_id, mhdp->regs + CDNS_SOURCE_PIF_WR_ADDR(stream_id));
> +
> + writel(SOURCE_PIF_WR_REQ_HOST_WR, mhdp->regs + CDNS_SOURCE_PIF_WR_REQ(stream_id));
> +
> + reg_val = SOURCE_PIF_PKT_ALLOC_REG_ACTIVE_IDLE_TYPE |
> + SOURCE_PIF_PKT_ALLOC_REG_TYPE_VALID |
> + ((DP_SDP_PPS << SOURCE_PIF_PKT_ALLOC_REG_PACKET_TYPE_SHIFT) &
> + SOURCE_PIF_PKT_ALLOC_REG_PACKET_TYPE) |
> + (entry_id & SOURCE_PIF_PKT_ALLOC_REG_PKT_ALLOC_ADDR);
> +
> + writel(reg_val, mhdp->regs + CDNS_SOURCE_PIF_PKT_ALLOC_REG(stream_id));
> +
> + writel
> + (SOURCE_PIF_PKT_ALLOC_WR_EN_EN, mhdp->regs + CDNS_SOURCE_PIF_PKT_ALLOC_WR_EN(stream_id));
Ugh. Newline after comma, please.
> +
> + return 0;
> +}
> +
> +int cdns_mhdp_dsc_send_pps_sdp(struct cdns_mhdp_device *mhdp, int stream_id)
> +{
> + struct drm_dsc_config *dsc_cfg = &mhdp->dsc_config;
> + struct drm_dsc_pps_infoframe dp_dsc_pps_sdp;
> +
> + drm_dsc_dp_pps_header_init(&dp_dsc_pps_sdp.pps_header);
> +
> + drm_dsc_pps_payload_pack(&dp_dsc_pps_sdp.pps_payload, dsc_cfg);
> +
> + return cdns_mhdp_write_pps_infoframe(mhdp, stream_id, &dp_dsc_pps_sdp);
> +}
> diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.h
> new file mode 100644
> index 000000000000..c44d7e3d0002
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.h
> @@ -0,0 +1,285 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) Cadence Design Systems, Inc.
> + *
> + * Author: Swapnil Jakhade <sjakhade@cadence.com>
> + */
> +
> +#ifndef CDNS_MHDP_DSC_H_
> +#define CDNS_MHDP_DSC_H_
> +
> +#include <linux/bitops.h>
> +#include <linux/io.h>
> +#include <linux/minmax.h>
> +#include <drm/display/drm_dsc_helper.h>
> +#include <drm/drm_bridge.h>
> +#include <drm/drm_connector.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_print.h>
Please don't include unnecessary headers through the header file. Use
forward declarations for structs where possible.
> +
> +#define DSC_SUPPORTED_VERSION_MIN 1
> +
> +#define DSC_OUTPUT_BUFFER_MAX_ADDRESS 3667U
> +#define DP_DSC_PPS_SIZE 128
> +
> +#define CDNS_DP_COM_MAIN_CONF 0
> +#define CDNS_DP_COM_MAIN_CONF_SPLIT_PANEL BIT(0)
> +#define CDNS_DP_COM_MAIN_CONF_MUX_MODE BIT(1)
> +#define CDNS_DP_COM_MAIN_CONF_MUX_SEL_OUT BIT(2)
> +#define CDNS_DP_COM_MAIN_CONF_DE_RASTER_EN BIT(3)
> +#define CDNS_DP_COM_MAIN_CONF_INPUT_MODE BIT(4)
> +#define CDNS_DP_COM_MAIN_CONF_MUX_EOC_EN BIT(5)
> +#define CDNS_DP_COM_MAIN_CONF_AUTO_DB_UPDATE BIT(6)
> +
> +#define CDNS_DP_ENC_MAIN_CONF(d) (0x120 + ((d) * 0x100))
> +#define CDNS_DP_ENC_MAIN_CONF_INPUT_BPC GENMASK(1, 0)
> +#define CDNS_DP_ENC_MAIN_CONF_CONVERT_RGB BIT(2)
> +#define CDNS_DP_ENC_MAIN_CONF_ENABLE_422 BIT(3)
> +#define CDNS_DP_ENC_MAIN_CONF_LINEBUF_DEPTH GENMASK(7, 4)
> +#define CDNS_DP_ENC_MAIN_CONF_LINEBUF_DEPTH_SHIFT 4
> +#define CDNS_DP_ENC_MAIN_CONF_BITS_PER_PIXEL GENMASK(17, 8)
> +#define CDNS_DP_ENC_MAIN_CONF_BITS_PER_PIXEL_SHIFT 8
> +#define CDNS_DP_ENC_MAIN_CONF_BLOCK_PRED_EN BIT(18)
> +#define CDNS_DP_ENC_MAIN_CONF_VIDEO_MODE BIT(19)
> +#define CDNS_DP_ENC_MAIN_CONF_ICH_RST_EOL BIT(20)
> +#define CDNS_DP_ENC_MAIN_CONF_INITIAL_LINES GENMASK(31, 24)
> +#define CDNS_DP_ENC_MAIN_CONF_INITIAL_LINES_SHIFT 24
> +
> +#define CDNS_DP_ENC_PICTURE_SIZE(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x4)
> +#define CDNS_DP_ENC_PICTURE_SIZE_HEIGHT GENMASK(31, 16)
> +#define CDNS_DP_ENC_PICTURE_SIZE_HEIGHT_SHIFT 16
> +#define CDNS_DP_ENC_PICTURE_SIZE_WIDTH GENMASK(15, 0)
> +
> +#define CDNS_DP_ENC_SLICE_SIZE(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x8)
> +#define CDNS_DP_ENC_SLICE_SIZE_HEIGHT GENMASK(31, 16)
> +#define CDNS_DP_ENC_SLICE_SIZE_HEIGHT_SHIFT 16
> +#define CDNS_DP_ENC_SLICE_SIZE_WIDTH GENMASK(15, 0)
> +
> +#define CDNS_DP_ENC_MISC_SIZE(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xc)
> +#define CDNS_DP_ENC_MISC_SIZE_CHUNK_SIZE GENMASK(31, 16)
> +#define CDNS_DP_ENC_MISC_SIZE_CHUNK_SIZE_SHIFT 16
> +#define CDNS_DP_ENC_MISC_SIZE_OB_MAX_ADDR GENMASK(15, 2)
> +#define CDNS_DP_ENC_MISC_SIZE_OB_MAX_ADDR_SHIFT 2
> +#define CDNS_DP_ENC_MISC_SIZE_LAST_GRP_SIZE GENMASK(1, 0)
> +
> +#define CDNS_DP_ENC_HRD_DELAYS(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x10)
> +#define CDNS_DP_ENC_HRD_DELAYS_INIT_DEC_DELAY GENMASK(31, 16)
> +#define CDNS_DP_ENC_HRD_DELAYS_INIT_DEC_DELAY_SHIFT 16
> +#define CDNS_DP_ENC_HRD_DELAYS_INIT_XMIT_DELAY GENMASK(9, 0)
> +
> +#define CDNS_DP_ENC_RC_SCALE(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x14)
> +#define CDNS_DP_ENC_RC_SCALE_INIT_SCALE_VALUE GENMASK(5, 0)
> +
> +#define CDNS_DP_ENC_RC_SCALE_INC_DEC(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x18)
> +#define CDNS_DP_ENC_RC_SCALE_DEC_INTERVAL GENMASK(27, 16)
> +#define CDNS_DP_ENC_RC_SCALE_DEC_INTERVAL_SHIFT 16
> +#define CDNS_DP_ENC_RC_SCALE_INC_INTERVAL GENMASK(15, 0)
> +
> +#define CDNS_DP_ENC_RC_OFFSETS_1(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x1c)
> +#define CDNS_DP_ENC_RC_OFFSETS_1_FL_BPG_OFFSET GENMASK(4, 0)
> +
> +#define CDNS_DP_ENC_RC_OFFSETS_2(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x20)
> +#define CDNS_DP_ENC_RC_OFFSETS_2_SL_BPG_OFFSET GENMASK(31, 16)
> +#define CDNS_DP_ENC_RC_OFFSETS_2_SL_BPG_OFFSET_SHIFT 16
> +#define CDNS_DP_ENC_RC_OFFSETS_2_NFL_BPG_OFFSET GENMASK(15, 0)
> +
> +#define CDNS_DP_ENC_RC_OFFSETS_3(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x24)
> +#define CDNS_DP_ENC_RC_OFFSETS_3_FINAL_OFFSET GENMASK(31, 16)
> +#define CDNS_DP_ENC_RC_OFFSETS_3_FINAL_OFFSET_SHIFT 16
> +#define CDNS_DP_ENC_RC_OFFSETS_3_INIT_OFFSET GENMASK(15, 0)
> +
> +#define CDNS_DP_ENC_FLATNESS_DETECTION(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x28)
> +#define CDNS_DP_ENC_FLATNESS_DETECTION_THRESH GENMASK(17, 10)
> +#define CDNS_DP_ENC_FLATNESS_DETECTION_THRESH_SHIFT 10
> +#define CDNS_DP_ENC_FLATNESS_DETECTION_MAX_QP GENMASK(9, 5)
> +#define CDNS_DP_ENC_FLATNESS_DETECTION_MAX_QP_SHIFT 5
> +#define CDNS_DP_ENC_FLATNESS_DETECTION_MIN_QP GENMASK(4, 0)
> +
> +#define CDNS_DP_ENC_RC_MODEL_SIZE(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x2c)
> +#define CDNS_DP_ENC_RC_MODEL_SIZE_RC_MODEL_SIZE GENMASK(15, 0)
> +
> +#define CDNS_DP_ENC_RC_CONFIG(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x30)
> +#define CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_LO GENMASK(27, 24)
> +#define CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_LO_SHIFT 24
> +#define CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_HI GENMASK(23, 20)
> +#define CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_HI_SHIFT 20
> +#define CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_1 GENMASK(17, 13)
> +#define CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_1_SHIFT 13
> +#define CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_0 GENMASK(12, 8)
> +#define CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_0_SHIFT 8
> +#define CDNS_DP_ENC_RC_CONFIG_EDGE_FACTOR GENMASK(3, 0)
> +
> +#define CDNS_DP_ENC_RC_BUF_THRESH_0(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x34)
> +#define CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_3 GENMASK(31, 24)
> +#define CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_2 GENMASK(23, 16)
> +#define CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_1 GENMASK(15, 8)
> +#define CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_0 GENMASK(7, 0)
> +
> +#define CDNS_DP_ENC_RC_BUF_THRESH_1(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x38)
> +#define CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_7 GENMASK(31, 24)
> +#define CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_6 GENMASK(23, 16)
> +#define CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_5 GENMASK(15, 8)
> +#define CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_4 GENMASK(7, 0)
> +
> +#define CDNS_DP_ENC_RC_BUF_THRESH_2(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x3c)
> +#define CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_11 GENMASK(31, 24)
> +#define CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_10 GENMASK(23, 16)
> +#define CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_9 GENMASK(15, 8)
> +#define CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_8 GENMASK(7, 0)
> +
> +#define CDNS_DP_ENC_RC_BUF_THRESH_3(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x40)
> +#define CDNS_DP_ENC_RC_BUF_THRESH_3_THRESH_13 GENMASK(15, 8)
> +#define CDNS_DP_ENC_RC_BUF_THRESH_3_THRESH_12 GENMASK(7, 0)
> +
> +#define CDNS_DP_ENC_RC_BUF_THRESH_THRESH_3_SHIFT 24
> +#define CDNS_DP_ENC_RC_BUF_THRESH_THRESH_2_SHIFT 16
> +#define CDNS_DP_ENC_RC_BUF_THRESH_THRESH_1_SHIFT 8
> +
> +#define CDNS_DP_ENC_RC_MIN_QP_0(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x44)
> +#define CDNS_DP_ENC_RC_MIN_QP_0_RANGE_4 GENMASK(24, 20)
> +#define CDNS_DP_ENC_RC_MIN_QP_0_RANGE_3 GENMASK(19, 15)
> +#define CDNS_DP_ENC_RC_MIN_QP_0_RANGE_2 GENMASK(14, 10)
> +#define CDNS_DP_ENC_RC_MIN_QP_0_RANGE_1 GENMASK(9, 5)
> +#define CDNS_DP_ENC_RC_MIN_QP_0_RANGE_0 GENMASK(4, 0)
> +
> +#define CDNS_DP_ENC_RC_MIN_QP_1(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x48)
> +#define CDNS_DP_ENC_RC_MIN_QP_1_RANGE_9 GENMASK(24, 20)
> +#define CDNS_DP_ENC_RC_MIN_QP_1_RANGE_8 GENMASK(19, 15)
> +#define CDNS_DP_ENC_RC_MIN_QP_1_RANGE_7 GENMASK(14, 10)
> +#define CDNS_DP_ENC_RC_MIN_QP_1_RANGE_6 GENMASK(9, 5)
> +#define CDNS_DP_ENC_RC_MIN_QP_1_RANGE_5 GENMASK(4, 0)
> +
> +#define CDNS_DP_ENC_RC_MIN_QP_2(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x4c)
> +#define CDNS_DP_ENC_RC_MIN_QP_2_RANGE_14 GENMASK(24, 20)
> +#define CDNS_DP_ENC_RC_MIN_QP_2_RANGE_13 GENMASK(19, 15)
> +#define CDNS_DP_ENC_RC_MIN_QP_2_RANGE_12 GENMASK(14, 10)
> +#define CDNS_DP_ENC_RC_MIN_QP_2_RANGE_11 GENMASK(9, 5)
> +#define CDNS_DP_ENC_RC_MIN_QP_2_RANGE_10 GENMASK(4, 0)
> +
> +#define CDNS_DP_ENC_RC_MAX_QP_0(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x50)
> +#define CDNS_DP_ENC_RC_MAX_QP_0_RANGE_4 GENMASK(24, 20)
> +#define CDNS_DP_ENC_RC_MAX_QP_0_RANGE_3 GENMASK(19, 15)
> +#define CDNS_DP_ENC_RC_MAX_QP_0_RANGE_2 GENMASK(14, 10)
> +#define CDNS_DP_ENC_RC_MAX_QP_0_RANGE_1 GENMASK(9, 5)
> +#define CDNS_DP_ENC_RC_MAX_QP_0_RANGE_0 GENMASK(4, 0)
> +
> +#define CDNS_DP_ENC_RC_MAX_QP_1(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x54)
> +#define CDNS_DP_ENC_RC_MAX_QP_1_RANGE_9 GENMASK(24, 20)
> +#define CDNS_DP_ENC_RC_MAX_QP_1_RANGE_8 GENMASK(19, 15)
> +#define CDNS_DP_ENC_RC_MAX_QP_1_RANGE_7 GENMASK(14, 10)
> +#define CDNS_DP_ENC_RC_MAX_QP_1_RANGE_6 GENMASK(9, 5)
> +#define CDNS_DP_ENC_RC_MAX_QP_1_RANGE_5 GENMASK(4, 0)
> +
> +#define CDNS_DP_ENC_RC_MAX_QP_2(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x58)
> +#define CDNS_DP_ENC_RC_MAX_QP_2_RANGE_14 GENMASK(24, 20)
> +#define CDNS_DP_ENC_RC_MAX_QP_2_RANGE_13 GENMASK(19, 15)
> +#define CDNS_DP_ENC_RC_MAX_QP_2_RANGE_12 GENMASK(14, 10)
> +#define CDNS_DP_ENC_RC_MAX_QP_2_RANGE_11 GENMASK(9, 5)
> +#define CDNS_DP_ENC_RC_MAX_QP_2_RANGE_10 GENMASK(4, 0)
> +
> +#define CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT 20
> +#define CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT 15
> +#define CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT 10
> +#define CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT 5
> +
> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x5c)
> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_4 GENMASK(24, 20)
> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_3 GENMASK(19, 15)
> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_2 GENMASK(14, 10)
> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_1 GENMASK(9, 5)
> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_0 GENMASK(4, 0)
> +
> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_1(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x60)
> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_9 GENMASK(24, 20)
> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_8 GENMASK(19, 15)
> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_7 GENMASK(14, 10)
> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_6 GENMASK(9, 5)
> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_5 GENMASK(4, 0)
> +
> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_2(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x64)
> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_14 GENMASK(24, 20)
> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_13 GENMASK(19, 15)
> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_12 GENMASK(14, 10)
> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_11 GENMASK(9, 5)
> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_10 GENMASK(4, 0)
> +
> +#define CDNS_DP_ENC_DPI_CTRL_OUT_DELAY(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x68)
> +#define CDNS_DP_ENC_DPI_CTRL_OUT_DELAY_CYCLES GENMASK(15, 0)
> +
> +#define CDNS_DP_ENC_GENERAL_STATUS(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xa0)
> +#define CDNS_DP_ENC_GENERAL_STATUS_OUT_BUFF_FULL_1 BIT(6)
> +#define CDNS_DP_ENC_GENERAL_STATUS_OUT_BUFF_FULL_0 BIT(5)
> +#define CDNS_DP_ENC_GENERAL_STATUS_OUT_BUFF_EMPTY_1 BIT(4)
> +#define CDNS_DP_ENC_GENERAL_STATUS_OUT_BUFF_EMPTY_0 BIT(3)
> +#define CDNS_DP_ENC_GENERAL_STATUS_FRAME_DONE BIT(2)
> +#define CDNS_DP_ENC_GENERAL_STATUS_FRAME_STARTED BIT(1)
> +#define CDNS_DP_ENC_GENERAL_STATUS_CE BIT(0)
> +
> +#define CDNS_DP_ENC_HSLICE_STATUS(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xa4)
> +#define CDNS_DP_ENC_HSLICE_STATUS_ACTUAL_SLICE GENMASK(31, 16)
> +#define CDNS_DP_ENC_HSLICE_STATUS_ACTUAL_LINE GENMASK(15, 0)
> +
> +#define CDNS_DP_ENC_OUT_STATUS(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xa8)
> +#define CDNS_DP_ENC_OUT_STATUS_ACTUAL_SLICE GENMASK(31, 16)
> +#define CDNS_DP_ENC_OUT_STATUS_ACTUAL_LINE GENMASK(15, 0)
> +
> +#define CDNS_DP_ENC_INT_STAT(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xac)
> +#define CDNS_DP_ENC_INT_STAT_OUT_BUFF_FULL_1 BIT(10)
> +#define CDNS_DP_ENC_INT_STAT_OUT_BUFF_FULL_0 BIT(9)
> +#define CDNS_DP_ENC_INT_STAT_OUT_BUFF_EMPTY_1 BIT(8)
> +#define CDNS_DP_ENC_INT_STAT_OUT_BUFF_EMPTY_0 BIT(7)
> +#define CDNS_DP_ENC_INT_STAT_FRAME_DONE BIT(6)
> +#define CDNS_DP_ENC_INT_STAT_FRAME_STARTED BIT(5)
> +#define CDNS_DP_ENC_INT_STAT_CE BIT(4)
> +#define CDNS_DP_ENC_INT_STAT_RC_BUFF_OVER_1 BIT(3)
> +#define CDNS_DP_ENC_INT_STAT_RC_BUFF_OVER_0 BIT(2)
> +#define CDNS_DP_ENC_INT_STAT_OUT_BUFF_UND_1 BIT(1)
> +#define CDNS_DP_ENC_INT_STAT_OUT_BUFF_UND_0 BIT(0)
> +
> +#define CDNS_DP_ENC_INT_CLR(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xb0)
> +#define CDNS_DP_ENC_INT_CLR_OUT_BUFF_FULL_1 BIT(10)
> +#define CDNS_DP_ENC_INT_CLR_OUT_BUFF_FULL_0 BIT(9)
> +#define CDNS_DP_ENC_INT_CLR_OUT_BUFF_EMPTY_1 BIT(8)
> +#define CDNS_DP_ENC_INT_CLR_OUT_BUFF_EMPTY_0 BIT(7)
> +#define CDNS_DP_ENC_INT_CLR_FRAME_DONE BIT(6)
> +#define CDNS_DP_ENC_INT_CLR_FRAME_STARTED BIT(5)
> +#define CDNS_DP_ENC_INT_CLR_CE BIT(4)
> +#define CDNS_DP_ENC_INT_CLR_RC_BUFF_OVER_1 BIT(3)
> +#define CDNS_DP_ENC_INT_CLR_RC_BUFF_OVER_0 BIT(2)
> +#define CDNS_DP_ENC_INT_CLR_OUT_BUFF_UND_1 BIT(1)
> +#define CDNS_DP_ENC_INT_CLR_OUT_BUFF_UND_0 BIT(0)
> +
> +#define CDNS_DP_ENC_INT_MASK(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xb4)
> +#define CDNS_DP_ENC_INT_MASK_OUT_BUFF_FULL_1 BIT(10)
> +#define CDNS_DP_ENC_INT_MASK_OUT_BUFF_FULL_0 BIT(9)
> +#define CDNS_DP_ENC_INT_MASK_OUT_BUFF_EMPTY_1 BIT(8)
> +#define CDNS_DP_ENC_INT_MASK_OUT_BUFF_EMPTY_0 BIT(7)
> +#define CDNS_DP_ENC_INT_MASK_FRAME_DONE BIT(6)
> +#define CDNS_DP_ENC_INT_MASK_FRAME_STARTED BIT(5)
> +#define CDNS_DP_ENC_INT_MASK_CE BIT(4)
> +#define CDNS_DP_ENC_INT_MASK_RC_BUFF_OVER_1 BIT(3)
> +#define CDNS_DP_ENC_INT_MASK_RC_BUFF_OVER_0 BIT(2)
> +#define CDNS_DP_ENC_INT_MASK_OUT_BUFF_UND_1 BIT(1)
> +#define CDNS_DP_ENC_INT_MASK_OUT_BUFF_UND_0 BIT(0)
> +
> +#define CDNS_DP_ENC_INT_TEST(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xb8)
> +#define CDNS_DP_ENC_INT_TEST_OUT_BUFF_FULL_1 BIT(10)
> +#define CDNS_DP_ENC_INT_TEST_OUT_BUFF_FULL_0 BIT(9)
> +#define CDNS_DP_ENC_INT_TEST_OUT_BUFF_EMPTY_1 BIT(8)
> +#define CDNS_DP_ENC_INT_TEST_OUT_BUFF_EMPTY_0 BIT(7)
> +#define CDNS_DP_ENC_INT_TEST_FRAME_DONE BIT(6)
> +#define CDNS_DP_ENC_INT_TEST_FRAME_STARTED BIT(5)
> +#define CDNS_DP_ENC_INT_TEST_CE BIT(4)
> +#define CDNS_DP_ENC_INT_TEST_RC_BUFF_OVER_1 BIT(3)
> +#define CDNS_DP_ENC_INT_TEST_RC_BUFF_OVER_0 BIT(2)
> +#define CDNS_DP_ENC_INT_TEST_OUT_BUFF_UND_1 BIT(1)
> +#define CDNS_DP_ENC_INT_TEST_OUT_BUFF_UND_0 BIT(0)
> +
> +void cdns_mhdp_dsc_write_config(struct cdns_mhdp_device *mhdp);
> +void cdns_mhdp_dsc_write_enc_config(struct cdns_mhdp_device *mhdp, int stream_id,
> + const struct drm_display_mode *mode);
> +int cdns_mhdp_dsc_sink_support(struct cdns_mhdp_device *mhdp);
> +int cdns_mhdp_compute_dsc_params(struct cdns_mhdp_device *mhdp);
> +int cdns_mhdp_dsc_send_pps_sdp(struct cdns_mhdp_device *mhdp, int stream_id);
> +
> +#endif /* MHDP_DSC_H_ */
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v5 2/2] drm: bridge: cdns-mhdp8546: Add support for DSC and FEC
2025-09-15 11:06 ` Dmitry Baryshkov
@ 2025-09-15 18:53 ` Dmitry Baryshkov
2025-09-30 12:41 ` Harikrishna Shenoy
1 sibling, 0 replies; 9+ messages in thread
From: Dmitry Baryshkov @ 2025-09-15 18:53 UTC (permalink / raw)
To: Harikrishna Shenoy
Cc: andrzej.hajda, neil.armstrong, rfoss, Laurent.pinchart, jonas,
jernej.skrabec, airlied, simona, maarten.lankhorst, mripard,
tzimmermann, robh, krzk+dt, conor+dt, sjakhade, yamonkar, lumag,
dianders, jani.nikula, luca.ceresoli, andy.yan, dri-devel,
devicetree, linux-kernel, devarsht, u-kumar1, s-jain1,
tomi.valkeinen
On Mon, Sep 15, 2025 at 02:06:58PM +0300, Dmitry Baryshkov wrote:
> On Mon, Sep 15, 2025 at 04:00:41PM +0530, Harikrishna Shenoy wrote:
> > From: Swapnil Jakhade <sjakhade@cadence.com>
> >
> > Enable support for Display Stream Compression (DSC) in independent
> > mode with a single stream, along with Forward Error Correction (FEC)
> > in the Cadence MHDP8546 DisplayPort controller driver.
> >
> > FEC is required when DSC is enabled to ensure reliable transmission
> > of the compressed stream.
> >
> > Signed-off-by: Swapnil Jakhade <sjakhade@cadence.com>
> > Signed-off-by: Harikrishna Shenoy <h-shenoy@ti.com>
> > ---
> > drivers/gpu/drm/bridge/cadence/Makefile | 2 +-
> > .../drm/bridge/cadence/cdns-mhdp8546-core.c | 367 ++++++++-
> > .../drm/bridge/cadence/cdns-mhdp8546-core.h | 68 ++
> > .../drm/bridge/cadence/cdns-mhdp8546-dsc.c | 695 ++++++++++++++++++
> > .../drm/bridge/cadence/cdns-mhdp8546-dsc.h | 285 +++++++
> > 5 files changed, 1392 insertions(+), 25 deletions(-)
> > create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.c
> > create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.h
> >
> > + goto err;
> > + }
> > +
> > + if (ret > 0)
> > + return 0;
> > +err:
> > + return ret;
> > +}
>
> Consider extracting a common helper and using it here and in the Intel
> DP driver. Also please use new DPCD helpers which return 0 instead of
> size.
For the reference, some time ago one of my colleagues implemented DP DSC
support for the drm/msm driver. It didn't go in for multiple reasons,
but feel free to use it as an inspiration for possible generic helpers.
See https://patchwork.freedesktop.org/series/113240/
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v5 1/2] dt-bindings: drm/bridge: MHDP8546 bridge binding changes for DSC
2025-09-15 10:30 ` [PATCH v5 1/2] dt-bindings: drm/bridge: MHDP8546 bridge binding changes for DSC Harikrishna Shenoy
@ 2025-09-18 1:30 ` Krzysztof Kozlowski
[not found] ` <d2367789-6b54-4fc2-bb7c-609c0fe084d3@ti.com>
0 siblings, 1 reply; 9+ messages in thread
From: Krzysztof Kozlowski @ 2025-09-18 1:30 UTC (permalink / raw)
To: Harikrishna Shenoy
Cc: andrzej.hajda, neil.armstrong, rfoss, Laurent.pinchart, jonas,
jernej.skrabec, airlied, simona, maarten.lankhorst, mripard,
tzimmermann, robh, krzk+dt, conor+dt, sjakhade, yamonkar, lumag,
dianders, jani.nikula, luca.ceresoli, andy.yan, dri-devel,
devicetree, linux-kernel, devarsht, u-kumar1, s-jain1,
tomi.valkeinen
On Mon, Sep 15, 2025 at 04:00:40PM +0530, Harikrishna Shenoy wrote:
> From: Swapnil Jakhade <sjakhade@cadence.com>
>
> Add binding changes for DSC(Display Stream Compression) in the MHDP8546
> DPI/DP bridge.
>
> Signed-off-by: Swapnil Jakhade <sjakhade@cadence.com>
> Signed-off-by: Harikrishna Shenoy <h-shenoy@ti.com>
> ---
> .../display/bridge/cdns,mhdp8546.yaml | 24 ++++++++++++-------
> 1 file changed, 15 insertions(+), 9 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8546.yaml b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8546.yaml
> index c2b369456e4e..2a05a7d5847f 100644
> --- a/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8546.yaml
> +++ b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8546.yaml
> @@ -27,13 +27,12 @@ properties:
> Register block for DSS_EDP0_INTG_CFG_VP registers in case of TI J7 SoCs.
> - description:
> Register block of mhdptx sapb registers.
> + - description:
> + Register block for mhdptx DSC encoder registers.
>
> reg-names:
> - minItems: 1
> - items:
> - - const: mhdptx
> - - const: j721e-intg
> - - const: mhdptx-sapb
> + description:
> + Names corresponding to entries in the reg property.
No, top-level should have broadest constraints. In your case it is
min/maxItems.
Description is completely redundant. Wasn't here before, so why adding
it?
>
> clocks:
> maxItems: 1
> @@ -100,18 +99,25 @@ allOf:
> properties:
> reg:
> minItems: 2
> - maxItems: 3
> + maxItems: 4
> reg-names:
> minItems: 2
> - maxItems: 3
> + items:
> + - const: mhdptx
> + - const: j721e-intg
> + - const: mhdptx-sapb
> + - const: dsc
> else:
> properties:
> reg:
> minItems: 1
> - maxItems: 2
> + maxItems: 3
> reg-names:
> minItems: 1
> - maxItems: 2
> + items:
> + - const: mhdptx
> + - const: mhdptx-sapb
This is wrong. Previously CDNS variant had two items means it had
"j721e-intg". Now it's something else.
First, this is an ABI break.
Second, there is no explanation at all for it in the commit msg! Looks
like random change.
Read carefully writing-bindings doc.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v5 2/2] drm: bridge: cdns-mhdp8546: Add support for DSC and FEC
2025-09-15 10:30 ` [PATCH v5 2/2] drm: bridge: cdns-mhdp8546: Add support for DSC and FEC Harikrishna Shenoy
2025-09-15 11:06 ` Dmitry Baryshkov
@ 2025-09-19 19:38 ` kernel test robot
1 sibling, 0 replies; 9+ messages in thread
From: kernel test robot @ 2025-09-19 19:38 UTC (permalink / raw)
To: Harikrishna Shenoy, andrzej.hajda, neil.armstrong, rfoss,
Laurent.pinchart, jonas, jernej.skrabec, airlied, simona,
maarten.lankhorst, mripard, tzimmermann, robh, krzk+dt, conor+dt,
sjakhade, yamonkar, lumag, dianders, jani.nikula, luca.ceresoli,
andy.yan, dri-devel, devicetree, linux-kernel, devarsht, u-kumar1,
s-jain1, tomi.valkeinen
Cc: oe-kbuild-all, h-shenoy
Hi Harikrishna,
kernel test robot noticed the following build errors:
[auto build test ERROR on robh/for-next]
[also build test ERROR on drm-misc/drm-misc-next linus/master v6.17-rc6 next-20250919]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Harikrishna-Shenoy/dt-bindings-drm-bridge-MHDP8546-bridge-binding-changes-for-DSC/20250915-183321
base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
patch link: https://lore.kernel.org/r/20250915103041.3891448-3-h-shenoy%40ti.com
patch subject: [PATCH v5 2/2] drm: bridge: cdns-mhdp8546: Add support for DSC and FEC
config: arm64-randconfig-002-20250919 (https://download.01.org/0day-ci/archive/20250920/202509200323.OEAahLBT-lkp@intel.com/config)
compiler: aarch64-linux-gcc (GCC) 8.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250920/202509200323.OEAahLBT-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202509200323.OEAahLBT-lkp@intel.com/
All errors (new ones prefixed by >>):
aarch64-linux-ld: Unexpected GOT/PLT entries detected!
aarch64-linux-ld: Unexpected run-time procedure linkages detected!
aarch64-linux-ld: drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.o: in function `cdns_mhdp_dsc_write_enc_config':
>> cdns-mhdp8546-dsc.c:(.text+0x2f0): undefined reference to `drm_dsc_flatness_det_thresh'
aarch64-linux-ld: drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.o: in function `cdns_mhdp_compute_dsc_params':
>> cdns-mhdp8546-dsc.c:(.text+0x91c): undefined reference to `drm_dsc_set_const_params'
>> aarch64-linux-ld: cdns-mhdp8546-dsc.c:(.text+0x924): undefined reference to `drm_dsc_set_rc_buf_thresh'
>> aarch64-linux-ld: cdns-mhdp8546-dsc.c:(.text+0x930): undefined reference to `drm_dsc_setup_rc_params'
>> aarch64-linux-ld: cdns-mhdp8546-dsc.c:(.text+0x940): undefined reference to `drm_dsc_initial_scale_value'
>> aarch64-linux-ld: cdns-mhdp8546-dsc.c:(.text+0x954): undefined reference to `drm_dsc_compute_rc_parameters'
aarch64-linux-ld: drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.o: in function `cdns_mhdp_dsc_send_pps_sdp':
>> cdns-mhdp8546-dsc.c:(.text+0xa44): undefined reference to `drm_dsc_dp_pps_header_init'
>> aarch64-linux-ld: cdns-mhdp8546-dsc.c:(.text+0xa54): undefined reference to `drm_dsc_pps_payload_pack'
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v5 2/2] drm: bridge: cdns-mhdp8546: Add support for DSC and FEC
2025-09-15 11:06 ` Dmitry Baryshkov
2025-09-15 18:53 ` Dmitry Baryshkov
@ 2025-09-30 12:41 ` Harikrishna Shenoy
1 sibling, 0 replies; 9+ messages in thread
From: Harikrishna Shenoy @ 2025-09-30 12:41 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: andrzej.hajda, neil.armstrong, rfoss, Laurent.pinchart, jonas,
jernej.skrabec, airlied, simona, maarten.lankhorst, mripard,
tzimmermann, robh, krzk+dt, conor+dt, sjakhade, yamonkar, lumag,
dianders, jani.nikula, luca.ceresoli, andy.yan, dri-devel,
devicetree, linux-kernel, devarsht, u-kumar1, s-jain1,
tomi.valkeinen
On 9/15/25 16:36, Dmitry Baryshkov wrote:
> On Mon, Sep 15, 2025 at 04:00:41PM +0530, Harikrishna Shenoy wrote:
>> From: Swapnil Jakhade <sjakhade@cadence.com>
>>
>> Enable support for Display Stream Compression (DSC) in independent
>> mode with a single stream, along with Forward Error Correction (FEC)
>> in the Cadence MHDP8546 DisplayPort controller driver.
>>
>> FEC is required when DSC is enabled to ensure reliable transmission
>> of the compressed stream.
>>
>> Signed-off-by: Swapnil Jakhade <sjakhade@cadence.com>
>> Signed-off-by: Harikrishna Shenoy <h-shenoy@ti.com>
>> ---
>> drivers/gpu/drm/bridge/cadence/Makefile | 2 +-
>> .../drm/bridge/cadence/cdns-mhdp8546-core.c | 367 ++++++++-
>> .../drm/bridge/cadence/cdns-mhdp8546-core.h | 68 ++
>> .../drm/bridge/cadence/cdns-mhdp8546-dsc.c | 695 ++++++++++++++++++
>> .../drm/bridge/cadence/cdns-mhdp8546-dsc.h | 285 +++++++
>> 5 files changed, 1392 insertions(+), 25 deletions(-)
>> create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.c
>> create mode 100644 drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.h
>>
>> diff --git a/drivers/gpu/drm/bridge/cadence/Makefile b/drivers/gpu/drm/bridge/cadence/Makefile
>> index c95fd5b81d13..7957fbdc1b78 100644
>> --- a/drivers/gpu/drm/bridge/cadence/Makefile
>> +++ b/drivers/gpu/drm/bridge/cadence/Makefile
>> @@ -3,5 +3,5 @@ obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o
>> cdns-dsi-y := cdns-dsi-core.o
>> cdns-dsi-$(CONFIG_DRM_CDNS_DSI_J721E) += cdns-dsi-j721e.o
>> obj-$(CONFIG_DRM_CDNS_MHDP8546) += cdns-mhdp8546.o
>> -cdns-mhdp8546-y := cdns-mhdp8546-core.o cdns-mhdp8546-hdcp.o
>> +cdns-mhdp8546-y := cdns-mhdp8546-core.o cdns-mhdp8546-hdcp.o cdns-mhdp8546-dsc.o
>> cdns-mhdp8546-$(CONFIG_DRM_CDNS_MHDP8546_J721E) += cdns-mhdp8546-j721e.o
>> diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
>> index a614d1384f71..df8bbf8919b2 100644
>> --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
>> +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
>> @@ -50,6 +50,7 @@
>> #include <linux/unaligned.h>
>>
>> #include "cdns-mhdp8546-core.h"
>> +#include "cdns-mhdp8546-dsc.h"
>> #include "cdns-mhdp8546-hdcp.h"
>> #include "cdns-mhdp8546-j721e.h"
>>
>> @@ -545,6 +546,116 @@ int cdns_mhdp_adjust_lt(struct cdns_mhdp_device *mhdp, unsigned int nlanes,
>> return ret;
>> }
>>
>> +static int cdns_mhdp_wait_for_fec(struct cdns_mhdp_device *mhdp,
>> + bool expected_status)
>> +{
>> + u32 fec_status;
>> + unsigned long timeout = jiffies + msecs_to_jiffies(1000);
>> +
>> + cdns_mhdp_reg_read(mhdp, CDNS_DP_FEC_STATUS, &fec_status);
>> + while (((fec_status & CDNS_DP_FEC_BUSY) != expected_status) &&
>> + time_before(jiffies, timeout)) {
>> + cdns_mhdp_reg_read(mhdp, CDNS_DP_FEC_STATUS, &fec_status);
>> + cpu_relax();
>> + }
>> +
>> + if (time_after_eq(jiffies, timeout)) {
>> + DRM_DEV_ERROR(mhdp->dev, "Timeout while waiting for FEC\n");
>> + return -ETIMEDOUT;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int cdns_mhdp_fec_sink_support(struct cdns_mhdp_device *mhdp)
>> +{
>> + int ret;
>> + u16 dpcd_buffer;
>> +
>> + ret = drm_dp_dpcd_read(&mhdp->aux, DP_FEC_CAPABILITY, &dpcd_buffer, 1);
>> + if (ret < 0)
>> + goto err;
> Only since DP 1.4 if I'm not mistaken.
will add the check for DP version>= 1.4.
>> +
>> + if (!(dpcd_buffer & DP_FEC_CAPABLE)) {
>> + ret = -EOPNOTSUPP;
>> + DRM_DEV_ERROR(mhdp->dev, "sink does not support FEC: %d\n", ret);
> This is too loud.
will reduce the level.
>
>> + goto err;
>> + }
>> +
>> + if (ret > 0)
>> + return 0;
>> +err:
>> + return ret;
>> +}
> Consider extracting a common helper and using it here and in the Intel
> DP driver. Also please use new DPCD helpers which return 0 instead of
> size.
>
will use dpcd_helpers which return 0 instead of number of bytes read
and check if anything can be extracted to drm dsc helpers I assume?
>> +
>> +static int cdns_mhdp_fec_sink_set_ready(struct cdns_mhdp_device *mhdp,
>> + bool enable)
>> +{
>> + int ret;
>> + u8 dpcd_buffer;
>> +
>> + ret = drm_dp_dpcd_read(&mhdp->aux, DP_FEC_CONFIGURATION, &dpcd_buffer, 1);
>> + if (ret < 0)
>> + goto err;
> No need to read it back, it's controlled by DPTX and you don't set
> anything else.
ok, will do the changes here.
>> +
>> + if (enable)
>> + dpcd_buffer |= DP_FEC_READY;
>> + else
>> + dpcd_buffer &= ~DP_FEC_READY;
>> +
>> + ret = drm_dp_dpcd_write(&mhdp->aux, DP_FEC_CONFIGURATION, &dpcd_buffer, 1);
>> +
>> + if (ret > 0)
>> + return 0;
>> +err:
>> + DRM_DEV_ERROR(mhdp->dev, "cannot set sink FEC ready: %d\n", ret);
>> + return ret;
>> +}
>> +
>> +static int cdns_mhdp_fec_set_ready(struct cdns_mhdp_device *mhdp, bool enable)
>> +{
>> + int ret;
>> +
>> + ret = cdns_mhdp_fec_sink_support(mhdp);
>> + if (ret)
>> + goto err;
>> +
>> + ret = cdns_mhdp_fec_sink_set_ready(mhdp, enable);
>> + if (ret)
>> + goto err;
>> +
>> + ret = cdns_mhdp_reg_write_bit(mhdp, CDNS_DP_FEC_CTRL, 1, 1, enable);
>> + if (ret)
>> + goto err;
>> +
>> +err:
>> + return ret;
>> +}
>> +
>> +static int cdns_mhdp_fec_enable(struct cdns_mhdp_device *mhdp, bool enable)
>> +{
>> + int ret;
>> + u32 resp;
>> +
>> + ret = cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &resp);
>> + if (ret < 0)
>> + goto err;
>> +
>> + if (!(resp & CDNS_DP_NO_VIDEO_MODE)) {
>> + ret = -EIO;
>> + goto err;
>> + }
>> +
>> + ret = cdns_mhdp_reg_write_bit(mhdp, CDNS_DP_FEC_CTRL, 0, 1, enable);
>> + if (ret)
>> + goto err;
>> +
>> + return cdns_mhdp_wait_for_fec(mhdp, enable);
>> +err:
>> + DRM_DEV_ERROR(mhdp->dev, "set fec enable failed: %d\n", ret);
>> + return ret;
>> +}
>> +
>> /**
>> * cdns_mhdp_link_configure() - configure a DisplayPort link
>> * @aux: DisplayPort AUX channel
>> @@ -1407,6 +1518,13 @@ static int cdns_mhdp_link_up(struct cdns_mhdp_device *mhdp)
>> amp[1] = DP_SET_ANSI_8B10B;
>> drm_dp_dpcd_write(&mhdp->aux, DP_DOWNSPREAD_CTRL, amp, 2);
>>
>> + if (cdns_mhdp_fec_set_ready(mhdp, true)) {
>> + mhdp->fec_enabled = false;
>> + dev_info(mhdp->dev, "Cannot set FEC ready.\n");
> If DPRX doesn't support FEC, we've just got several messages for no
> particular reason. It's an optional feature.
will reduce the logging level.
>> + } else {
>> + mhdp->fec_enabled = true;
>> + }
>> +
>> if (mhdp->host.fast_link & mhdp->sink.fast_link) {
>> dev_err(mhdp->dev, "fastlink not supported\n");
>> return -EOPNOTSUPP;
>> @@ -1494,10 +1612,14 @@ static int cdns_mhdp_connector_detect(struct drm_connector *conn,
>> return cdns_mhdp_detect(mhdp);
>> }
>>
>> -static u32 cdns_mhdp_get_bpp(struct cdns_mhdp_display_fmt *fmt)
>> +static u32 cdns_mhdp_get_bpp(struct cdns_mhdp_device *mhdp)
>> {
>> + struct cdns_mhdp_display_fmt *fmt = &mhdp->display_fmt;
>> u32 bpp;
>>
>> + if (mhdp->dsc_params.compression_enable)
>> + return mhdp->dsc_params.compressed_bpp;
>> +
>> if (fmt->y_only)
>> return fmt->bpc;
>>
>> @@ -1533,7 +1655,7 @@ bool cdns_mhdp_bandwidth_ok(struct cdns_mhdp_device *mhdp,
>> * units of the rate parameter.
>> */
>>
>> - bpp = cdns_mhdp_get_bpp(&mhdp->display_fmt);
>> + bpp = cdns_mhdp_get_bpp(mhdp);
>> req_bw = mode->clock * bpp / 8;
>> max_bw = lanes * rate;
>> if (req_bw > max_bw) {
>> @@ -1693,6 +1815,74 @@ static int cdns_mhdp_attach(struct drm_bridge *bridge,
>> return ret;
>> }
>>
>> +static int cdns_mhdp_dsc_set_stream_compressed(struct cdns_mhdp_device *mhdp,
>> + int stream_id, bool compressed)
>> +{
>> + u32 reg_val;
>> + int ret;
>> +
>> + ret = cdns_mhdp_reg_read(mhdp, CDNS_DP_VB_ID(stream_id), ®_val);
>> + if (ret < 0)
>> + return ret;
>> +
>> + if (compressed)
>> + reg_val |= CDNS_DP_VB_ID_COMPRESSED;
>> + else
>> + reg_val &= ~CDNS_DP_VB_ID_COMPRESSED;
>> +
>> + return cdns_mhdp_reg_write(mhdp, CDNS_DP_VB_ID(stream_id), reg_val);
>> +}
>> +
>> +static int cdns_mhdp_dsc_wait_for_completion(struct cdns_mhdp_device *mhdp,
>> + u8 event_bit, int stream_id)
>> +{
>> + u32 dsc_ctrl;
>> + int ret;
>> + unsigned long timeout;
>> +
>> + ret = cdns_mhdp_reg_write_bit(mhdp, CDNS_DP_DSC_CTRL(stream_id),
>> + event_bit, 1, true);
>> + if (ret)
>> + return ret;
>> +
>> + timeout = jiffies + msecs_to_jiffies(1000);
>> +
>> + do {
>> + cdns_mhdp_reg_read(mhdp, CDNS_DP_DSC_CTRL(stream_id), &dsc_ctrl);
>> + cpu_relax();
>> + } while (((dsc_ctrl & (1 << event_bit)) != 0) && time_before(jiffies, timeout));
>> +
>> + if (time_after_eq(jiffies, timeout)) {
>> + DRM_DEV_ERROR(mhdp->dev, "Timeout while waiting for event %d\n", event_bit);
>> + return -ETIMEDOUT;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int cdns_mhdp_dsc_reset(struct cdns_mhdp_device *mhdp)
>> +{
>> + /* Setting reset bit in any stream resets entire DSC. Stream 0 may always be used for it. */
>> + return cdns_mhdp_dsc_wait_for_completion(mhdp, CDNS_DP_DSC_CTRL_SW_RST_BIT, 0);
>> +}
>> +
>> +static int cdns_mhdp_dsc_update(struct cdns_mhdp_device *mhdp, int stream_id)
>> +{
>> + return cdns_mhdp_dsc_wait_for_completion(mhdp, CDNS_DP_DSC_CTRL_REG_UPDATE_BIT,
>> + stream_id);
>> +}
>> +
>> +static int cdns_mhdp_dsc_enable(struct cdns_mhdp_device *mhdp, int stream_id, bool enable)
>> +{
>> + return cdns_mhdp_reg_write_bit(mhdp, CDNS_DP_DSC_CTRL(stream_id),
>> + CDNS_DP_DSC_CTRL_EN_BIT, 1, enable ? 1 : 0);
>> +}
>> +
>> +static int cdns_mhdp_dsc_sink_enable(struct cdns_mhdp_device *mhdp, bool enable)
>> +{
>> + return drm_dp_dpcd_writeb(&mhdp->aux, DP_DSC_ENABLE, enable) != 1;
>> +}
>> +
>> static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
>> const struct drm_display_mode *mode)
>> {
>> @@ -1702,7 +1892,7 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
>> front_porch, back_porch, msa_h0, msa_v0, hsync, vsync,
>> dp_vertical_1;
>> u8 stream_id = mhdp->stream_id;
>> - u32 bpp, bpc, pxlfmt, framer;
>> + u32 bpp, bpc, pxlfmt, framer, dp_byte_count;
>> int ret;
>>
>> pxlfmt = mhdp->display_fmt.color_format;
>> @@ -1716,7 +1906,7 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
>> pxlfmt == DRM_COLOR_FORMAT_YCBCR422) && mode->crtc_vdisplay >= 720)
>> misc0 = DP_YCBCR_COEFFICIENTS_ITU709;
>>
>> - bpp = cdns_mhdp_get_bpp(&mhdp->display_fmt);
>> + bpp = cdns_mhdp_get_bpp(mhdp);
>>
>> switch (pxlfmt) {
>> case DRM_COLOR_FORMAT_RGB444:
>> @@ -1765,6 +1955,9 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
>> if (mode->flags & DRM_MODE_FLAG_INTERLACE)
>> bnd_hsync2vsync |= CDNS_IP_DET_INTERLACE_FORMAT;
>>
>> + if (mhdp->dsc_params.compression_enable)
>> + bnd_hsync2vsync |= CDNS_IP_VIF_ALIGNMENT_LSB;
>> +
>> cdns_mhdp_reg_write(mhdp, CDNS_BND_HSYNC2VSYNC(stream_id),
>> bnd_hsync2vsync);
>>
>> @@ -1792,8 +1985,14 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
>> CDNS_DP_FRONT_PORCH(front_porch) |
>> CDNS_DP_BACK_PORCH(back_porch));
>>
>> - cdns_mhdp_reg_write(mhdp, CDNS_DP_BYTE_COUNT(stream_id),
>> - mode->crtc_hdisplay * bpp / 8);
>> + if (mhdp->dsc_params.compression_enable) {
>> + dp_byte_count = (((mhdp->dsc_config.slice_chunk_size / mhdp->link.num_lanes) + 1) <<
>> + CDNS_DP_BYTE_COUNT_BYTES_IN_CHUNK_SHIFT) |
>> + ((mhdp->dsc_config.slice_chunk_size / mhdp->link.num_lanes) + 1);
>> + } else {
>> + dp_byte_count = (mode->crtc_hdisplay * bpp / 8);
>> + }
>> + cdns_mhdp_reg_write(mhdp, CDNS_DP_BYTE_COUNT(stream_id), dp_byte_count);
>>
>> msa_h0 = mode->crtc_htotal - mode->crtc_hsync_start;
>> cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_HORIZONTAL_0(stream_id),
>> @@ -1852,6 +2051,9 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
>> (mode->flags & DRM_MODE_FLAG_INTERLACE) ?
>> CDNS_DP_VB_ID_INTERLACED : 0);
>>
>> + if (mhdp->dsc_params.compression_enable)
>> + cdns_mhdp_dsc_set_stream_compressed(mhdp, stream_id, true);
>> +
>> ret = cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &framer);
>> if (ret < 0) {
>> dev_err(mhdp->dev,
>> @@ -1860,7 +2062,6 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
>> return;
>> }
>> framer |= CDNS_DP_FRAMER_EN;
>> - framer &= ~CDNS_DP_NO_VIDEO_MODE;
>> cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, framer);
>> }
>>
>> @@ -1869,20 +2070,67 @@ static void cdns_mhdp_sst_enable(struct cdns_mhdp_device *mhdp,
>> {
>> u32 rate, vs, required_bandwidth, available_bandwidth;
>> s32 line_thresh1, line_thresh2, line_thresh = 0;
>> - int pxlclock = mode->crtc_clock;
>> + int ret, pxlclock = mode->crtc_clock;
>> + u32 vs_f, framer, pxl_repr;
>> u32 tu_size = 64;
>> u32 bpp;
>>
>> /* Get rate in MSymbols per second per lane */
>> rate = mhdp->link.rate / 1000;
>>
>> - bpp = cdns_mhdp_get_bpp(&mhdp->display_fmt);
>> + if (mhdp->fec_enabled) {
>> + if (cdns_mhdp_fec_enable(mhdp, true))
>> + mhdp->fec_enabled = false;
>> + } else {
>> + cdns_mhdp_fec_enable(mhdp, false);
>> + }
>> +
>> + if (mhdp->dsc_supported && !cdns_mhdp_dsc_sink_support(mhdp)) {
> Should be happening only if FEC is supported and enabled.
yes, will change to enable DSC only when FEC is supported and enabled.
>
>> + ret = cdns_mhdp_dsc_reset(mhdp);
>> + if (ret)
>> + dev_err(mhdp->dev, "DSC reset failed. ret = %d\n", ret);
>> +
>> + mhdp->dsc_params.compressed_bpp = 8;
>> + mhdp->dsc_params.slice_count = 10;
> Why is it 10?
for DSC independent mode, there is a requirement to use 1 slice per line.
Basically, any value greater than or equal to 1 for slice_count should
be supported.
will check with some values and make changes if required, but not any
specific
reason for 10.
>
>> +
>> + ret = cdns_mhdp_compute_dsc_params(mhdp);
>> + if (ret < 0) {
>> + mhdp->dsc_params.compression_enable = false;
>> + dev_err(mhdp->dev, "DSC params computation failed. ret = %d\n", ret);
>> + } else {
>> + mhdp->dsc_params.compression_enable = true;
>> + /* Write config for stream 0 */
>> + cdns_mhdp_dsc_write_enc_config(mhdp, 0, mode);
>> + cdns_mhdp_dsc_update(mhdp, 0);
>> + cdns_mhdp_dsc_write_config(mhdp);
>> + }
>> + } else {
>> + if (mhdp->dsc_params.compression_enable) {
>> + cdns_mhdp_dsc_sink_enable(mhdp, false);
>> + cdns_mhdp_dsc_set_stream_compressed(mhdp, 0, false);
>> + }
>> + mhdp->dsc_params.compression_enable = false;
>> + }
>> +
>> + /* Enable DSC for stream 0 */
>> + if (mhdp->dsc_params.compression_enable) {
>> + cdns_mhdp_dsc_enable(mhdp, 0, true);
>> +
>> + if (cdns_mhdp_dsc_sink_enable(mhdp, true))
>> + dev_err(mhdp->dev, "Cannot enable DSC in sink.\n");
>> + cdns_mhdp_dsc_send_pps_sdp(mhdp, 0);
>> + }
>> +
>> + bpp = cdns_mhdp_get_bpp(mhdp);
>>
>> required_bandwidth = pxlclock * bpp / 8;
>> available_bandwidth = mhdp->link.num_lanes * rate;
>>
>> - vs = tu_size * required_bandwidth / available_bandwidth;
>> - vs /= 1000;
>> + vs_f = tu_size * required_bandwidth / available_bandwidth;
>> + if (mhdp->fec_enabled)
>> + vs_f = (vs_f * 1024) / 1000; //2.4%
>> + vs = vs_f / 1000;
>> + vs_f = vs_f % 1000;
>>
>> if (vs == tu_size)
>> vs = tu_size - 1;
>> @@ -1907,6 +2155,70 @@ static void cdns_mhdp_sst_enable(struct cdns_mhdp_device *mhdp,
>> 0 : tu_size - vs));
>>
>> cdns_mhdp_configure_video(mhdp, mode);
>> +
>> + if (mhdp->dsc_params.compression_enable) {
>> + cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_PXL_REPR(0), &pxl_repr);
>> + pxl_repr &= ~CDNS_DP_FRAMER_PXL_REPR_M;
>> + pxl_repr &= ~CDNS_DP_FRAMER_PXL_REPR_DIFF;
>> + pxl_repr |= (((vs_f / 10) << CDNS_DP_FRAMER_PXL_REPR_M_SHIFT)
>> + & CDNS_DP_FRAMER_PXL_REPR_M) |
>> + (((100 - (vs_f / 10)) << CDNS_DP_FRAMER_PXL_REPR_DIFF_SHIFT)
>> + & CDNS_DP_FRAMER_PXL_REPR_DIFF);
>> + cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_PXL_REPR(0), pxl_repr);
>> + }
>> +
>> + /* Enable video mode */
>> + cdns_mhdp_reg_read(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, &framer);
>> + framer &= ~CDNS_DP_NO_VIDEO_MODE;
>> + cdns_mhdp_reg_write(mhdp, CDNS_DP_FRAMER_GLOBAL_CONFIG, framer);
>> +}
>> +
>> +static int cdns_mhdp_configure_car(struct cdns_mhdp_device *mhdp, bool enable)
>> +{
>> + u32 dptx_car, source_pkt_car;
>> + int ret;
>> +
>> + ret = cdns_mhdp_reg_read(mhdp, CDNS_DPTX_CAR, &dptx_car);
>> + if (ret < 0) {
>> + dev_err(mhdp->dev, "Failed to read CDNS_DPTX_CAR %d\n", ret);
>> + goto out;
>> + }
>> +
>> + ret = cdns_mhdp_reg_read(mhdp, CDNS_SOURCE_PKT_CAR, &source_pkt_car);
>> + if (ret < 0) {
>> + dev_err(mhdp->dev, "Failed to read CDNS_SOURCE_PKT_CAR %d\n", ret);
>> + goto out;
>> + }
>> +
>> + if (enable) {
>> + dev_dbg(mhdp->dev, "%s: Enable clocks for VIF and PIF\n", __func__);
>> +
>> + /* Enable VIF clock for stream 0 */
>> + cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR,
>> + dptx_car | CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN);
>> +
>> + /* Enable PKT clock */
>> + cdns_mhdp_reg_write(mhdp, CDNS_SOURCE_PKT_CAR,
>> + source_pkt_car | CDNS_PKT_DATA_CLK_EN
>> + | CDNS_PKT_DATA_RSTN
>> + | CDNS_PKT_SYS_CLK_EN
>> + | CDNS_PKT_SYS_RSTN);
>> + } else {
>> + dev_dbg(mhdp->dev, "%s: Disable clocks for VIF and PIF\n", __func__);
>> +
>> + /* Disable VIF clock for stream 0 */
>> + cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR,
>> + dptx_car & ~(CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN));
>> +
>> + /* Disable PKT clock */
>> + cdns_mhdp_reg_write(mhdp, CDNS_SOURCE_PKT_CAR,
>> + source_pkt_car & ~(CDNS_PKT_DATA_CLK_EN
>> + | CDNS_PKT_DATA_RSTN
>> + | CDNS_PKT_SYS_CLK_EN
>> + | CDNS_PKT_SYS_RSTN));
>> + }
>> +out:
>> + return ret;
>> }
>>
>> static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge,
>> @@ -1919,8 +2231,7 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge,
>> struct drm_connector_state *conn_state;
>> struct drm_bridge_state *new_state;
>> const struct drm_display_mode *mode;
>> - u32 resp;
>> - int ret;
>> + int ret = 0;
>>
>> dev_dbg(mhdp->dev, "bridge enable\n");
>>
>> @@ -1935,16 +2246,13 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge,
>> if (mhdp->info && mhdp->info->ops && mhdp->info->ops->enable)
>> mhdp->info->ops->enable(mhdp);
>>
>> - /* Enable VIF clock for stream 0 */
>> - ret = cdns_mhdp_reg_read(mhdp, CDNS_DPTX_CAR, &resp);
>> + /* Enable clocks for video and packet interfaces */
>> + ret = cdns_mhdp_configure_car(mhdp, true);
>> if (ret < 0) {
>> - dev_err(mhdp->dev, "Failed to read CDNS_DPTX_CAR %d\n", ret);
>> + dev_err(mhdp->dev, "Failed to enable clocks %d\n", ret);
>> goto out;
>> }
>>
>> - cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR,
>> - resp | CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN);
>> -
>> connector = drm_atomic_get_new_connector_for_encoder(state,
>> bridge->encoder);
>> if (WARN_ON(!connector))
>> @@ -2020,10 +2328,8 @@ static void cdns_mhdp_atomic_disable(struct drm_bridge *bridge,
>>
>> cdns_mhdp_link_down(mhdp);
>>
>> - /* Disable VIF clock for stream 0 */
>> - cdns_mhdp_reg_read(mhdp, CDNS_DPTX_CAR, &resp);
>> - cdns_mhdp_reg_write(mhdp, CDNS_DPTX_CAR,
>> - resp & ~(CDNS_VIF_CLK_EN | CDNS_VIF_CLK_RSTN));
>> + /* Disable clocks for video and packet interfaces */
>> + cdns_mhdp_configure_car(mhdp, false);
>>
>> if (mhdp->info && mhdp->info->ops && mhdp->info->ops->disable)
>> mhdp->info->ops->disable(mhdp);
>> @@ -2119,7 +2425,7 @@ static int cdns_mhdp_atomic_check(struct drm_bridge *bridge,
>> struct drm_connector_state *conn_state)
>> {
>> struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge);
>> - const struct drm_display_mode *mode = &crtc_state->adjusted_mode;
>> + struct drm_display_mode *mode = &crtc_state->adjusted_mode;
>>
>> mutex_lock(&mhdp->link_mutex);
>>
>> @@ -2139,6 +2445,10 @@ static int cdns_mhdp_atomic_check(struct drm_bridge *bridge,
>> if (mhdp->info)
>> bridge_state->input_bus_cfg.flags = *mhdp->info->input_bus_flags;
>>
>> + //TODO For DSC. Might need proper handling. 1920x1080 mode doesn't work without this.
>> + mode->flags |= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
>> + mode->flags &= ~(DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC);
>> +
>> mutex_unlock(&mhdp->link_mutex);
>> return 0;
>> }
>> @@ -2426,6 +2736,15 @@ static int cdns_mhdp_probe(struct platform_device *pdev)
>> mhdp->hdcp_supported = true;
>> }
>>
>> + mhdp->dsc_regs = devm_platform_ioremap_resource_byname(pdev, "dsc");
>> + if (IS_ERR(mhdp->dsc_regs)) {
>> + mhdp->dsc_supported = false;
>> + dev_info(dev,
>> + "Failed to get DSC memory resource, DSC not supported\n");
>> + } else {
>> + mhdp->dsc_supported = true;
>> + }
>> +
>> mhdp->phy = devm_of_phy_get_by_index(dev, pdev->dev.of_node, 0);
>> if (IS_ERR(mhdp->phy)) {
>> dev_err(dev, "no PHY configured\n");
>> diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
>> index bad2fc0c7306..c8f8071776d7 100644
>> --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
>> +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
>> @@ -16,6 +16,7 @@
>> #include <linux/spinlock.h>
>>
>> #include <drm/display/drm_dp_helper.h>
>> +#include <drm/display/drm_dsc.h>
>> #include <drm/drm_bridge.h>
>> #include <drm/drm_connector.h>
>>
>> @@ -66,18 +67,30 @@ struct phy;
>> #define CDNS_VIF_CLK_EN BIT(0)
>> #define CDNS_VIF_CLK_RSTN BIT(1)
>>
>> +#define CDNS_SOURCE_PKT_CAR 0x00918
>> +#define CDNS_PKT_DATA_CLK_EN BIT(0)
>> +#define CDNS_PKT_DATA_RSTN BIT(1)
>> +#define CDNS_PKT_SYS_CLK_EN BIT(2)
>> +#define CDNS_PKT_SYS_RSTN BIT(3)
>> +
>> #define CDNS_SOURCE_VIDEO_IF(s) (0x00b00 + ((s) * 0x20))
>> #define CDNS_BND_HSYNC2VSYNC(s) (CDNS_SOURCE_VIDEO_IF(s) + \
>> 0x00)
>> #define CDNS_IP_DTCT_WIN GENMASK(11, 0)
>> #define CDNS_IP_DET_INTERLACE_FORMAT BIT(12)
>> #define CDNS_IP_BYPASS_V_INTERFACE BIT(13)
>> +#define CDNS_IP_VIF_ALIGNMENT_LSB BIT(14)
>>
>> #define CDNS_HSYNC2VSYNC_POL_CTRL(s) (CDNS_SOURCE_VIDEO_IF(s) + \
>> 0x10)
>> #define CDNS_H2V_HSYNC_POL_ACTIVE_LOW BIT(1)
>> #define CDNS_H2V_VSYNC_POL_ACTIVE_LOW BIT(2)
>>
>> +#define CDNS_DP_DSC_CTRL(s) (CDNS_SOURCE_VIDEO_IF(s) + 0x14)
>> +#define CDNS_DP_DSC_CTRL_EN_BIT 0
>> +#define CDNS_DP_DSC_CTRL_SW_RST_BIT 1
>> +#define CDNS_DP_DSC_CTRL_REG_UPDATE_BIT 2
>> +
>> #define CDNS_DPTX_PHY_CONFIG 0x02000
>> #define CDNS_PHY_TRAINING_EN BIT(0)
>> #define CDNS_PHY_TRAINING_TYPE(x) (((x) & GENMASK(3, 0)) << 1)
>> @@ -121,6 +134,10 @@ struct phy;
>>
>> #define CDNS_DP_ENHNCD 0x02304
>>
>> +#define CDNS_DP_FEC_CTRL 0x02310
>> +#define CDNS_DP_FEC_STATUS 0x02314
>> +#define CDNS_DP_FEC_BUSY BIT(0)
>> +
>> #define CDNS_DPTX_STREAM(s) (0x03000 + (s) * 0x80)
>> #define CDNS_DP_MSA_HORIZONTAL_0(s) (CDNS_DPTX_STREAM(s) + 0x00)
>> #define CDNS_DP_MSAH0_H_TOTAL(x) (x)
>> @@ -178,6 +195,10 @@ struct phy;
>> #define CDNS_DP_FRAMER_YCBCR422 BIT(2)
>> #define CDNS_DP_FRAMER_YCBCR420 BIT(3)
>> #define CDNS_DP_FRAMER_Y_ONLY BIT(4)
>> +#define CDNS_DP_FRAMER_PXL_REPR_M GENMASK(22, 16)
>> +#define CDNS_DP_FRAMER_PXL_REPR_DIFF GENMASK(30, 24)
>> +#define CDNS_DP_FRAMER_PXL_REPR_M_SHIFT 16
>> +#define CDNS_DP_FRAMER_PXL_REPR_DIFF_SHIFT 24
>>
>> #define CDNS_DP_FRAMER_SP(s) (CDNS_DPTX_STREAM(s) + 0x50)
>> #define CDNS_DP_FRAMER_VSYNC_POL_LOW BIT(0)
>> @@ -198,6 +219,38 @@ struct phy;
>> #define CDNS_DP_BYTE_COUNT(s) (CDNS_DPTX_STREAM(s) + 0x7c)
>> #define CDNS_DP_BYTE_COUNT_BYTES_IN_CHUNK_SHIFT 16
>>
>> +#define CDNS_SOURCE_PACKET_IF(s) (0x30800 + ((s) * 0x40))
>> +#define CDNS_SOURCE_PIF_WR_ADDR(s) (CDNS_SOURCE_PACKET_IF(s) + 0x00)
>> +
>> +#define CDNS_SOURCE_PIF_WR_REQ(s) (CDNS_SOURCE_PACKET_IF(s) + 0x04)
>> +#define SOURCE_PIF_WR_REQ_HOST_WR BIT(0)
>> +
>> +#define CDNS_SOURCE_PIF_RD_ADDR(s) (CDNS_SOURCE_PACKET_IF(s) + 0x08)
>> +#define CDNS_SOURCE_PIF_RD_REQ(s) (CDNS_SOURCE_PACKET_IF(s) + 0x0c)
>> +#define CDNS_SOURCE_PIF_DATA_WR(s) (CDNS_SOURCE_PACKET_IF(s) + 0x10)
>> +#define CDNS_SOURCE_PIF_DATA_RD(s) (CDNS_SOURCE_PACKET_IF(s) + 0x14)
>> +#define CDNS_SOURCE_PIF_FIFO1_FLUSH(s) (CDNS_SOURCE_PACKET_IF(s) + 0x18)
>> +#define CDNS_SOURCE_PIF_FIFO2_FLUSH(s) (CDNS_SOURCE_PACKET_IF(s) + 0x1c)
>> +#define CDNS_SOURCE_PIF_STATUS(s) (CDNS_SOURCE_PACKET_IF(s) + 0x20)
>> +#define CDNS_SOURCE_PIF_INT_SOURCE(s) (CDNS_SOURCE_PACKET_IF(s) + 0x24)
>> +#define CDNS_SOURCE_PIF_INT_MASK(s) (CDNS_SOURCE_PACKET_IF(s) + 0x28)
>> +
>> +#define CDNS_SOURCE_PIF_PKT_ALLOC_REG(s) (CDNS_SOURCE_PACKET_IF(s) + 0x2c)
>> +#define SOURCE_PIF_PKT_ALLOC_REG_ACTIVE_IDLE_TYPE BIT(17)
>> +#define SOURCE_PIF_PKT_ALLOC_REG_TYPE_VALID BIT(16)
>> +#define SOURCE_PIF_PKT_ALLOC_REG_PACKET_TYPE GENMASK(15, 8)
>> +#define SOURCE_PIF_PKT_ALLOC_REG_PACKET_TYPE_SHIFT 8
>> +#define SOURCE_PIF_PKT_ALLOC_REG_PKT_ALLOC_ADDR GENMASK(3, 0)
>> +
>> +#define CDNS_SOURCE_PIF_PKT_ALLOC_WR_EN(s) (CDNS_SOURCE_PACKET_IF(s) + 0x30)
>> +#define SOURCE_PIF_PKT_ALLOC_WR_EN_EN BIT(0)
>> +
>> +#define CDNS_SOURCE_PIF_SW_RST(s) (CDNS_SOURCE_PACKET_IF(s) + 0x34)
>> +#define CDNS_SOURCE_PIF_PPS_HEADER(s) (CDNS_SOURCE_PACKET_IF(s) + 0x38)
>> +
>> +#define CDNS_SOURCE_PIF_PPS(s) (CDNS_SOURCE_PACKET_IF(s) + 0x3c)
>> +#define SOURCE_PIF_PPS_PPS BIT(0)
>> +
>> /* mailbox */
>> #define MAILBOX_RETRY_US 1000
>> #define MAILBOX_TIMEOUT_US 2000000
>> @@ -354,6 +407,7 @@ struct cdns_mhdp_hdcp {
>> struct cdns_mhdp_device {
>> void __iomem *regs;
>> void __iomem *sapb_regs;
>> + void __iomem *dsc_regs;
>> void __iomem *j721e_regs;
>>
>> struct device *dev;
>> @@ -412,6 +466,20 @@ struct cdns_mhdp_device {
>>
>> struct cdns_mhdp_hdcp hdcp;
>> bool hdcp_supported;
>> +
>> + struct drm_dsc_config dsc_config;
>> +
>> + /* Display Stream Compression state */
>> + bool dsc_supported;
>> + struct {
>> + bool compression_enable;
>> + bool dsc_split;
>> + u16 compressed_bpp;
>> + u8 slice_count;
>> + u8 dsc_cap[DP_DSC_RECEIVER_CAP_SIZE];
>> + } dsc_params;
>> +
>> + bool fec_enabled;
>> };
>>
>> #define connector_to_mhdp(x) container_of(x, struct cdns_mhdp_device, connector)
>> diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.c
>> new file mode 100644
>> index 000000000000..e540e8f2dd4a
>> --- /dev/null
>> +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.c
>> @@ -0,0 +1,695 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (C) Cadence Design Systems, Inc.
>> + *
>> + * Author: Swapnil Jakhade <sjakhade@cadence.com>
>> + */
>> +
>> +#include "cdns-mhdp8546-core.h"
>> +#include "cdns-mhdp8546-dsc.h"
>> +
>> +void cdns_mhdp_dsc_write_config(struct cdns_mhdp_device *mhdp)
>> +{
>> + u32 main_conf = 0;
>> +
>> + main_conf = CDNS_DP_COM_MAIN_CONF_INPUT_MODE |
>> + CDNS_DP_COM_MAIN_CONF_AUTO_DB_UPDATE;
>> +
>> + if (mhdp->dsc_params.dsc_split) {
>> + main_conf |= CDNS_DP_COM_MAIN_CONF_MUX_MODE |
>> + CDNS_DP_COM_MAIN_CONF_SPLIT_PANEL;
>> + }
>> +
>> + writel(main_conf, mhdp->dsc_regs + CDNS_DP_COM_MAIN_CONF);
>> +}
>> +
>> +static u8 cdns_mhdp_dsc_compute_initial_lines(struct cdns_mhdp_device *mhdp)
>> +{
>> + struct drm_dsc_config *dsc_cfg = &mhdp->dsc_config;
>> + unsigned long k1, real_bpp;
>> + u8 initial_lines;
>> +
>> + real_bpp = (unsigned long)dsc_cfg->bits_per_pixel / 16;
>> +
>> + if (dsc_cfg->bits_per_component == 8)
>> + k1 = 296;
>> + else
>> + k1 = 320;
>> +
>> + if (mhdp->dsc_params.dsc_split) {
>> + initial_lines = (u8)DIV_ROUND_UP
>> + ((k1 + (unsigned long)dsc_cfg->initial_xmit_delay +
>> + ((((unsigned long)dsc_cfg->slice_chunk_size * 8) + 144) /
>> + real_bpp)), (unsigned long)dsc_cfg->slice_width);
>> + } else {
>> + initial_lines = (u8)DIV_ROUND_UP
>> + ((k1 + (unsigned long)dsc_cfg->initial_xmit_delay +
>> + ((DIV_ROUND_UP(((1 - (real_bpp / 48)) *
>> + ((unsigned long)dsc_cfg->slice_chunk_size * 8)), 1) + 144) /
>> + real_bpp)), (unsigned long)dsc_cfg->slice_width);
>> + }
> Is there a way to make it possible to comprehend?
will break it down and make it better.
>
>> +
>> + return initial_lines;
>> +}
>> +
>> +static void write_enc_main_conf(struct cdns_mhdp_device *mhdp, int stream_id)
>> +{
>> + u32 reg_val = 0;
>> +
>> + if (mhdp->dsc_config.convert_rgb)
>> + reg_val |= CDNS_DP_ENC_MAIN_CONF_CONVERT_RGB;
>> +
>> + reg_val |= (mhdp->dsc_config.line_buf_depth <<
>> + CDNS_DP_ENC_MAIN_CONF_LINEBUF_DEPTH_SHIFT) &
>> + CDNS_DP_ENC_MAIN_CONF_LINEBUF_DEPTH;
>> +
>> + reg_val |= (mhdp->dsc_config.bits_per_pixel <<
>> + CDNS_DP_ENC_MAIN_CONF_BITS_PER_PIXEL_SHIFT) &
>> + CDNS_DP_ENC_MAIN_CONF_BITS_PER_PIXEL;
>> +
>> + if (mhdp->dsc_config.block_pred_enable)
>> + reg_val |= CDNS_DP_ENC_MAIN_CONF_BLOCK_PRED_EN;
>> +
>> + reg_val |= CDNS_DP_ENC_MAIN_CONF_VIDEO_MODE;
>> +
>> + reg_val |= (cdns_mhdp_dsc_compute_initial_lines(mhdp) <<
>> + CDNS_DP_ENC_MAIN_CONF_INITIAL_LINES_SHIFT) &
>> + CDNS_DP_ENC_MAIN_CONF_INITIAL_LINES;
>> +
>> + if (mhdp->dsc_config.bits_per_component == 10)
>> + reg_val |= 0x1;
>> + else if (mhdp->dsc_config.bits_per_component != 8)
>> + dev_err(mhdp->dev, "Unsupported bits_per_component = %d\n",
>> + mhdp->dsc_config.bits_per_component);
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_MAIN_CONF(stream_id));
>> +}
>> +
>> +static void write_enc_picture_size(struct cdns_mhdp_device *mhdp, int stream_id)
>> +{
>> + u32 reg_val = 0;
>> +
>> + reg_val = (mhdp->dsc_config.pic_width &
>> + CDNS_DP_ENC_PICTURE_SIZE_WIDTH);
>> +
>> + reg_val |= (mhdp->dsc_config.pic_height <<
>> + CDNS_DP_ENC_PICTURE_SIZE_HEIGHT_SHIFT) &
>> + CDNS_DP_ENC_PICTURE_SIZE_HEIGHT;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_PICTURE_SIZE(stream_id));
>> +}
>> +
>> +static void write_enc_slice_size(struct cdns_mhdp_device *mhdp, int stream_id)
>> +{
>> + u32 reg_val = 0;
>> +
>> + reg_val = (mhdp->dsc_config.slice_width &
>> + CDNS_DP_ENC_SLICE_SIZE_WIDTH);
>> +
>> + reg_val |= (mhdp->dsc_config.slice_height <<
>> + CDNS_DP_ENC_SLICE_SIZE_HEIGHT_SHIFT) &
>> + CDNS_DP_ENC_SLICE_SIZE_HEIGHT;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_SLICE_SIZE(stream_id));
>> +}
>> +
>> +static void write_enc_misc_size(struct cdns_mhdp_device *mhdp, int stream_id)
>> +{
>> + u32 reg_val = 0;
>> +
>> + reg_val = ((mhdp->dsc_config.slice_width + 2) % 3) &
>> + CDNS_DP_ENC_MISC_SIZE_LAST_GRP_SIZE;
>> +
>> + reg_val |= (DSC_OUTPUT_BUFFER_MAX_ADDRESS <<
>> + CDNS_DP_ENC_MISC_SIZE_OB_MAX_ADDR_SHIFT) &
>> + CDNS_DP_ENC_MISC_SIZE_OB_MAX_ADDR;
>> +
>> + reg_val |= (mhdp->dsc_config.slice_chunk_size <<
>> + CDNS_DP_ENC_MISC_SIZE_CHUNK_SIZE_SHIFT) &
>> + CDNS_DP_ENC_MISC_SIZE_CHUNK_SIZE;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_MISC_SIZE(stream_id));
>> +}
>> +
>> +static void write_enc_hrd_delays(struct cdns_mhdp_device *mhdp, int stream_id)
>> +{
>> + u32 reg_val = 0;
>> +
>> + reg_val = (mhdp->dsc_config.initial_xmit_delay &
>> + CDNS_DP_ENC_HRD_DELAYS_INIT_XMIT_DELAY);
>> +
>> + reg_val |= (mhdp->dsc_config.initial_dec_delay <<
>> + CDNS_DP_ENC_HRD_DELAYS_INIT_DEC_DELAY_SHIFT) &
>> + CDNS_DP_ENC_HRD_DELAYS_INIT_DEC_DELAY;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_HRD_DELAYS(stream_id));
>> +}
>> +
>> +static void write_enc_rc_scale(struct cdns_mhdp_device *mhdp, int stream_id)
>> +{
>> + u32 reg_val = 0;
>> +
>> + reg_val = (mhdp->dsc_config.initial_scale_value &
>> + CDNS_DP_ENC_RC_SCALE_INIT_SCALE_VALUE);
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_SCALE(stream_id));
>> +}
>> +
>> +static void write_enc_rc_scale_inc_dec(struct cdns_mhdp_device *mhdp, int stream_id)
>> +{
>> + u32 reg_val = 0;
>> +
>> + reg_val = (mhdp->dsc_config.scale_increment_interval &
>> + CDNS_DP_ENC_RC_SCALE_INC_INTERVAL);
>> +
>> + reg_val |= (mhdp->dsc_config.scale_decrement_interval <<
>> + CDNS_DP_ENC_RC_SCALE_DEC_INTERVAL_SHIFT) &
>> + CDNS_DP_ENC_RC_SCALE_DEC_INTERVAL;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_SCALE_INC_DEC(stream_id));
>> +}
>> +
>> +static void write_enc_rc_offsets(struct cdns_mhdp_device *mhdp, int stream_id)
>> +{
>> + u32 reg_val;
>> +
>> + reg_val = (mhdp->dsc_config.first_line_bpg_offset &
>> + CDNS_DP_ENC_RC_OFFSETS_1_FL_BPG_OFFSET);
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_OFFSETS_1(stream_id));
>> +
>> + reg_val = (mhdp->dsc_config.nfl_bpg_offset &
>> + CDNS_DP_ENC_RC_OFFSETS_2_NFL_BPG_OFFSET);
>> +
>> + reg_val |= (mhdp->dsc_config.slice_bpg_offset <<
>> + CDNS_DP_ENC_RC_OFFSETS_2_SL_BPG_OFFSET_SHIFT) &
>> + CDNS_DP_ENC_RC_OFFSETS_2_SL_BPG_OFFSET;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_OFFSETS_2(stream_id));
>> +
>> + reg_val = (mhdp->dsc_config.initial_offset &
>> + CDNS_DP_ENC_RC_OFFSETS_3_INIT_OFFSET);
>> +
>> + reg_val |= (mhdp->dsc_config.final_offset <<
>> + CDNS_DP_ENC_RC_OFFSETS_3_FINAL_OFFSET_SHIFT) &
>> + CDNS_DP_ENC_RC_OFFSETS_3_FINAL_OFFSET;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_OFFSETS_3(stream_id));
>> +}
>> +
>> +static void write_enc_flatness_detection(struct cdns_mhdp_device *mhdp, int stream_id)
>> +{
>> + u32 reg_val;
>> +
>> + reg_val = (mhdp->dsc_config.flatness_min_qp &
>> + CDNS_DP_ENC_FLATNESS_DETECTION_MIN_QP);
>> +
>> + reg_val |= (mhdp->dsc_config.flatness_max_qp <<
>> + CDNS_DP_ENC_FLATNESS_DETECTION_MAX_QP_SHIFT) &
>> + CDNS_DP_ENC_FLATNESS_DETECTION_MAX_QP;
>> +
>> + reg_val |= (drm_dsc_flatness_det_thresh(&mhdp->dsc_config) <<
>> + CDNS_DP_ENC_FLATNESS_DETECTION_THRESH_SHIFT) &
>> + CDNS_DP_ENC_FLATNESS_DETECTION_THRESH;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_FLATNESS_DETECTION(stream_id));
>> +}
>> +
>> +static void write_enc_rc_model_size(struct cdns_mhdp_device *mhdp, int stream_id)
>> +{
>> + u32 reg_val;
>> +
>> + reg_val = (mhdp->dsc_config.rc_model_size &
>> + CDNS_DP_ENC_RC_MODEL_SIZE_RC_MODEL_SIZE);
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_MODEL_SIZE(stream_id));
>> +}
>> +
>> +static void write_enc_rc_config(struct cdns_mhdp_device *mhdp, int stream_id)
>> +{
>> + u32 reg_val;
>> +
>> + reg_val = (mhdp->dsc_config.rc_edge_factor &
>> + CDNS_DP_ENC_RC_CONFIG_EDGE_FACTOR);
>> +
>> + reg_val |= (mhdp->dsc_config.rc_quant_incr_limit0 <<
>> + CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_0_SHIFT) &
>> + CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_0;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_quant_incr_limit1 <<
>> + CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_1_SHIFT) &
>> + CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_1;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_tgt_offset_high <<
>> + CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_HI_SHIFT) &
>> + CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_HI;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_tgt_offset_low <<
>> + CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_LO_SHIFT) &
>> + CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_LO;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_CONFIG(stream_id));
>> +}
>> +
>> +static void write_enc_rc_buf_thresh(struct cdns_mhdp_device *mhdp, int stream_id)
>> +{
>> + u32 reg_val;
>> + int index = 0;
>> +
>> + reg_val = (mhdp->dsc_config.rc_buf_thresh[index++] &
>> + CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_0);
>> +
>> + reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
>> + CDNS_DP_ENC_RC_BUF_THRESH_THRESH_1_SHIFT) &
>> + CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_1;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
>> + CDNS_DP_ENC_RC_BUF_THRESH_THRESH_2_SHIFT) &
>> + CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_2;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
>> + CDNS_DP_ENC_RC_BUF_THRESH_THRESH_3_SHIFT) &
>> + CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_3;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_BUF_THRESH_0(stream_id));
>> +
>> + reg_val = (mhdp->dsc_config.rc_buf_thresh[index++] &
>> + CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_4);
>> +
>> + reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
>> + CDNS_DP_ENC_RC_BUF_THRESH_THRESH_1_SHIFT) &
>> + CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_5;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
>> + CDNS_DP_ENC_RC_BUF_THRESH_THRESH_2_SHIFT) &
>> + CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_6;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
>> + CDNS_DP_ENC_RC_BUF_THRESH_THRESH_3_SHIFT) &
>> + CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_7;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_BUF_THRESH_1(stream_id));
>> +
>> + reg_val = (mhdp->dsc_config.rc_buf_thresh[index++] &
>> + CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_8);
>> +
>> + reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
>> + CDNS_DP_ENC_RC_BUF_THRESH_THRESH_1_SHIFT) &
>> + CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_9;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
>> + CDNS_DP_ENC_RC_BUF_THRESH_THRESH_2_SHIFT) &
>> + CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_10;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
>> + CDNS_DP_ENC_RC_BUF_THRESH_THRESH_3_SHIFT) &
>> + CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_11;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_BUF_THRESH_2(stream_id));
>> +
>> + reg_val = (mhdp->dsc_config.rc_buf_thresh[index++] &
>> + CDNS_DP_ENC_RC_BUF_THRESH_3_THRESH_12);
>> +
>> + reg_val |= (mhdp->dsc_config.rc_buf_thresh[index++] <<
>> + CDNS_DP_ENC_RC_BUF_THRESH_THRESH_1_SHIFT) &
>> + CDNS_DP_ENC_RC_BUF_THRESH_3_THRESH_13;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_BUF_THRESH_3(stream_id));
>> +}
>> +
>> +static void write_enc_rc_min_qp(struct cdns_mhdp_device *mhdp, int stream_id)
>> +{
>> + u32 reg_val;
>> + int index = 0;
>> +
>> + reg_val = (mhdp->dsc_config.rc_range_params[index++].range_min_qp &
>> + CDNS_DP_ENC_RC_MIN_QP_0_RANGE_0);
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
>> + CDNS_DP_ENC_RC_MIN_QP_0_RANGE_1;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
>> + CDNS_DP_ENC_RC_MIN_QP_0_RANGE_2;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
>> + CDNS_DP_ENC_RC_MIN_QP_0_RANGE_3;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
>> + CDNS_DP_ENC_RC_MIN_QP_0_RANGE_4;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_MIN_QP_0(stream_id));
>> +
>> + reg_val = (mhdp->dsc_config.rc_range_params[index++].range_min_qp &
>> + CDNS_DP_ENC_RC_MIN_QP_1_RANGE_5);
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
>> + CDNS_DP_ENC_RC_MIN_QP_1_RANGE_6;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
>> + CDNS_DP_ENC_RC_MIN_QP_1_RANGE_7;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
>> + CDNS_DP_ENC_RC_MIN_QP_1_RANGE_8;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
>> + CDNS_DP_ENC_RC_MIN_QP_1_RANGE_9;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_MIN_QP_1(stream_id));
>> +
>> + reg_val = (mhdp->dsc_config.rc_range_params[index++].range_min_qp &
>> + CDNS_DP_ENC_RC_MIN_QP_2_RANGE_10);
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
>> + CDNS_DP_ENC_RC_MIN_QP_2_RANGE_11;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
>> + CDNS_DP_ENC_RC_MIN_QP_2_RANGE_12;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
>> + CDNS_DP_ENC_RC_MIN_QP_2_RANGE_13;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_min_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
>> + CDNS_DP_ENC_RC_MIN_QP_2_RANGE_14;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_MIN_QP_2(stream_id));
>> +}
>> +
>> +static void write_enc_rc_max_qp(struct cdns_mhdp_device *mhdp, int stream_id)
>> +{
>> + u32 reg_val;
>> + int index = 0;
>> +
>> + reg_val = (mhdp->dsc_config.rc_range_params[index++].range_max_qp &
>> + CDNS_DP_ENC_RC_MAX_QP_0_RANGE_0);
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
>> + CDNS_DP_ENC_RC_MAX_QP_0_RANGE_1;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
>> + CDNS_DP_ENC_RC_MAX_QP_0_RANGE_2;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
>> + CDNS_DP_ENC_RC_MAX_QP_0_RANGE_3;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
>> + CDNS_DP_ENC_RC_MAX_QP_0_RANGE_4;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_MAX_QP_0(stream_id));
>> +
>> + reg_val = (mhdp->dsc_config.rc_range_params[index++].range_max_qp &
>> + CDNS_DP_ENC_RC_MAX_QP_1_RANGE_5);
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
>> + CDNS_DP_ENC_RC_MAX_QP_1_RANGE_6;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
>> + CDNS_DP_ENC_RC_MAX_QP_1_RANGE_7;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
>> + CDNS_DP_ENC_RC_MAX_QP_1_RANGE_8;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
>> + CDNS_DP_ENC_RC_MAX_QP_1_RANGE_9;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_MAX_QP_1(stream_id));
>> +
>> + reg_val = (mhdp->dsc_config.rc_range_params[index++].range_max_qp &
>> + CDNS_DP_ENC_RC_MAX_QP_2_RANGE_10);
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
>> + CDNS_DP_ENC_RC_MAX_QP_2_RANGE_11;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
>> + CDNS_DP_ENC_RC_MAX_QP_2_RANGE_12;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
>> + CDNS_DP_ENC_RC_MAX_QP_2_RANGE_13;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_max_qp <<
>> + CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
>> + CDNS_DP_ENC_RC_MAX_QP_2_RANGE_14;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_MAX_QP_2(stream_id));
>> +}
>> +
>> +static void write_enc_rc_range_bpg(struct cdns_mhdp_device *mhdp, int stream_id)
>> +{
>> + u32 reg_val;
>> + int index = 0;
>> +
>> + reg_val = (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset &
>> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_0);
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
>> + CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
>> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_1;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
>> + CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
>> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_2;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
>> + CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
>> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_3;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
>> + CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
>> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_4;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0(stream_id));
>> +
>> + reg_val = (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset &
>> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_5);
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
>> + CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
>> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_6;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
>> + CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
>> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_7;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
>> + CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
>> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_8;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
>> + CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
>> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_9;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_1(stream_id));
>> +
>> + reg_val = (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset &
>> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_10);
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
>> + CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT) &
>> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_11;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
>> + CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT) &
>> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_12;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
>> + CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT) &
>> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_13;
>> +
>> + reg_val |= (mhdp->dsc_config.rc_range_params[index++].range_bpg_offset <<
>> + CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT) &
>> + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_14;
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_2(stream_id));
>> +}
>> +
>> +static void write_enc_dpi_ctrl(struct cdns_mhdp_device *mhdp, int stream_id,
>> + const struct drm_display_mode *mode)
>> +{
>> + u32 reg_val = 0;
>> +
>> + reg_val = ((mode->crtc_htotal * cdns_mhdp_dsc_compute_initial_lines(mhdp)) &
>> + CDNS_DP_ENC_DPI_CTRL_OUT_DELAY_CYCLES);
>> +
>> + writel(reg_val, mhdp->dsc_regs + CDNS_DP_ENC_DPI_CTRL_OUT_DELAY(stream_id));
>> +}
>> +
>> +void cdns_mhdp_dsc_write_enc_config(struct cdns_mhdp_device *mhdp, int stream_id,
>> + const struct drm_display_mode *mode)
>> +{
>> + write_enc_main_conf(mhdp, stream_id);
>> + write_enc_picture_size(mhdp, stream_id);
>> + write_enc_slice_size(mhdp, stream_id);
>> + write_enc_misc_size(mhdp, stream_id);
>> + write_enc_hrd_delays(mhdp, stream_id);
>> + write_enc_rc_scale(mhdp, stream_id);
>> + write_enc_rc_scale_inc_dec(mhdp, stream_id);
>> + write_enc_rc_offsets(mhdp, stream_id);
>> + write_enc_flatness_detection(mhdp, stream_id);
>> + write_enc_rc_model_size(mhdp, stream_id);
>> + write_enc_rc_config(mhdp, stream_id);
>> + write_enc_rc_buf_thresh(mhdp, stream_id);
>> + write_enc_rc_min_qp(mhdp, stream_id);
>> + write_enc_rc_max_qp(mhdp, stream_id);
>> + write_enc_rc_range_bpg(mhdp, stream_id);
>> + write_enc_dpi_ctrl(mhdp, stream_id, mode);
>> +}
>> +
>> +int cdns_mhdp_dsc_sink_support(struct cdns_mhdp_device *mhdp)
>> +{
>> + int ret;
>> +
>> + ret = drm_dp_dpcd_read(&mhdp->aux, DP_DSC_SUPPORT, &mhdp->dsc_params.dsc_cap,
>> + DP_DSC_RECEIVER_CAP_SIZE);
>> + if (ret != DP_DSC_RECEIVER_CAP_SIZE) {
>> + DRM_DEV_ERROR(mhdp->dev, "cannot read sink DSC DPCD: %d\n", ret);
>> + goto err;
>> + }
>> + if (!(mhdp->dsc_params.dsc_cap[0] & DP_DSC_DECOMPRESSION_IS_SUPPORTED)) {
>> + ret = -EOPNOTSUPP;
>> + DRM_DEV_ERROR(mhdp->dev, "sink does not support DSC: %d\n", ret);
>> + goto err;
>> + }
>> +
>> + ret = 0;
>> +err:
>> + return ret;
>> +}
>> +
>> +int cdns_mhdp_compute_dsc_params(struct cdns_mhdp_device *mhdp)
>> +{
>> + struct drm_bridge *bridge = &mhdp->bridge;
>> + struct drm_dsc_config *dsc_cfg = &mhdp->dsc_config;
>> + struct drm_crtc_state *crtc_state = bridge->encoder->crtc->state;
>> + u8 *dsc_dpcd = (u8 *)&mhdp->dsc_params.dsc_cap;
>> + int ret;
>> +
>> + dsc_cfg->pic_width = crtc_state->adjusted_mode.crtc_hdisplay;
>> + dsc_cfg->pic_height = crtc_state->adjusted_mode.crtc_vdisplay;
>> +
>> + dsc_cfg->slice_width = dsc_cfg->pic_width;
>> + dsc_cfg->slice_height = DIV_ROUND_UP(dsc_cfg->pic_height,
>> + mhdp->dsc_params.slice_count);
>> +
>> + dsc_cfg->dsc_version_major = (dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] &
>> + DP_DSC_MAJOR_MASK) >> DP_DSC_MAJOR_SHIFT;
>> + dsc_cfg->dsc_version_minor =
>> + min(DSC_SUPPORTED_VERSION_MIN,
>> + (dsc_dpcd[DP_DSC_REV - DP_DSC_SUPPORT] &
>> + DP_DSC_MINOR_MASK) >> DP_DSC_MINOR_SHIFT);
>> +
>> + dsc_cfg->convert_rgb =
>> + dsc_dpcd[DP_DSC_DEC_COLOR_FORMAT_CAP - DP_DSC_SUPPORT] & DP_DSC_RGB;
>> +
>> + dsc_cfg->vbr_enable = false;
>> +
>> + dsc_cfg->block_pred_enable =
>> + dsc_dpcd[DP_DSC_BLK_PREDICTION_SUPPORT - DP_DSC_SUPPORT] &
>> + DP_DSC_BLK_PREDICTION_IS_SUPPORTED;
>> +
>> + dsc_cfg->bits_per_pixel = mhdp->dsc_params.compressed_bpp << 4;
>> +
>> + dsc_cfg->bits_per_component = mhdp->display_fmt.bpc;
>> +
>> + if (mhdp->dsc_config.bits_per_component == 8)
>> + dsc_cfg->line_buf_depth = min(9, drm_dp_dsc_sink_line_buf_depth(dsc_dpcd));
>> + else if (mhdp->dsc_config.bits_per_component == 10)
>> + dsc_cfg->line_buf_depth = min(11, drm_dp_dsc_sink_line_buf_depth(dsc_dpcd));
>> +
>> + drm_dsc_set_const_params(dsc_cfg);
>> + drm_dsc_set_rc_buf_thresh(dsc_cfg);
>> +
>> + ret = drm_dsc_setup_rc_params(dsc_cfg, DRM_DSC_1_1_PRE_SCR);
>> + if (ret) {
>> + dev_err(mhdp->dev, "could not find DSC RC parameters");
>> + return ret;
>> + }
>> +
>> + dsc_cfg->initial_scale_value = drm_dsc_initial_scale_value(dsc_cfg);
>> + dsc_cfg->slice_count = mhdp->dsc_params.slice_count;
>> +
>> + return drm_dsc_compute_rc_parameters(dsc_cfg);
>> +}
> Please consider extracting code common with Intel driver.
will check and make changes.
>
>> +
>> +static void cdns_mhdp_write_data_packet(struct cdns_mhdp_device *mhdp, u32 *buf,
>> + int length, int stream_id)
>> +{
>> + int i;
>> + u32 reg_val;
>> +
>> + for (i = 0; i < length; i++) {
>> + reg_val = buf[i];
>> + writel(reg_val, mhdp->regs + CDNS_SOURCE_PIF_DATA_WR(stream_id));
>> + }
>> +}
>> +
>> +static void cdns_mhdp_write_pps_header(struct cdns_mhdp_device *mhdp, u32 *buf,
>> + int stream_id)
>> +{
>> + writel(SOURCE_PIF_PPS_PPS, mhdp->regs + CDNS_SOURCE_PIF_PPS(stream_id));
>> + writel(*buf, mhdp->regs + CDNS_SOURCE_PIF_PPS_HEADER(stream_id));
>> +}
>> +
>> +static int cdns_mhdp_write_pps_infoframe(struct cdns_mhdp_device *mhdp, int stream_id,
>> + struct drm_dsc_pps_infoframe *pps_infoframe)
>> +{
>> + u32 reg_val;
>> + u32 entry_id = 0;
>> +
>> + writel(1, mhdp->regs + CDNS_SOURCE_PIF_FIFO1_FLUSH(stream_id));
>> +
>> + cdns_mhdp_write_pps_header(mhdp, (u32 *)&pps_infoframe->pps_header, 0);
>> + cdns_mhdp_write_data_packet(mhdp, (u32 *)&pps_infoframe->pps_payload,
>> + DP_DSC_PPS_SIZE / 4, 0);
> sizeof(foo) / 4
Noted.
>
>> +
>> + /* Entry ID */
>> + writel(entry_id, mhdp->regs + CDNS_SOURCE_PIF_WR_ADDR(stream_id));
>> +
>> + writel(SOURCE_PIF_WR_REQ_HOST_WR, mhdp->regs + CDNS_SOURCE_PIF_WR_REQ(stream_id));
>> +
>> + reg_val = SOURCE_PIF_PKT_ALLOC_REG_ACTIVE_IDLE_TYPE |
>> + SOURCE_PIF_PKT_ALLOC_REG_TYPE_VALID |
>> + ((DP_SDP_PPS << SOURCE_PIF_PKT_ALLOC_REG_PACKET_TYPE_SHIFT) &
>> + SOURCE_PIF_PKT_ALLOC_REG_PACKET_TYPE) |
>> + (entry_id & SOURCE_PIF_PKT_ALLOC_REG_PKT_ALLOC_ADDR);
>> +
>> + writel(reg_val, mhdp->regs + CDNS_SOURCE_PIF_PKT_ALLOC_REG(stream_id));
>> +
>> + writel
>> + (SOURCE_PIF_PKT_ALLOC_WR_EN_EN, mhdp->regs + CDNS_SOURCE_PIF_PKT_ALLOC_WR_EN(stream_id));
> Ugh. Newline after comma, please.
will make changes.
>> +
>> + return 0;
>> +}
>> +
>> +int cdns_mhdp_dsc_send_pps_sdp(struct cdns_mhdp_device *mhdp, int stream_id)
>> +{
>> + struct drm_dsc_config *dsc_cfg = &mhdp->dsc_config;
>> + struct drm_dsc_pps_infoframe dp_dsc_pps_sdp;
>> +
>> + drm_dsc_dp_pps_header_init(&dp_dsc_pps_sdp.pps_header);
>> +
>> + drm_dsc_pps_payload_pack(&dp_dsc_pps_sdp.pps_payload, dsc_cfg);
>> +
>> + return cdns_mhdp_write_pps_infoframe(mhdp, stream_id, &dp_dsc_pps_sdp);
>> +}
>> diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.h
>> new file mode 100644
>> index 000000000000..c44d7e3d0002
>> --- /dev/null
>> +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-dsc.h
>> @@ -0,0 +1,285 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * Copyright (C) Cadence Design Systems, Inc.
>> + *
>> + * Author: Swapnil Jakhade <sjakhade@cadence.com>
>> + */
>> +
>> +#ifndef CDNS_MHDP_DSC_H_
>> +#define CDNS_MHDP_DSC_H_
>> +
>> +#include <linux/bitops.h>
>> +#include <linux/io.h>
>> +#include <linux/minmax.h>
>> +#include <drm/display/drm_dsc_helper.h>
>> +#include <drm/drm_bridge.h>
>> +#include <drm/drm_connector.h>
>> +#include <drm/drm_crtc_helper.h>
>> +#include <drm/drm_print.h>
> Please don't include unnecessary headers through the header file. Use
> forward declarations for structs where possible.
Noted, will make appropriate changes.
>
>> +
>> +#define DSC_SUPPORTED_VERSION_MIN 1
>> +
>> +#define DSC_OUTPUT_BUFFER_MAX_ADDRESS 3667U
>> +#define DP_DSC_PPS_SIZE 128
>> +
>> +#define CDNS_DP_COM_MAIN_CONF 0
>> +#define CDNS_DP_COM_MAIN_CONF_SPLIT_PANEL BIT(0)
>> +#define CDNS_DP_COM_MAIN_CONF_MUX_MODE BIT(1)
>> +#define CDNS_DP_COM_MAIN_CONF_MUX_SEL_OUT BIT(2)
>> +#define CDNS_DP_COM_MAIN_CONF_DE_RASTER_EN BIT(3)
>> +#define CDNS_DP_COM_MAIN_CONF_INPUT_MODE BIT(4)
>> +#define CDNS_DP_COM_MAIN_CONF_MUX_EOC_EN BIT(5)
>> +#define CDNS_DP_COM_MAIN_CONF_AUTO_DB_UPDATE BIT(6)
>> +
>> +#define CDNS_DP_ENC_MAIN_CONF(d) (0x120 + ((d) * 0x100))
>> +#define CDNS_DP_ENC_MAIN_CONF_INPUT_BPC GENMASK(1, 0)
>> +#define CDNS_DP_ENC_MAIN_CONF_CONVERT_RGB BIT(2)
>> +#define CDNS_DP_ENC_MAIN_CONF_ENABLE_422 BIT(3)
>> +#define CDNS_DP_ENC_MAIN_CONF_LINEBUF_DEPTH GENMASK(7, 4)
>> +#define CDNS_DP_ENC_MAIN_CONF_LINEBUF_DEPTH_SHIFT 4
>> +#define CDNS_DP_ENC_MAIN_CONF_BITS_PER_PIXEL GENMASK(17, 8)
>> +#define CDNS_DP_ENC_MAIN_CONF_BITS_PER_PIXEL_SHIFT 8
>> +#define CDNS_DP_ENC_MAIN_CONF_BLOCK_PRED_EN BIT(18)
>> +#define CDNS_DP_ENC_MAIN_CONF_VIDEO_MODE BIT(19)
>> +#define CDNS_DP_ENC_MAIN_CONF_ICH_RST_EOL BIT(20)
>> +#define CDNS_DP_ENC_MAIN_CONF_INITIAL_LINES GENMASK(31, 24)
>> +#define CDNS_DP_ENC_MAIN_CONF_INITIAL_LINES_SHIFT 24
>> +
>> +#define CDNS_DP_ENC_PICTURE_SIZE(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x4)
>> +#define CDNS_DP_ENC_PICTURE_SIZE_HEIGHT GENMASK(31, 16)
>> +#define CDNS_DP_ENC_PICTURE_SIZE_HEIGHT_SHIFT 16
>> +#define CDNS_DP_ENC_PICTURE_SIZE_WIDTH GENMASK(15, 0)
>> +
>> +#define CDNS_DP_ENC_SLICE_SIZE(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x8)
>> +#define CDNS_DP_ENC_SLICE_SIZE_HEIGHT GENMASK(31, 16)
>> +#define CDNS_DP_ENC_SLICE_SIZE_HEIGHT_SHIFT 16
>> +#define CDNS_DP_ENC_SLICE_SIZE_WIDTH GENMASK(15, 0)
>> +
>> +#define CDNS_DP_ENC_MISC_SIZE(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xc)
>> +#define CDNS_DP_ENC_MISC_SIZE_CHUNK_SIZE GENMASK(31, 16)
>> +#define CDNS_DP_ENC_MISC_SIZE_CHUNK_SIZE_SHIFT 16
>> +#define CDNS_DP_ENC_MISC_SIZE_OB_MAX_ADDR GENMASK(15, 2)
>> +#define CDNS_DP_ENC_MISC_SIZE_OB_MAX_ADDR_SHIFT 2
>> +#define CDNS_DP_ENC_MISC_SIZE_LAST_GRP_SIZE GENMASK(1, 0)
>> +
>> +#define CDNS_DP_ENC_HRD_DELAYS(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x10)
>> +#define CDNS_DP_ENC_HRD_DELAYS_INIT_DEC_DELAY GENMASK(31, 16)
>> +#define CDNS_DP_ENC_HRD_DELAYS_INIT_DEC_DELAY_SHIFT 16
>> +#define CDNS_DP_ENC_HRD_DELAYS_INIT_XMIT_DELAY GENMASK(9, 0)
>> +
>> +#define CDNS_DP_ENC_RC_SCALE(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x14)
>> +#define CDNS_DP_ENC_RC_SCALE_INIT_SCALE_VALUE GENMASK(5, 0)
>> +
>> +#define CDNS_DP_ENC_RC_SCALE_INC_DEC(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x18)
>> +#define CDNS_DP_ENC_RC_SCALE_DEC_INTERVAL GENMASK(27, 16)
>> +#define CDNS_DP_ENC_RC_SCALE_DEC_INTERVAL_SHIFT 16
>> +#define CDNS_DP_ENC_RC_SCALE_INC_INTERVAL GENMASK(15, 0)
>> +
>> +#define CDNS_DP_ENC_RC_OFFSETS_1(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x1c)
>> +#define CDNS_DP_ENC_RC_OFFSETS_1_FL_BPG_OFFSET GENMASK(4, 0)
>> +
>> +#define CDNS_DP_ENC_RC_OFFSETS_2(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x20)
>> +#define CDNS_DP_ENC_RC_OFFSETS_2_SL_BPG_OFFSET GENMASK(31, 16)
>> +#define CDNS_DP_ENC_RC_OFFSETS_2_SL_BPG_OFFSET_SHIFT 16
>> +#define CDNS_DP_ENC_RC_OFFSETS_2_NFL_BPG_OFFSET GENMASK(15, 0)
>> +
>> +#define CDNS_DP_ENC_RC_OFFSETS_3(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x24)
>> +#define CDNS_DP_ENC_RC_OFFSETS_3_FINAL_OFFSET GENMASK(31, 16)
>> +#define CDNS_DP_ENC_RC_OFFSETS_3_FINAL_OFFSET_SHIFT 16
>> +#define CDNS_DP_ENC_RC_OFFSETS_3_INIT_OFFSET GENMASK(15, 0)
>> +
>> +#define CDNS_DP_ENC_FLATNESS_DETECTION(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x28)
>> +#define CDNS_DP_ENC_FLATNESS_DETECTION_THRESH GENMASK(17, 10)
>> +#define CDNS_DP_ENC_FLATNESS_DETECTION_THRESH_SHIFT 10
>> +#define CDNS_DP_ENC_FLATNESS_DETECTION_MAX_QP GENMASK(9, 5)
>> +#define CDNS_DP_ENC_FLATNESS_DETECTION_MAX_QP_SHIFT 5
>> +#define CDNS_DP_ENC_FLATNESS_DETECTION_MIN_QP GENMASK(4, 0)
>> +
>> +#define CDNS_DP_ENC_RC_MODEL_SIZE(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x2c)
>> +#define CDNS_DP_ENC_RC_MODEL_SIZE_RC_MODEL_SIZE GENMASK(15, 0)
>> +
>> +#define CDNS_DP_ENC_RC_CONFIG(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x30)
>> +#define CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_LO GENMASK(27, 24)
>> +#define CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_LO_SHIFT 24
>> +#define CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_HI GENMASK(23, 20)
>> +#define CDNS_DP_ENC_RC_CONFIG_TGT_OFFSET_HI_SHIFT 20
>> +#define CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_1 GENMASK(17, 13)
>> +#define CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_1_SHIFT 13
>> +#define CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_0 GENMASK(12, 8)
>> +#define CDNS_DP_ENC_RC_CONFIG_QUANT_INC_LIM_0_SHIFT 8
>> +#define CDNS_DP_ENC_RC_CONFIG_EDGE_FACTOR GENMASK(3, 0)
>> +
>> +#define CDNS_DP_ENC_RC_BUF_THRESH_0(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x34)
>> +#define CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_3 GENMASK(31, 24)
>> +#define CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_2 GENMASK(23, 16)
>> +#define CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_1 GENMASK(15, 8)
>> +#define CDNS_DP_ENC_RC_BUF_THRESH_0_THRESH_0 GENMASK(7, 0)
>> +
>> +#define CDNS_DP_ENC_RC_BUF_THRESH_1(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x38)
>> +#define CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_7 GENMASK(31, 24)
>> +#define CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_6 GENMASK(23, 16)
>> +#define CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_5 GENMASK(15, 8)
>> +#define CDNS_DP_ENC_RC_BUF_THRESH_1_THRESH_4 GENMASK(7, 0)
>> +
>> +#define CDNS_DP_ENC_RC_BUF_THRESH_2(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x3c)
>> +#define CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_11 GENMASK(31, 24)
>> +#define CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_10 GENMASK(23, 16)
>> +#define CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_9 GENMASK(15, 8)
>> +#define CDNS_DP_ENC_RC_BUF_THRESH_2_THRESH_8 GENMASK(7, 0)
>> +
>> +#define CDNS_DP_ENC_RC_BUF_THRESH_3(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x40)
>> +#define CDNS_DP_ENC_RC_BUF_THRESH_3_THRESH_13 GENMASK(15, 8)
>> +#define CDNS_DP_ENC_RC_BUF_THRESH_3_THRESH_12 GENMASK(7, 0)
>> +
>> +#define CDNS_DP_ENC_RC_BUF_THRESH_THRESH_3_SHIFT 24
>> +#define CDNS_DP_ENC_RC_BUF_THRESH_THRESH_2_SHIFT 16
>> +#define CDNS_DP_ENC_RC_BUF_THRESH_THRESH_1_SHIFT 8
>> +
>> +#define CDNS_DP_ENC_RC_MIN_QP_0(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x44)
>> +#define CDNS_DP_ENC_RC_MIN_QP_0_RANGE_4 GENMASK(24, 20)
>> +#define CDNS_DP_ENC_RC_MIN_QP_0_RANGE_3 GENMASK(19, 15)
>> +#define CDNS_DP_ENC_RC_MIN_QP_0_RANGE_2 GENMASK(14, 10)
>> +#define CDNS_DP_ENC_RC_MIN_QP_0_RANGE_1 GENMASK(9, 5)
>> +#define CDNS_DP_ENC_RC_MIN_QP_0_RANGE_0 GENMASK(4, 0)
>> +
>> +#define CDNS_DP_ENC_RC_MIN_QP_1(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x48)
>> +#define CDNS_DP_ENC_RC_MIN_QP_1_RANGE_9 GENMASK(24, 20)
>> +#define CDNS_DP_ENC_RC_MIN_QP_1_RANGE_8 GENMASK(19, 15)
>> +#define CDNS_DP_ENC_RC_MIN_QP_1_RANGE_7 GENMASK(14, 10)
>> +#define CDNS_DP_ENC_RC_MIN_QP_1_RANGE_6 GENMASK(9, 5)
>> +#define CDNS_DP_ENC_RC_MIN_QP_1_RANGE_5 GENMASK(4, 0)
>> +
>> +#define CDNS_DP_ENC_RC_MIN_QP_2(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x4c)
>> +#define CDNS_DP_ENC_RC_MIN_QP_2_RANGE_14 GENMASK(24, 20)
>> +#define CDNS_DP_ENC_RC_MIN_QP_2_RANGE_13 GENMASK(19, 15)
>> +#define CDNS_DP_ENC_RC_MIN_QP_2_RANGE_12 GENMASK(14, 10)
>> +#define CDNS_DP_ENC_RC_MIN_QP_2_RANGE_11 GENMASK(9, 5)
>> +#define CDNS_DP_ENC_RC_MIN_QP_2_RANGE_10 GENMASK(4, 0)
>> +
>> +#define CDNS_DP_ENC_RC_MAX_QP_0(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x50)
>> +#define CDNS_DP_ENC_RC_MAX_QP_0_RANGE_4 GENMASK(24, 20)
>> +#define CDNS_DP_ENC_RC_MAX_QP_0_RANGE_3 GENMASK(19, 15)
>> +#define CDNS_DP_ENC_RC_MAX_QP_0_RANGE_2 GENMASK(14, 10)
>> +#define CDNS_DP_ENC_RC_MAX_QP_0_RANGE_1 GENMASK(9, 5)
>> +#define CDNS_DP_ENC_RC_MAX_QP_0_RANGE_0 GENMASK(4, 0)
>> +
>> +#define CDNS_DP_ENC_RC_MAX_QP_1(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x54)
>> +#define CDNS_DP_ENC_RC_MAX_QP_1_RANGE_9 GENMASK(24, 20)
>> +#define CDNS_DP_ENC_RC_MAX_QP_1_RANGE_8 GENMASK(19, 15)
>> +#define CDNS_DP_ENC_RC_MAX_QP_1_RANGE_7 GENMASK(14, 10)
>> +#define CDNS_DP_ENC_RC_MAX_QP_1_RANGE_6 GENMASK(9, 5)
>> +#define CDNS_DP_ENC_RC_MAX_QP_1_RANGE_5 GENMASK(4, 0)
>> +
>> +#define CDNS_DP_ENC_RC_MAX_QP_2(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x58)
>> +#define CDNS_DP_ENC_RC_MAX_QP_2_RANGE_14 GENMASK(24, 20)
>> +#define CDNS_DP_ENC_RC_MAX_QP_2_RANGE_13 GENMASK(19, 15)
>> +#define CDNS_DP_ENC_RC_MAX_QP_2_RANGE_12 GENMASK(14, 10)
>> +#define CDNS_DP_ENC_RC_MAX_QP_2_RANGE_11 GENMASK(9, 5)
>> +#define CDNS_DP_ENC_RC_MAX_QP_2_RANGE_10 GENMASK(4, 0)
>> +
>> +#define CDNS_DP_ENC_RC_QP_RANGE_4_SHIFT 20
>> +#define CDNS_DP_ENC_RC_QP_RANGE_3_SHIFT 15
>> +#define CDNS_DP_ENC_RC_QP_RANGE_2_SHIFT 10
>> +#define CDNS_DP_ENC_RC_QP_RANGE_1_SHIFT 5
>> +
>> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x5c)
>> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_4 GENMASK(24, 20)
>> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_3 GENMASK(19, 15)
>> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_2 GENMASK(14, 10)
>> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_1 GENMASK(9, 5)
>> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_0 GENMASK(4, 0)
>> +
>> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_1(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x60)
>> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_9 GENMASK(24, 20)
>> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_8 GENMASK(19, 15)
>> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_7 GENMASK(14, 10)
>> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_6 GENMASK(9, 5)
>> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_5 GENMASK(4, 0)
>> +
>> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_2(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x64)
>> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_14 GENMASK(24, 20)
>> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_13 GENMASK(19, 15)
>> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_12 GENMASK(14, 10)
>> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_11 GENMASK(9, 5)
>> +#define CDNS_DP_ENC_RC_RANGE_BPG_OFFSETS_0_10 GENMASK(4, 0)
>> +
>> +#define CDNS_DP_ENC_DPI_CTRL_OUT_DELAY(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0x68)
>> +#define CDNS_DP_ENC_DPI_CTRL_OUT_DELAY_CYCLES GENMASK(15, 0)
>> +
>> +#define CDNS_DP_ENC_GENERAL_STATUS(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xa0)
>> +#define CDNS_DP_ENC_GENERAL_STATUS_OUT_BUFF_FULL_1 BIT(6)
>> +#define CDNS_DP_ENC_GENERAL_STATUS_OUT_BUFF_FULL_0 BIT(5)
>> +#define CDNS_DP_ENC_GENERAL_STATUS_OUT_BUFF_EMPTY_1 BIT(4)
>> +#define CDNS_DP_ENC_GENERAL_STATUS_OUT_BUFF_EMPTY_0 BIT(3)
>> +#define CDNS_DP_ENC_GENERAL_STATUS_FRAME_DONE BIT(2)
>> +#define CDNS_DP_ENC_GENERAL_STATUS_FRAME_STARTED BIT(1)
>> +#define CDNS_DP_ENC_GENERAL_STATUS_CE BIT(0)
>> +
>> +#define CDNS_DP_ENC_HSLICE_STATUS(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xa4)
>> +#define CDNS_DP_ENC_HSLICE_STATUS_ACTUAL_SLICE GENMASK(31, 16)
>> +#define CDNS_DP_ENC_HSLICE_STATUS_ACTUAL_LINE GENMASK(15, 0)
>> +
>> +#define CDNS_DP_ENC_OUT_STATUS(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xa8)
>> +#define CDNS_DP_ENC_OUT_STATUS_ACTUAL_SLICE GENMASK(31, 16)
>> +#define CDNS_DP_ENC_OUT_STATUS_ACTUAL_LINE GENMASK(15, 0)
>> +
>> +#define CDNS_DP_ENC_INT_STAT(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xac)
>> +#define CDNS_DP_ENC_INT_STAT_OUT_BUFF_FULL_1 BIT(10)
>> +#define CDNS_DP_ENC_INT_STAT_OUT_BUFF_FULL_0 BIT(9)
>> +#define CDNS_DP_ENC_INT_STAT_OUT_BUFF_EMPTY_1 BIT(8)
>> +#define CDNS_DP_ENC_INT_STAT_OUT_BUFF_EMPTY_0 BIT(7)
>> +#define CDNS_DP_ENC_INT_STAT_FRAME_DONE BIT(6)
>> +#define CDNS_DP_ENC_INT_STAT_FRAME_STARTED BIT(5)
>> +#define CDNS_DP_ENC_INT_STAT_CE BIT(4)
>> +#define CDNS_DP_ENC_INT_STAT_RC_BUFF_OVER_1 BIT(3)
>> +#define CDNS_DP_ENC_INT_STAT_RC_BUFF_OVER_0 BIT(2)
>> +#define CDNS_DP_ENC_INT_STAT_OUT_BUFF_UND_1 BIT(1)
>> +#define CDNS_DP_ENC_INT_STAT_OUT_BUFF_UND_0 BIT(0)
>> +
>> +#define CDNS_DP_ENC_INT_CLR(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xb0)
>> +#define CDNS_DP_ENC_INT_CLR_OUT_BUFF_FULL_1 BIT(10)
>> +#define CDNS_DP_ENC_INT_CLR_OUT_BUFF_FULL_0 BIT(9)
>> +#define CDNS_DP_ENC_INT_CLR_OUT_BUFF_EMPTY_1 BIT(8)
>> +#define CDNS_DP_ENC_INT_CLR_OUT_BUFF_EMPTY_0 BIT(7)
>> +#define CDNS_DP_ENC_INT_CLR_FRAME_DONE BIT(6)
>> +#define CDNS_DP_ENC_INT_CLR_FRAME_STARTED BIT(5)
>> +#define CDNS_DP_ENC_INT_CLR_CE BIT(4)
>> +#define CDNS_DP_ENC_INT_CLR_RC_BUFF_OVER_1 BIT(3)
>> +#define CDNS_DP_ENC_INT_CLR_RC_BUFF_OVER_0 BIT(2)
>> +#define CDNS_DP_ENC_INT_CLR_OUT_BUFF_UND_1 BIT(1)
>> +#define CDNS_DP_ENC_INT_CLR_OUT_BUFF_UND_0 BIT(0)
>> +
>> +#define CDNS_DP_ENC_INT_MASK(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xb4)
>> +#define CDNS_DP_ENC_INT_MASK_OUT_BUFF_FULL_1 BIT(10)
>> +#define CDNS_DP_ENC_INT_MASK_OUT_BUFF_FULL_0 BIT(9)
>> +#define CDNS_DP_ENC_INT_MASK_OUT_BUFF_EMPTY_1 BIT(8)
>> +#define CDNS_DP_ENC_INT_MASK_OUT_BUFF_EMPTY_0 BIT(7)
>> +#define CDNS_DP_ENC_INT_MASK_FRAME_DONE BIT(6)
>> +#define CDNS_DP_ENC_INT_MASK_FRAME_STARTED BIT(5)
>> +#define CDNS_DP_ENC_INT_MASK_CE BIT(4)
>> +#define CDNS_DP_ENC_INT_MASK_RC_BUFF_OVER_1 BIT(3)
>> +#define CDNS_DP_ENC_INT_MASK_RC_BUFF_OVER_0 BIT(2)
>> +#define CDNS_DP_ENC_INT_MASK_OUT_BUFF_UND_1 BIT(1)
>> +#define CDNS_DP_ENC_INT_MASK_OUT_BUFF_UND_0 BIT(0)
>> +
>> +#define CDNS_DP_ENC_INT_TEST(d) (CDNS_DP_ENC_MAIN_CONF(d) + 0xb8)
>> +#define CDNS_DP_ENC_INT_TEST_OUT_BUFF_FULL_1 BIT(10)
>> +#define CDNS_DP_ENC_INT_TEST_OUT_BUFF_FULL_0 BIT(9)
>> +#define CDNS_DP_ENC_INT_TEST_OUT_BUFF_EMPTY_1 BIT(8)
>> +#define CDNS_DP_ENC_INT_TEST_OUT_BUFF_EMPTY_0 BIT(7)
>> +#define CDNS_DP_ENC_INT_TEST_FRAME_DONE BIT(6)
>> +#define CDNS_DP_ENC_INT_TEST_FRAME_STARTED BIT(5)
>> +#define CDNS_DP_ENC_INT_TEST_CE BIT(4)
>> +#define CDNS_DP_ENC_INT_TEST_RC_BUFF_OVER_1 BIT(3)
>> +#define CDNS_DP_ENC_INT_TEST_RC_BUFF_OVER_0 BIT(2)
>> +#define CDNS_DP_ENC_INT_TEST_OUT_BUFF_UND_1 BIT(1)
>> +#define CDNS_DP_ENC_INT_TEST_OUT_BUFF_UND_0 BIT(0)
>> +
>> +void cdns_mhdp_dsc_write_config(struct cdns_mhdp_device *mhdp);
>> +void cdns_mhdp_dsc_write_enc_config(struct cdns_mhdp_device *mhdp, int stream_id,
>> + const struct drm_display_mode *mode);
>> +int cdns_mhdp_dsc_sink_support(struct cdns_mhdp_device *mhdp);
>> +int cdns_mhdp_compute_dsc_params(struct cdns_mhdp_device *mhdp);
>> +int cdns_mhdp_dsc_send_pps_sdp(struct cdns_mhdp_device *mhdp, int stream_id);
>> +
>> +#endif /* MHDP_DSC_H_ */
>> --
>> 2.34.1
Regards.
Hari
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v5 1/2] dt-bindings: drm/bridge: MHDP8546 bridge binding changes for DSC
[not found] ` <d2367789-6b54-4fc2-bb7c-609c0fe084d3@ti.com>
@ 2025-10-17 10:58 ` Harikrishna shenoy
0 siblings, 0 replies; 9+ messages in thread
From: Harikrishna shenoy @ 2025-10-17 10:58 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: andrzej.hajda, neil.armstrong, rfoss, Laurent.pinchart, jonas,
jernej.skrabec, airlied, simona, maarten.lankhorst, mripard,
tzimmermann, robh, krzk+dt, conor+dt, sjakhade, yamonkar, lumag,
dianders, jani.nikula, luca.ceresoli, andy.yan, dri-devel,
devicetree, linux-kernel, devarsht, u-kumar1, s-jain1,
tomi.valkeinen
On 22/09/25 13:11, Harikrishna Shenoy wrote:
>
>
> On 9/18/25 07:00, Krzysztof Kozlowski wrote:
>> On Mon, Sep 15, 2025 at 04:00:40PM +0530, Harikrishna Shenoy wrote:
>>> From: Swapnil Jakhade<sjakhade@cadence.com>
>>>
>>> Add binding changes for DSC(Display Stream Compression) in the MHDP8546
>>> DPI/DP bridge.
>>>
>>> Signed-off-by: Swapnil Jakhade<sjakhade@cadence.com>
>>> Signed-off-by: Harikrishna Shenoy<h-shenoy@ti.com>
>>> ---
>>> .../display/bridge/cdns,mhdp8546.yaml | 24 ++++++++++++-------
>>> 1 file changed, 15 insertions(+), 9 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8546.yaml b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8546.yaml
>>> index c2b369456e4e..2a05a7d5847f 100644
>>> --- a/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8546.yaml
>>> +++ b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8546.yaml
>>> @@ -27,13 +27,12 @@ properties:
>>> Register block for DSS_EDP0_INTG_CFG_VP registers in case of TI J7 SoCs.
>>> - description:
>>> Register block of mhdptx sapb registers.
>>> + - description:
>>> + Register block for mhdptx DSC encoder registers.
>>>
>>> reg-names:
>>> - minItems: 1
>>> - items:
>>> - - const: mhdptx
>>> - - const: j721e-intg
>>> - - const: mhdptx-sapb
>>> + description:
>>> + Names corresponding to entries in the reg property.
>> No, top-level should have broadest constraints. In your case it is
>> min/maxItems.
>>
>> Description is completely redundant. Wasn't here before, so why adding
>> it?
>>
> Noted, will remove description and add minItems:1.
>>>
>>> clocks:
>>> maxItems: 1
>>> @@ -100,18 +99,25 @@ allOf:
>>> properties:
>>> reg:
>>> minItems: 2
>>> - maxItems: 3
>>> + maxItems: 4
>>> reg-names:
>>> minItems: 2
>>> - maxItems: 3
>>> + items:
>>> + - const: mhdptx
>>> + - const: j721e-intg
>>> + - const: mhdptx-sapb
>>> + - const: dsc
>>> else:
>>> properties:
>>> reg:
>>> minItems: 1
>>> - maxItems: 2
>>> + maxItems: 3
>>> reg-names:
>>> minItems: 1
>>> - maxItems: 2
>>> + items:
>>> + - const: mhdptx
>>> + - const: mhdptx-sapb
>> This is wrong. Previously CDNS variant had two items means it had
>> "j721e-intg". Now it's something else.
>>
>> First, this is an ABI break.
>>
>> Second, there is no explanation at all for it in the commit msg! Looks
>> like random change.
>>
>> Read carefully writing-bindings doc.
>>
>> Best regards,
>> Krzysztof
>>
>
> Hi Krzysztof,
>
>
> Keeping this patch series aside, The existing binding-docs clearly have
> a bug.
>
> Since even for cadence specific compatible "cdns,mhdp8546" it
> compulsorily expects "j721e-intg" register space
>
> which is NOT part of the cadence IP block mhdp8546 and hence not
> applicable to "cdns,mhdp8546".
>
> This was also discussed here [1] and can also be referred in this TRM
> section [2],
>
> which clearly show that "j721e-intg" is part of TI wrapper IP block and
> should be
>
> applicable to "ti,j721e-mhdp8546" compatible.
>
> Yes agreed it breaks the ABI but it also fixes a bug and I don't see any
> one using only "cdns,mhdp8546" yet.
>
> so I am thinking it's more appropriate to fix this as a separate patch
> independent of this series.
>
> Kindly let me know if I should submit a separate patch to fix this bug
> or I should just ignore this bug.
>
> Depending on your suggestion, if it's agreed upon to send the bug fix
> patch first, I will send out an independent
>
> bug fix to remove "j721e-intg" for compatible "cdns,mhdp8546" and then
> rebase the series for adding DSC reg blocks
>
> on top of bug fix.
>
> [1]: https://lore.kernel.org/all/20250903220312.GA2903503-
> robh@kernel.org/ <https://lore.kernel.org/all/20250903220312.GA2903503-
> robh@kernel.org/>
> [2]: Link to TRM ZIP:https://www.ti.com/lit/zip/spruil1 <https://
> www.ti.com/lit/zip/spruil1>
> Table 2-1. MAIN Domain Memory Map
> DSS_EDP0_V2A_CORE_VP_REGS_APB are EDP core register identified by name
> mhdptx in DT.
> DSS_EDP0_INTG_CFG_VP identified by j721e-intg in DT.
>
> Section 12.6.6.16.4: EDP_CFG Registers
>
> Driver use: TI j721e Cadence MHDP8546 DP wrapper(drivers/gpu/drm/bridge/
> cadence/cdns-mhdp8546-j721e.c)
>
>
> Regards.
Hi Krzysztof,
Could you please let us know your thoughts on above, will re-spin it
accordingly.
Regards.
>
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-10-17 10:58 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-15 10:30 [PATCH v5 0/2] Add support for DSC and FEC for cadence MHDP8546 bridge Harikrishna Shenoy
2025-09-15 10:30 ` [PATCH v5 1/2] dt-bindings: drm/bridge: MHDP8546 bridge binding changes for DSC Harikrishna Shenoy
2025-09-18 1:30 ` Krzysztof Kozlowski
[not found] ` <d2367789-6b54-4fc2-bb7c-609c0fe084d3@ti.com>
2025-10-17 10:58 ` Harikrishna shenoy
2025-09-15 10:30 ` [PATCH v5 2/2] drm: bridge: cdns-mhdp8546: Add support for DSC and FEC Harikrishna Shenoy
2025-09-15 11:06 ` Dmitry Baryshkov
2025-09-15 18:53 ` Dmitry Baryshkov
2025-09-30 12:41 ` Harikrishna Shenoy
2025-09-19 19:38 ` kernel test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).