From: Jani Nikula <jani.nikula@intel.com>
To: "Michał Grzelak" <michal.grzelak@intel.com>,
intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org
Cc: "Suraj Kandpal" <suraj.kandpal@intel.com>,
"Michał Grzelak" <michal.grzelak@intel.com>
Subject: Re: [PATCH v10 6/8] drm/i915: override Snps's VS/PE when requested
Date: Tue, 11 Aug 2026 18:48:55 +0300 [thread overview]
Message-ID: <85c105f4619e348618c048f0ae3e0f8bc49d947b@intel.com> (raw)
In-Reply-To: <20260702185839.4042397-7-michal.grzelak@intel.com>
On Thu, 02 Jul 2026, Michał Grzelak <michal.grzelak@intel.com> wrote:
> Add accessor function for Snps to read requested table from VBT #57.
> Parse the requested table and transform data into port's buffer.
>
> Choose appropriate accessor function in intel_ddi_buf_trans_get() based
> on display version and PHY type.
>
> For C20, use 6th table if encoder supports DP 2.0 or higher. Otherwise
> use 5th table for DP.
>
> For C20, tables 1-4 are not used at all and are most likely to be
> zeroed. 5th table is used for any mode below DP 2.0 (exclusive). 6th
> table is used for any mode above DP 2.0 (inclusive).
>
> For C10, use 2nd table for external DP if encoder supports any mode
> beyond or including HBR2. Use 1st table if external DP encoder supports
> anything lower than HBR2. For eDP, use 4th table if encoder supports
> HBR3. Otherwise use 3rd table for eDP.
>
> For C10, 1st table is used for external DP with modes below HBR2
> (exclusive). 1st table is also used as a fallback for non-DPs. 2nd
> table is used for external DP with modes higher than HBR2 (inclusive).
> 3rd table is used for eDP with modes lower than HBR3 (exclusive). 4th
> table is used for eDP with modes higher than HBR3 (inclusive).
>
> Indices for other tables have not yet been observed to be used as of
> now.
>
> There are no changes to intel_ddi_dp_level() since selection of correct
> row of intel_ddi_buf_trans_entry is same as when no override request has
> been done.
>
> v9->v10
> - call dedicated VS/PE-O vfunc
> - drop deconstifying default tables (Suraj, Jani)
> - cache `entries` into const field after data is overwritten (Jani)
>
> v8->v9
> - init vspeo before using it
> - deconstify intel_ddi_buf_trans_entry
>
> v7->v8
> - remove comments (Suraj)
> - add check for LT (Suraj)
>
> v6->v7
> - handle VS/PE-O's VBT details in intel_bios_* functions (Jani)
> - remove vspeo's cast to (void *) (Jani)
> - check devdata->vspeo if VS/PE-O was requested
> - call encoder->get_buf_trans() once (Jani)
> - return NULL from intel_bios_get_* when using default (Jani)
> - validate VS/PE-O in intel_bios.c (Jani)
> - inline mtl_{c10,c20}_get_vspeo_buf_trans()
> - remove temporarily LT
>
> v4->v5
> - blend index computation with table parsing
> - remove enums entirely
> - change funcs prefix from snps_ to mtl_ (Suraj)
> - add spaces around operators (Suraj)
> - remove spaces after type casting (Suraj)
> - remove INTEL_DISPLAY_STATE_WARN (Suraj)
>
> v3->v4
> - stick to solely changing VBT data into current structures (Jani)
> - move iterator declaration to declaration block (Suraj)
>
> v2->v3
> - remove unnecessary braces from if block (Suraj)
> - return -EINVAL instead of -1 (Suraj)
>
> Signed-off-by: Michał Grzelak <michal.grzelak@intel.com>
> Reviewed-by: Suraj Kandpal <suraj.kandpal@intel.com>
> ---
> drivers/gpu/drm/i915/display/intel_bios.c | 104 ++++++++++++++++++
> drivers/gpu/drm/i915/display/intel_bios.h | 7 ++
> .../drm/i915/display/intel_ddi_buf_trans.c | 37 ++++++-
> 3 files changed, 146 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index a491b8500611..f897ac067585 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -3881,6 +3881,110 @@ bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devda
> return devdata->display->vbt.version >= 209 && devdata->child.tbt;
> }
>
> +static bool
> +validate_vspeo(const struct intel_bios_encoder_data *devdata, bool has_dp)
> +{
> + struct intel_ddi_buf_trans *vspeo;
> +
> + if (!devdata)
> + return false;
When would this be NULL?
> +
> + vspeo = devdata->vspeo;
> + if (!vspeo)
> + return false;
> +
> + if (!has_dp)
> + return false;
> +
> + return true;
> +}
> +
> +const struct intel_ddi_buf_trans *
> +intel_bios_get_c20_vspeo(const struct intel_bios_encoder_data *devdata,
> + bool has_dp, bool is_uhbr)
> +{
> + struct intel_display *display;
> + union intel_ddi_buf_trans_entry *entries;
> + int num_columns, num_rows, level, idx;
> + struct intel_ddi_buf_trans *vspeo;
> + const u32 *tables;
> + size_t offset = 0;
> +
> + if (!validate_vspeo(devdata, has_dp))
> + return NULL;
> +
> + display = devdata->display;
> + vspeo = devdata->vspeo;
> + entries = devdata->entries;
> + tables = display->vbt.vspeo.tables;
> + num_columns = display->vbt.vspeo.num_columns;
> + num_rows = display->vbt.vspeo.num_rows;
> + idx = is_uhbr ? 5 : 4;
All of these should just be initialized at declaration.
> +
> + offset += idx * num_rows * num_columns;
> +
> + for (level = 0; level < num_rows; level++) {
> + u32 vswing = tables[offset];
> + u32 pre_cursor = tables[offset + 1];
> + u32 post_cursor = tables[offset + 2];
> +
> + entries[level].snps.vswing = vswing;
> + entries[level].snps.pre_cursor = pre_cursor;
> + entries[level].snps.post_cursor = post_cursor;
The struct dg2_snps_phy_buf_trans (snps) have u8 members. Is the data in
VBT in only the lowest byte of the u32? Or how is it arranged?
> +
> + offset += num_columns;
> + }
> +
> + vspeo->entries = entries;
> + vspeo->num_entries = num_rows;
It's common to have a blank line before return.
> + return vspeo;
> +}
> +
> +const struct intel_ddi_buf_trans *
> +intel_bios_get_c10_vspeo(const struct intel_bios_encoder_data *devdata,
> + bool has_dp, int port_clock, bool has_edp)
> +{
> + struct intel_display *display;
> + union intel_ddi_buf_trans_entry *entries;
> + int num_columns, num_rows, level, idx;
> + struct intel_ddi_buf_trans *vspeo;
> + const u32 *tables;
> + size_t offset = 0;
> +
> + if (!validate_vspeo(devdata, has_dp))
> + return NULL;
> +
> + display = devdata->display;
> + vspeo = devdata->vspeo;
> + entries = devdata->entries;
> + tables = display->vbt.vspeo.tables;
> + num_columns = display->vbt.vspeo.num_columns;
> + num_rows = display->vbt.vspeo.num_rows;
Ditto about initialization.
> +
> + idx = port_clock > 270000 ? 1 : 0;
> + if (has_edp)
> + idx = port_clock > 540000 ? 3 : 2;
if (has_edp)
...
else
...
seems more idiomatic than assigning twice for has_edp.
> +
> + offset += idx * num_rows * num_columns;
> +
> + for (level = 0; level < num_rows; level++) {
> + u32 vswing = tables[offset];
> + u32 pre_cursor = tables[offset + 1];
> + u32 post_cursor = tables[offset + 2];
> +
> + entries[level].snps.vswing = vswing;
> + entries[level].snps.pre_cursor = pre_cursor;
> + entries[level].snps.post_cursor = post_cursor;
Ditto about u8 vs u32.
> +
> + offset += num_columns;
> + }
> +
> + vspeo->entries = entries;
> + vspeo->num_entries = num_rows;
> +
> + return vspeo;
> +}
> +
> bool intel_bios_encoder_is_dedicated_external(const struct intel_bios_encoder_data *devdata)
> {
> return devdata->display->vbt.version >= 264 &&
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h
> index 7a50a272cd27..49acf8c405e2 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.h
> +++ b/drivers/gpu/drm/i915/display/intel_bios.h
> @@ -73,6 +73,13 @@ bool intel_bios_get_dsc_params(struct intel_encoder *encoder,
> const struct intel_bios_encoder_data *
> intel_bios_encoder_data_lookup(struct intel_display *display, enum port port);
>
> +const struct intel_ddi_buf_trans *
> +intel_bios_get_c20_vspeo(const struct intel_bios_encoder_data *devdata,
> + bool has_dp, bool is_uhbr);
> +const struct intel_ddi_buf_trans *
> +intel_bios_get_c10_vspeo(const struct intel_bios_encoder_data *devdata,
> + bool has_dp, int port_clock, bool has_edp);
> +
> bool intel_bios_encoder_requests_vspeo(const struct intel_bios_encoder_data *devdata);
> bool intel_bios_encoder_supports_dvi(const struct intel_bios_encoder_data *devdata);
> bool intel_bios_encoder_supports_hdmi(const struct intel_bios_encoder_data *devdata);
> diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
> index f31283a0331b..92c0d0f933ab 100644
> --- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
> +++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c
> @@ -1784,6 +1784,36 @@ xe3plpd_get_lt_buf_trans(struct intel_encoder *encoder,
> return intel_get_buf_trans(&xe3plpd_lt_trans_dp14, n_entries);
> }
>
> +static const struct intel_ddi_buf_trans *
> +mtl_get_c10_buf_trans_override(struct intel_encoder *encoder,
> + const struct intel_crtc_state *crtc_state,
> + int *n_entries)
> +{
> + const struct intel_bios_encoder_data *devdata = encoder->devdata;
> + bool has_edp, has_dp;
> + int port_clock;
> +
> + has_edp = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP);
> + has_dp = intel_crtc_has_dp_encoder(crtc_state);
> + port_clock = crtc_state->port_clock;
> +
> + return intel_bios_get_c10_vspeo(devdata, has_dp, port_clock, has_edp);
> +}
> +
> +static const struct intel_ddi_buf_trans *
> +mtl_get_c20_buf_trans_override(struct intel_encoder *encoder,
> + const struct intel_crtc_state *crtc_state,
> + int *n_entries)
> +{
> + const struct intel_bios_encoder_data *devdata = encoder->devdata;
> + bool has_dp, is_uhbr;
> +
> + has_dp = intel_crtc_has_dp_encoder(crtc_state);
> + is_uhbr = intel_dp_is_uhbr(crtc_state);
> +
> + return intel_bios_get_c20_vspeo(devdata, has_dp, is_uhbr);
> +}
> +
> void intel_ddi_buf_trans_init(struct intel_encoder *encoder)
> {
> struct intel_display *display = to_intel_display(encoder);
> @@ -1791,10 +1821,13 @@ void intel_ddi_buf_trans_init(struct intel_encoder *encoder)
> if (HAS_LT_PHY(display)) {
> encoder->get_buf_trans = xe3plpd_get_lt_buf_trans;
> } else if (DISPLAY_VER(display) >= 14) {
> - if (intel_encoder_is_c10phy(encoder))
> + if (intel_encoder_is_c10phy(encoder)) {
> encoder->get_buf_trans = mtl_get_c10_buf_trans;
> - else
> + encoder->get_buf_trans_override = mtl_get_c10_buf_trans_override;
> + } else {
> encoder->get_buf_trans = mtl_get_c20_buf_trans;
> + encoder->get_buf_trans_override = mtl_get_c20_buf_trans_override;
> + }
> } else if (display->platform.dg2) {
> encoder->get_buf_trans = dg2_get_snps_buf_trans;
> } else if (display->platform.alderlake_p) {
--
Jani Nikula, Intel
next prev parent reply other threads:[~2026-08-11 15:49 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-02 18:58 [PATCH v10 0/8] Vswing / Pre-emphasis Override Michał Grzelak
2026-07-02 18:58 ` [PATCH v10 1/8] drm/i915/bios: search for VBT #57 by default Michał Grzelak
2026-07-02 18:58 ` [PATCH v10 2/8] drm/i915/bios: store VBT #57's metadata in intel_vbt_data Michał Grzelak
2026-07-02 18:58 ` [PATCH v10 3/8] drm/i915/bios: print VS/PE-O port info Michał Grzelak
2026-07-02 18:58 ` [PATCH v10 4/8] drm/i915/bios: de/allocate VS/PE-O buffers for each port Michał Grzelak
2026-07-02 18:58 ` [PATCH v10 5/8] drm/i915/buf_trans: add vfunc for VS/PE-O Michał Grzelak
2026-07-06 6:12 ` Kandpal, Suraj
2026-07-02 18:58 ` [PATCH v10 6/8] drm/i915: override Snps's VS/PE when requested Michał Grzelak
2026-08-11 15:48 ` Jani Nikula [this message]
2026-08-13 15:52 ` Michał Grzelak
2026-07-02 18:58 ` [PATCH v10 7/8] drm/i915: override Combo's " Michał Grzelak
2026-08-11 15:51 ` Jani Nikula
2026-07-02 18:58 ` [PATCH v10 8/8] drm/i915/bios: remove VS/PE-O warning Michał Grzelak
2026-07-02 19:06 ` ✗ CI.checkpatch: warning for Vswing / Pre-emphasis Override (rev5) Patchwork
2026-07-02 19:07 ` ✓ CI.KUnit: success " Patchwork
2026-07-02 20:07 ` ✓ Xe.CI.BAT: " Patchwork
2026-07-02 20:07 ` ✓ i915.CI.BAT: " Patchwork
2026-07-03 13:55 ` ✓ Xe.CI.FULL: " Patchwork
2026-07-03 15:39 ` ✗ i915.CI.Full: failure " Patchwork
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=85c105f4619e348618c048f0ae3e0f8bc49d947b@intel.com \
--to=jani.nikula@intel.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=intel-xe@lists.freedesktop.org \
--cc=michal.grzelak@intel.com \
--cc=suraj.kandpal@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 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.