From: Imre Deak <imre.deak@intel.com>
To: "Ville Syrjälä" <ville.syrjala@linux.intel.com>
Cc: <intel-gfx@lists.freedesktop.org>,
<intel-xe@lists.freedesktop.org>,
<dri-devel@lists.freedesktop.org>
Subject: Re: [PATCH v5 2/6] drm/dp: Add helpers to query the branch DSC max throughput/line-width
Date: Mon, 29 Sep 2025 13:47:29 +0300 [thread overview]
Message-ID: <aNpjwQcvbQL0Gu9y@ideak-desk> (raw)
In-Reply-To: <aNpbf4HJDrtbsuex@intel.com>
On Mon, Sep 29, 2025 at 01:12:15PM +0300, Ville Syrjälä wrote:
> On Mon, Sep 29, 2025 at 09:36:44AM +0300, Imre Deak wrote:
> > Add helpers to query the DP DSC sink device's per-slice throughput as
> > well as a DSC branch device's overall throughput and line-width
> > capabilities.
> >
> > v2 (Ville):
> > - Rename pixel_clock to peak_pixel_rate, document what the value means
> > in case of MST tiled displays.
> > - Fix name of drm_dp_dsc_branch_max_slice_throughput() to
> > drm_dp_dsc_sink_max_slice_throughput().
> > v3:
> > - Fix the DSC branch device minimum valid line width value from 2560
> > to 5120 pixels.
> > - Fix drm_dp_dsc_sink_max_slice_throughput()'s pixel_clock parameter
> > name to peak_pixel_rate in header file.
> > - Add handling for throughput mode 0 granular delta, defined by DP
> > Standard v2.1a.
> >
> > Cc: dri-devel@lists.freedesktop.org
> > Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> > drivers/gpu/drm/display/drm_dp_helper.c | 156 ++++++++++++++++++++++++
> > include/drm/display/drm_dp.h | 3 +
> > include/drm/display/drm_dp_helper.h | 5 +
> > 3 files changed, 164 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c
> > index 1c74fe9459ad9..6084ca7fbe263 100644
> > --- a/drivers/gpu/drm/display/drm_dp_helper.c
> > +++ b/drivers/gpu/drm/display/drm_dp_helper.c
> > @@ -2844,6 +2844,162 @@ int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_S
> > }
> > EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs);
> >
> > +/*
> > + * See DP Standard v2.1a 2.8.4 Minimum Slices/Display, Table 2-159 and
> > + * Appendix L.1 Derivation of Slice Count Requirements.
> > + */
> > +static int dsc_sink_min_slice_throughput(int peak_pixel_rate)
> > +{
> > + if (peak_pixel_rate >= 4800000)
> > + return 600000;
> > + else if (peak_pixel_rate >= 2700000)
> > + return 400000;
> > + else
> > + return 340000;
> > +}
> > +
> > +/**
> > + * drm_dp_dsc_sink_max_slice_throughput() - Get a DSC sink's maximum pixel throughput per slice
> > + * @dsc_dpcd: DSC sink's capabilities from DPCD
> > + * @peak_pixel_rate: Cumulative peak pixel rate in kHz
> > + * @is_rgb_yuv444: The mode is either RGB or YUV444
> > + *
> > + * Return the DSC sink device's maximum pixel throughput per slice, based on
> > + * the device's @dsc_dpcd capabilities, the @peak_pixel_rate of the transferred
> > + * stream(s) and whether the output format @is_rgb_yuv444 or yuv422/yuv420.
> > + *
> > + * Note that @peak_pixel_rate is the total pixel rate transferred to the same
> > + * DSC/display sink. For instance to calculate a tile's slice count of an MST
> > + * multi-tiled display sink (not considering here the required
> > + * rounding/alignment of slice count)::
> > + *
> > + * @peak_pixel_rate = tile_pixel_rate * tile_count
> > + * total_slice_count = @peak_pixel_rate / drm_dp_dsc_sink_max_slice_throughput(@peak_pixel_rate)
> > + * tile_slice_count = total_slice_count / tile_count
> > + *
> > + * Returns:
> > + * The maximum pixel throughput per slice supported by the DSC sink device
> > + * in kPixels/sec.
> > + */
> > +int drm_dp_dsc_sink_max_slice_throughput(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE],
> > + int peak_pixel_rate, bool is_rgb_yuv444)
> > +{
> > + int throughput;
> > + int delta = 0;
> > + int base;
> > +
> > + throughput = dsc_dpcd[DP_DSC_PEAK_THROUGHPUT - DP_DSC_SUPPORT];
> > +
> > + if (is_rgb_yuv444) {
> > + throughput = (throughput & DP_DSC_THROUGHPUT_MODE_0_MASK) >>
> > + DP_DSC_THROUGHPUT_MODE_0_SHIFT;
> > +
> > + delta = ((dsc_dpcd[DP_DSC_RC_BUF_BLK_SIZE - DP_DSC_SUPPORT]) &
> > + DP_DSC_THROUGHPUT_MODE_0_DELTA_MASK) >>
> > + DP_DSC_THROUGHPUT_MODE_0_DELTA_SHIFT; /* in units of 2 MPixels/sec */
> > + delta *= 2000;
>
> That thing really is very poorly documented. The DSC spec has a
> note about possibly needing extra throughput at the right edges
> of slices due to some alignment reasons. Maybe this is for that?
> Dunno.
I assumed it's for the sink to be able to specify the throughput in a
smaller granularity, so the calculated slice count is then also closer
to the actual requirement. But yes, could be for another reason too,
I'll reread the DSC spec too.
> And the fact that there is a delta just for the 4:4:4 throughput
> is also rather weird.
Yes it is, but that's what the Standard says, unless I missed something.
> > + } else {
> > + throughput = (throughput & DP_DSC_THROUGHPUT_MODE_1_MASK) >>
> > + DP_DSC_THROUGHPUT_MODE_1_SHIFT;
> > + }
> > +
> > + switch (throughput) {
> > + case 0:
> > + return dsc_sink_min_slice_throughput(peak_pixel_rate);
> > + case 1:
> > + base = 340000;
> > + break;
> > + case 2 ... 14:
> > + base = 400000 + 50000 * (throughput - 2);
> > + break;
> > + case 15:
> > + base = 170000;
> > + break;
> > + default:
> > + WARN(1, "Missing case %d\n", throughput);
> > + base = 340000;
> > + break;
>
> nit: that looks like an impossible situation. Could either nuke
> the default case, or if the compiler/static checks are dumb
> then get rid of the 2...14 case instead.
Yes, the compiler should catch an unhandled case and atm the default
case could cause an an unreachable code compiler warn. Will remove the
default case.
> Anyways, for the series
> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Thanks!
> > + }
> > +
> > + return base + delta;
> > +}
> > +EXPORT_SYMBOL(drm_dp_dsc_sink_max_slice_throughput);
> > +
> > +static u8 dsc_branch_dpcd_cap(const u8 dpcd[DP_DSC_BRANCH_CAP_SIZE], int reg)
> > +{
> > + return dpcd[reg - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0];
> > +}
> > +
> > +/**
> > + * drm_dp_dsc_branch_max_overall_throughput() - Branch device's max overall DSC pixel throughput
> > + * @dsc_branch_dpcd: DSC branch capabilities from DPCD
> > + * @is_rgb_yuv444: The mode is either RGB or YUV444
> > + *
> > + * Return the branch device's maximum overall DSC pixel throughput, based on
> > + * the device's DPCD DSC branch capabilities, and whether the output
> > + * format @is_rgb_yuv444 or yuv422/yuv420.
> > + *
> > + * Returns:
> > + * - 0: The maximum overall throughput capability is not indicated by
> > + * the device separately and it must be determined from the per-slice
> > + * max throughput (see @drm_dp_dsc_branch_slice_max_throughput())
> > + * and the maximum slice count supported by the device.
> > + * - > 0: The maximum overall DSC pixel throughput supported by the branch
> > + * device in kPixels/sec.
> > + */
> > +int drm_dp_dsc_branch_max_overall_throughput(const u8 dsc_branch_dpcd[DP_DSC_BRANCH_CAP_SIZE],
> > + bool is_rgb_yuv444)
> > +{
> > + int throughput;
> > +
> > + if (is_rgb_yuv444)
> > + throughput = dsc_branch_dpcd_cap(dsc_branch_dpcd,
> > + DP_DSC_BRANCH_OVERALL_THROUGHPUT_0);
> > + else
> > + throughput = dsc_branch_dpcd_cap(dsc_branch_dpcd,
> > + DP_DSC_BRANCH_OVERALL_THROUGHPUT_1);
> > +
> > + switch (throughput) {
> > + case 0:
> > + return 0;
> > + case 1:
> > + return 680000;
> > + default:
> > + return 600000 + 50000 * throughput;
> > + }
> > +}
> > +EXPORT_SYMBOL(drm_dp_dsc_branch_max_overall_throughput);
> > +
> > +/**
> > + * drm_dp_dsc_branch_max_line_width() - Branch device's max DSC line width
> > + * @dsc_branch_dpcd: DSC branch capabilities from DPCD
> > + *
> > + * Return the branch device's maximum overall DSC line width, based on
> > + * the device's @dsc_branch_dpcd capabilities.
> > + *
> > + * Returns:
> > + * - 0: The maximum line width is not indicated by the device
> > + * separately and it must be determined from the maximum
> > + * slice count and slice-width supported by the device.
> > + * - %-EINVAL: The device indicates an invalid maximum line width
> > + * (< 5120 pixels).
> > + * - >= 5120: The maximum line width in pixels.
> > + */
> > +int drm_dp_dsc_branch_max_line_width(const u8 dsc_branch_dpcd[DP_DSC_BRANCH_CAP_SIZE])
> > +{
> > + int line_width = dsc_branch_dpcd_cap(dsc_branch_dpcd, DP_DSC_BRANCH_MAX_LINE_WIDTH);
> > +
> > + switch (line_width) {
> > + case 0:
> > + return 0;
> > + case 1 ... 15:
> > + return -EINVAL;
> > + default:
> > + return line_width * 320;
> > + }
> > +}
> > +EXPORT_SYMBOL(drm_dp_dsc_branch_max_line_width);
> > +
> > static int drm_dp_read_lttpr_regs(struct drm_dp_aux *aux,
> > const u8 dpcd[DP_RECEIVER_CAP_SIZE], int address,
> > u8 *buf, int buf_size)
> > diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h
> > index cf318e3ddb5c5..e4eebabab9759 100644
> > --- a/include/drm/display/drm_dp.h
> > +++ b/include/drm/display/drm_dp.h
> > @@ -258,6 +258,8 @@
> > # define DP_DSC_RC_BUF_BLK_SIZE_4 0x1
> > # define DP_DSC_RC_BUF_BLK_SIZE_16 0x2
> > # define DP_DSC_RC_BUF_BLK_SIZE_64 0x3
> > +# define DP_DSC_THROUGHPUT_MODE_0_DELTA_SHIFT 3 /* DP 2.1a, in units of 2 MPixels/sec */
> > +# define DP_DSC_THROUGHPUT_MODE_0_DELTA_MASK (0x1f << DP_DSC_THROUGHPUT_MODE_0_DELTA_SHIFT)
> >
> > #define DP_DSC_RC_BUF_SIZE 0x063
> >
> > @@ -1686,6 +1688,7 @@ enum drm_dp_phy {
> > #define DP_BRANCH_OUI_HEADER_SIZE 0xc
> > #define DP_RECEIVER_CAP_SIZE 0xf
> > #define DP_DSC_RECEIVER_CAP_SIZE 0x10 /* DSC Capabilities 0x60 through 0x6F */
> > +#define DP_DSC_BRANCH_CAP_SIZE 3
> > #define EDP_PSR_RECEIVER_CAP_SIZE 2
> > #define EDP_DISPLAY_CTL_CAP_SIZE 5
> > #define DP_LTTPR_COMMON_CAP_SIZE 8
> > diff --git a/include/drm/display/drm_dp_helper.h b/include/drm/display/drm_dp_helper.h
> > index e438c44409952..df2f24b950e4c 100644
> > --- a/include/drm/display/drm_dp_helper.h
> > +++ b/include/drm/display/drm_dp_helper.h
> > @@ -211,6 +211,11 @@ u8 drm_dp_dsc_sink_max_slice_count(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE],
> > u8 drm_dp_dsc_sink_line_buf_depth(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE]);
> > int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpc[DP_DSC_RECEIVER_CAP_SIZE],
> > u8 dsc_bpc[3]);
> > +int drm_dp_dsc_sink_max_slice_throughput(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE],
> > + int peak_pixel_rate, bool is_rgb_yuv444);
> > +int drm_dp_dsc_branch_max_overall_throughput(const u8 dsc_branch_dpcd[DP_DSC_BRANCH_CAP_SIZE],
> > + bool is_rgb_yuv444);
> > +int drm_dp_dsc_branch_max_line_width(const u8 dsc_branch_dpcd[DP_DSC_BRANCH_CAP_SIZE]);
> >
> > static inline bool
> > drm_dp_sink_supports_dsc(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_SIZE])
> > --
> > 2.49.1
>
> --
> Ville Syrjälä
> Intel
next prev parent reply other threads:[~2025-09-29 10:47 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-26 21:12 [PATCH v4 0/6] drm/i915/dp: Work around a DSC pixel throughput issue Imre Deak
2025-09-26 21:12 ` [PATCH v4 1/6] drm/dp: Add quirk for Synaptics DSC throughput link-bpp limit Imre Deak
2025-09-26 21:12 ` [PATCH v4 2/6] drm/dp: Add helpers to query the branch DSC max throughput/line-width Imre Deak
2025-09-29 6:36 ` [PATCH v5 " Imre Deak
2025-09-29 9:00 ` Dmitry Baryshkov
2025-09-29 10:10 ` Imre Deak
2025-09-30 5:30 ` Dmitry Baryshkov
2025-09-30 11:38 ` Imre Deak
2025-09-30 20:04 ` Dmitry Baryshkov
2025-09-30 21:03 ` Imre Deak
2025-09-29 10:12 ` Ville Syrjälä
2025-09-29 10:47 ` Imre Deak [this message]
2025-09-26 21:12 ` [PATCH v4 3/6] drm/i915/dp: Calculate DSC slice count based on per-slice peak throughput Imre Deak
2025-09-26 21:12 ` [PATCH v4 4/6] drm/i915/dp: Pass DPCD device descriptor to intel_dp_get_dsc_sink_cap() Imre Deak
2025-09-26 21:12 ` [PATCH v4 5/6] drm/i915/dp: Verify branch devices' overall pixel throughput/line width Imre Deak
2025-09-26 21:12 ` [PATCH v4 6/6] drm/i915/dp: Handle Synaptics DSC throughput link-bpp quirk Imre Deak
2025-09-26 22:04 ` ✓ i915.CI.BAT: success for drm/i915/dp: Work around a DSC pixel throughput issue (rev5) Patchwork
2025-09-27 3:08 ` ✓ i915.CI.Full: " Patchwork
2025-09-29 7:24 ` ✓ i915.CI.BAT: success for drm/i915/dp: Work around a DSC pixel throughput issue (rev6) Patchwork
2025-09-29 9:02 ` ✗ i915.CI.Full: failure " Patchwork
2025-09-29 21:47 ` [PATCH v4 0/6] drm/i915/dp: Work around a DSC pixel throughput issue Sharma, Swati2
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=aNpjwQcvbQL0Gu9y@ideak-desk \
--to=imre.deak@intel.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=intel-gfx@lists.freedesktop.org \
--cc=intel-xe@lists.freedesktop.org \
--cc=ville.syrjala@linux.intel.com \
/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 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).