From: Chaoyi Chen <kernel@airkyi.com>
To: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
Maxime Ripard <mripard@kernel.org>,
Thomas Zimmermann <tzimmermann@suse.de>,
David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>,
Dmitry Baryshkov <lumag@kernel.org>
Cc: Chaoyi Chen <chaoyi.chen@rock-chips.com>,
dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
Chaoyi Chen <kernel@airkyi.com>
Subject: [PATCH] drm/display/dsc: Add YCbCr 4:2:2 and 4:2:0 computation for DSC 1.2 RC parameters
Date: Wed, 23 Sep 2026 18:26:16 +0800 [thread overview]
Message-ID: <20260923102616.215-1-kernel@airkyi.com> (raw)
drm_dsc_compute_rc_parameters() still derives the rate control
parameters that depend on native 4:2:0/4:2:2 operation using the
DSC 1.1 model.
Bring the helper in line with the latest DSC 1.2 reference
implementation (C model 20211213, version 1.67):
- Compute second_line_bpg_offset, second_line_offset_adj and
nsl_bpg_offset for native 4:2:0.
- Compute rbsMin for DSC 1.2 native 4:2:0/4:2:2 using the optimized
method of the C model.
Signed-off-by: Chaoyi Chen <kernel@airkyi.com>
---
drivers/gpu/drm/display/drm_dsc_helper.c | 114 ++++++++++++++++++++++-
1 file changed, 109 insertions(+), 5 deletions(-)
mode change 100644 => 100755 drivers/gpu/drm/display/drm_dsc_helper.c
diff --git a/drivers/gpu/drm/display/drm_dsc_helper.c b/drivers/gpu/drm/display/drm_dsc_helper.c
index 05996c526a8a..90b088335997
--- a/drivers/gpu/drm/display/drm_dsc_helper.c
+++ b/drivers/gpu/drm/display/drm_dsc_helper.c
@@ -1300,6 +1300,59 @@ int drm_dsc_setup_rc_params(struct drm_dsc_config *vdsc_cfg, enum drm_dsc_params
}
EXPORT_SYMBOL(drm_dsc_setup_rc_params);
+/**
+ * __drm_dsc_compute_buffer_offset - Compute the rate buffer offset at a given
+ * group position within a slice, following the method of the DSC 1.2 C model.
+ *
+ * @vdsc_cfg: DSC Configuration data partially filled by driver
+ * @groups_per_line: number of groups used to code each line of a slice
+ * @grpcnt: group position to compute the offset for
+ *
+ * Return: the offset value for the group @grpcnt.
+ */
+static long
+__drm_dsc_compute_buffer_offset(const struct drm_dsc_config *vdsc_cfg,
+ unsigned long groups_per_line,
+ unsigned long grpcnt)
+{
+ unsigned long grpcnt_id = DIV_ROUND_UP(vdsc_cfg->initial_xmit_delay,
+ DSC_RC_PIXELS_PER_GROUP);
+ long offset;
+
+ if (grpcnt <= grpcnt_id)
+ offset = DIV_ROUND_UP(grpcnt * DSC_RC_PIXELS_PER_GROUP *
+ vdsc_cfg->bits_per_pixel, 16);
+ else
+ offset = DIV_ROUND_UP(grpcnt_id * DSC_RC_PIXELS_PER_GROUP *
+ vdsc_cfg->bits_per_pixel, 16) -
+ (((grpcnt - grpcnt_id) *
+ vdsc_cfg->slice_bpg_offset) >> 11);
+
+ if (grpcnt <= groups_per_line)
+ offset += grpcnt * vdsc_cfg->first_line_bpg_offset;
+ else
+ offset += groups_per_line * vdsc_cfg->first_line_bpg_offset -
+ (((grpcnt - groups_per_line) *
+ vdsc_cfg->nfl_bpg_offset) >> 11);
+
+ if (vdsc_cfg->native_420) {
+ if (grpcnt <= groups_per_line)
+ offset -= (grpcnt * vdsc_cfg->nsl_bpg_offset) >> 11;
+ else if (grpcnt <= 2 * groups_per_line)
+ offset += (grpcnt - groups_per_line) *
+ vdsc_cfg->second_line_bpg_offset -
+ ((groups_per_line *
+ vdsc_cfg->nsl_bpg_offset) >> 11);
+ else
+ offset += (grpcnt - groups_per_line) *
+ vdsc_cfg->second_line_bpg_offset -
+ (((grpcnt - groups_per_line) *
+ vdsc_cfg->nsl_bpg_offset) >> 11);
+ }
+
+ return offset;
+}
+
/**
* drm_dsc_compute_rc_parameters() - Write rate control
* parameters to the dsc configuration defined in
@@ -1391,6 +1444,36 @@ int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg)
else
vdsc_cfg->nfl_bpg_offset = 0;
+ /*
+ * According to DSC 1.2 spec in Section 4.1 if native_420 is set:
+ * -second_line_bpg_offset is 12 in general and equal to 2*(slice_height-1) if slice
+ * height < 8.
+ * -second_line_offset_adj is 512 as shown by emperical values to yield best chroma
+ * preservation in second line.
+ * -nsl_bpg_offset is calculated as second_line_offset/slice_height -1 then rounded
+ * up to 16 fractional bits, we left shift second line offset by 11 to preserve 11
+ * fractional bits.
+ */
+ if (vdsc_cfg->native_420) {
+ if (vdsc_cfg->slice_height >= 8)
+ vdsc_cfg->second_line_bpg_offset = 12;
+ else
+ vdsc_cfg->second_line_bpg_offset =
+ 2 * (vdsc_cfg->slice_height - 1);
+
+ vdsc_cfg->second_line_offset_adj = 512;
+ } else {
+ vdsc_cfg->second_line_bpg_offset = 0;
+ vdsc_cfg->second_line_offset_adj = 0;
+ }
+
+ if (vdsc_cfg->native_420 && vdsc_cfg->slice_height > 2)
+ vdsc_cfg->nsl_bpg_offset =
+ DIV_ROUND_UP(vdsc_cfg->second_line_bpg_offset << 11,
+ (vdsc_cfg->slice_height - 1));
+ else
+ vdsc_cfg->nsl_bpg_offset = 0;
+
/* Number of groups used to code the entire slice */
groups_total = groups_per_line * vdsc_cfg->slice_height;
@@ -1410,7 +1493,9 @@ int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg)
vdsc_cfg->scale_increment_interval =
(vdsc_cfg->final_offset * (1 << 11)) /
((vdsc_cfg->nfl_bpg_offset +
- vdsc_cfg->slice_bpg_offset) *
+ vdsc_cfg->slice_bpg_offset +
+ (vdsc_cfg->native_420 ?
+ vdsc_cfg->nsl_bpg_offset : 0)) *
(final_scale - 9));
} else {
/*
@@ -1425,10 +1510,29 @@ int drm_dsc_compute_rc_parameters(struct drm_dsc_config *vdsc_cfg)
* bits/pixel (bpp) rate that is used by the encoder,
* in steps of 1/16 of a bit per pixel
*/
- rbs_min = vdsc_cfg->rc_model_size - vdsc_cfg->initial_offset +
- DIV_ROUND_UP(vdsc_cfg->initial_xmit_delay *
- vdsc_cfg->bits_per_pixel, 16) +
- groups_per_line * vdsc_cfg->first_line_bpg_offset;
+ if (vdsc_cfg->dsc_version_minor == 2 &&
+ (vdsc_cfg->native_420 || vdsc_cfg->native_422)) {
+ /* Optimized computation of rbsMin for DSC 1.2 */
+ unsigned long grpcnt_id =
+ DIV_ROUND_UP(vdsc_cfg->initial_xmit_delay,
+ DSC_RC_PIXELS_PER_GROUP);
+ long max_offset;
+
+ max_offset = __drm_dsc_compute_buffer_offset(vdsc_cfg, groups_per_line, grpcnt_id);
+ max_offset = max(max_offset,
+ __drm_dsc_compute_buffer_offset(vdsc_cfg, groups_per_line,
+ groups_per_line));
+ max_offset = max(max_offset,
+ __drm_dsc_compute_buffer_offset(vdsc_cfg, groups_per_line,
+ 2 * groups_per_line));
+
+ rbs_min = vdsc_cfg->rc_model_size - vdsc_cfg->initial_offset + max_offset;
+ } else {
+ rbs_min = vdsc_cfg->rc_model_size - vdsc_cfg->initial_offset +
+ DIV_ROUND_UP(vdsc_cfg->initial_xmit_delay *
+ vdsc_cfg->bits_per_pixel, 16) +
+ groups_per_line * vdsc_cfg->first_line_bpg_offset;
+ }
hrd_delay = DIV_ROUND_UP((rbs_min * 16), vdsc_cfg->bits_per_pixel);
vdsc_cfg->rc_bits = (hrd_delay * vdsc_cfg->bits_per_pixel) / 16;
--
2.53.0
next reply other threads:[~2026-09-23 10:27 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-23 10:26 Chaoyi Chen [this message]
2026-09-23 10:34 ` [PATCH] drm/display/dsc: Add YCbCr 4:2:2 and 4:2:0 computation for DSC 1.2 RC parameters sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260923102616.215-1-kernel@airkyi.com \
--to=kernel@airkyi.com \
--cc=airlied@gmail.com \
--cc=chaoyi.chen@rock-chips.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lumag@kernel.org \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mripard@kernel.org \
--cc=simona@ffwll.ch \
--cc=tzimmermann@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.