From 3018008dc1c3ca1d8c3f0a2362e15a1f47e66616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Grzelak?= Date: Fri, 4 Sep 2026 14:31:41 +0200 Subject: [PATCH 01/98] drm/i915/bios: search for VBT #57 by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Start searching for Vswing / Preemphasis Override Block during VBT parsing at init_bdb_blocks(). Check for failure since pre-ICL GOPs do not contain the block. Check also if VBT version is appropriately up-to-date. v6->v7 - parse VBT#57 before blocks dependent on child device list (Jani) - remove debug message (Suraj) v3->v4 - add Bspec (Suraj) Bspec: 32063 Signed-off-by: Michał Grzelak Reviewed-by: Suraj Kandpal Acked-by: Jani Nikula Signed-off-by: Suraj Kandpal Link: https://patch.msgid.link/20260904123148.2165596-2-michal.grzelak@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 97cbae2e547e..ece4df4a9d62 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -200,6 +200,8 @@ static const struct { .min_size = sizeof(struct bdb_mipi_sequence) }, { .section_id = BDB_COMPRESSION_PARAMETERS, .min_size = sizeof(struct bdb_compression_parameters), }, + { .section_id = BDB_VSWING_PREEMPH, + .min_size = sizeof(struct bdb_vswing_preemph), }, { .section_id = BDB_GENERIC_DTD, .min_size = sizeof(struct bdb_generic_dtd), }, }; @@ -2203,6 +2205,21 @@ parse_compression_parameters(struct intel_display *display) } } +static void +parse_vswing_preemph_override(struct intel_display *display) +{ + const struct bdb_vswing_preemph *block; + + if (display->vbt.version < 218) + return; + + block = bdb_find_section(display, BDB_VSWING_PREEMPH); + + /* pre-ICL GOPs don't have VBT #57 */ + if (!block) + return; +} + static u8 translate_iboost(struct intel_display *display, u8 val) { static const u8 mapping[] = { 1, 3, 7 }; /* See VBT spec */ @@ -3291,6 +3308,7 @@ void intel_bios_init(struct intel_display *display) parse_general_features(display); parse_general_definitions(display); parse_driver_features(display); + parse_vswing_preemph_override(display); /* Depends on child device list */ parse_compression_parameters(display); From c76c03dab828709469558a6bdd55336ef9fd9420 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Grzelak?= Date: Fri, 4 Sep 2026 14:31:42 +0200 Subject: [PATCH 02/98] drm/i915/bios: store VBT #57's metadata in intel_vbt_data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Store tables, number of tables, number of rows and number of columns in intel_vbt_data when search for the VBT #57 has succeeded. Structurize all VS/PE-O relevant metadata inside anonymous struct named as vspeo. Presence of C20 or newer PHY causes each table to contain 16 rows. Each table contains 10 rows in case C20 PHY is absent. Use display version to determine number of rows since there is no helper in intel_bios.c to check presence of any C20+ PHY. pre-MTL platforms should have 10 rows while MTL+ should have 16 rows. v5->v6 - add Bspec (Suraj) v3->v4 - remove unnecessary init of VS/PE-O metadata (Suraj) - add helper for computing number of rows (Suraj) - fix num_rows's type (Jani, Suraj) - declare num_rows (Suraj) Bspec: 68963 Signed-off-by: Michał Grzelak Reviewed-by: Suraj Kandpal Acked-by: Jani Nikula Signed-off-by: Suraj Kandpal Link: https://patch.msgid.link/20260904123148.2165596-3-michal.grzelak@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 10 ++++++++++ drivers/gpu/drm/i915/display/intel_display_core.h | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index ece4df4a9d62..06a8dd7581bb 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -2205,6 +2205,11 @@ parse_compression_parameters(struct intel_display *display) } } +static int vswing_preemph_num_rows(struct intel_display *display) +{ + return DISPLAY_VER(display) >= 14 ? 16 : 10; +} + static void parse_vswing_preemph_override(struct intel_display *display) { @@ -2218,6 +2223,11 @@ parse_vswing_preemph_override(struct intel_display *display) /* pre-ICL GOPs don't have VBT #57 */ if (!block) return; + + display->vbt.vspeo.tables = block->tables; + display->vbt.vspeo.num_tables = block->num_tables; + display->vbt.vspeo.num_columns = block->num_columns; + display->vbt.vspeo.num_rows = vswing_preemph_num_rows(display); } static u8 translate_iboost(struct intel_display *display, u8 val) diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h index 7e988b7b1fe7..c80b4a2f74f9 100644 --- a/drivers/gpu/drm/i915/display/intel_display_core.h +++ b/drivers/gpu/drm/i915/display/intel_display_core.h @@ -244,6 +244,13 @@ struct intel_vbt_data { struct list_head display_devices; struct list_head bdb_blocks; + struct { + const u32 *tables; + int num_tables; + int num_columns; + int num_rows; + } vspeo; + struct sdvo_device_mapping { u8 initialized; u8 dvo_port; From 1b15117625045baa107970a9a1ffb5638ab05414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Grzelak?= Date: Fri, 4 Sep 2026 14:31:43 +0200 Subject: [PATCH 03/98] drm/i915/bios: print VS/PE-O port info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue a debug message when port asks to override default Vswing / Preemphasis tables. Add helper intel_bios_encoder_requests_vspeo() to check if port requests for overriding default VS/PE tables. v6->v7 - expand VS/PE-O acronym in debug logging (Jani) v3->v4 - change debug message when requesting VS/PE-O (Suraj) Signed-off-by: Michał Grzelak Reviewed-by: Suraj Kandpal Acked-by: Jani Nikula Signed-off-by: Suraj Kandpal Link: https://patch.msgid.link/20260904123148.2165596-4-michal.grzelak@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 10 ++++++++++ drivers/gpu/drm/i915/display/intel_bios.h | 1 + 2 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 06a8dd7581bb..9610b794bc14 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -2801,6 +2801,11 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata) "Port %c supports dynamic DDI allocation in TCSS\n", port_name(port)); + if (intel_bios_encoder_requests_vspeo(devdata)) + drm_dbg_kms(display->drm, + "Port %c requests vswing/pre-emphasis override\n", + port_name(port)); + hdmi_level_shift = intel_bios_hdmi_level_shift(devdata); if (hdmi_level_shift >= 0) { drm_dbg_kms(display->drm, @@ -3829,6 +3834,11 @@ int intel_bios_hdmi_ddc_pin(const struct intel_bios_encoder_data *devdata) return map_ddc_pin(devdata->display, devdata->child.ddc_pin); } +bool intel_bios_encoder_requests_vspeo(const struct intel_bios_encoder_data *devdata) +{ + return devdata->display->vbt.version >= 218 && devdata->child.use_vbt_vswing; +} + bool intel_bios_encoder_supports_typec_usb(const struct intel_bios_encoder_data *devdata) { return devdata->display->vbt.version >= 195 && devdata->child.dp_usb_type_c; diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h index 75dff27b4228..7a50a272cd27 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.h +++ b/drivers/gpu/drm/i915/display/intel_bios.h @@ -73,6 +73,7 @@ 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); +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); bool intel_bios_encoder_supports_dp(const struct intel_bios_encoder_data *devdata); From a138a81d7805a025a778035c0850642381d1fdf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Grzelak?= Date: Fri, 4 Sep 2026 14:31:44 +0200 Subject: [PATCH 04/98] drm/i915/bios: de/allocate VS/PE-O buffers for each port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every devdata needs VS/PE-O dedicated buffers since each port can request an override. Add intel_ddi_buf_trans{,_entry} pointers into intel_bios_encoder_data. Allocate struct intel_ddi_buf_trans{,_entry} for the port if VS/PE-O was requested and is supported. Keep NULL in vspeo if any allocation failed or VS/PE-O was not requested. It will be used later for checking if override should actually take place. Note that we theoretically could store intel_ddi_buf_trans_entry inside `entries` field of newly allocated intel_ddi_buf_trans. However it will be impossible to overwrite the buffer during intel_ddi_get_buf_trans() without discarding const qualifier of `entries` field. This would involve either void casting or deconstifying entries field and in turn all predefined tables as well. Thus add a separate non-const qualified field into intel_bios_encoder_data for the buffer, which after overwriting will be promoted to be const qualified. Deallocate the buffer as well as entries if requested. v11->v12 - set vspeo->num_entries once (Sashiko) - free allocated vspeo->entries (Sashiko) v9->v10 - add separate non-const field for `entries` caching - cache `entries` into const field after data is overwritten (Jani) v4->v5 - set devdata->vspeo->num_entries in intel_bios.c Signed-off-by: Michał Grzelak Reviewed-by: Suraj Kandpal Acked-by: Jani Nikula Signed-off-by: Suraj Kandpal Link: https://patch.msgid.link/20260904123148.2165596-5-michal.grzelak@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 31 +++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 9610b794bc14..1a09f7933e49 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -34,6 +34,7 @@ #include #include +#include "intel_ddi_buf_trans.h" #include "intel_display.h" #include "intel_display_core.h" #include "intel_display_rpm.h" @@ -72,6 +73,8 @@ struct intel_bios_encoder_data { struct intel_display *display; + struct intel_ddi_buf_trans *vspeo; + union intel_ddi_buf_trans_entry *entries; struct child_device_config child; struct dsc_compression_parameters_entry *dsc; struct list_head node; @@ -2648,6 +2651,30 @@ static void sanitize_device_type(struct intel_bios_encoder_data *devdata, devdata->child.device_type |= DEVICE_TYPE_NOT_HDMI_OUTPUT; } +static void allocate_vswing_preemph_override(struct intel_bios_encoder_data *devdata) +{ + int num_rows = devdata->display->vbt.vspeo.num_rows; + union intel_ddi_buf_trans_entry *entries; + struct intel_ddi_buf_trans *vspeo; + + if (!intel_bios_encoder_requests_vspeo(devdata)) + return; + + vspeo = kzalloc_obj(*vspeo); + if (!vspeo) + return; + + entries = kzalloc_objs(*entries, num_rows); + if (!entries) { + kfree(vspeo); + return; + } + + devdata->entries = entries; + devdata->vspeo = vspeo; + devdata->vspeo->num_entries = num_rows; +} + static void sanitize_hdmi_level_shift(struct intel_bios_encoder_data *devdata, enum port port) { @@ -2866,6 +2893,7 @@ static void parse_ddi_port(struct intel_bios_encoder_data *devdata) sanitize_dedicated_external(devdata, port); sanitize_device_type(devdata, port); sanitize_hdmi_level_shift(devdata, port); + allocate_vswing_preemph_override(devdata); } static bool has_ddi_port_info(struct intel_display *display) @@ -3403,6 +3431,9 @@ void intel_bios_driver_remove(struct intel_display *display) list_for_each_entry_safe(devdata, nd, &display->vbt.display_devices, node) { list_del(&devdata->node); + + kfree(devdata->entries); + kfree(devdata->vspeo); kfree(devdata->dsc); kfree(devdata); } From e084812de907c63b0b943b3955bf629df62f6745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Grzelak?= Date: Fri, 4 Sep 2026 14:31:45 +0200 Subject: [PATCH 05/98] drm/i915/buf_trans: add vfunc for VS/PE-O MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Choosing correct table for Vswing / Pre-emphasis Override is platform specific. It also requires different checks that are already used for choosing predefined tables. Add new get_buf_trans_override() vfunc into intel_encoder returning deparsed table from VBT#57. In next patches, set it inside already present if-ladder from intel_ddi_buf_trans_init() instead of duplicating it. Note that get_buf_trans() cannot be overwritten since there are cases when we need to rollback although VS/PE-O was requested, eg. DP is not connected or feature is not yet implemented for the platform. Assume that vfunc returns NULL on rollback and return predefined tables. Suggested-by: Jani Nikula Signed-off-by: Michał Grzelak Reviewed-by: Suraj Kandpal Acked-by: Jani Nikula Signed-off-by: Suraj Kandpal Link: https://patch.msgid.link/20260904123148.2165596-6-michal.grzelak@intel.com --- drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c | 8 ++++++++ drivers/gpu/drm/i915/display/intel_display_types.h | 3 +++ 2 files changed, 11 insertions(+) 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 4cd1e4d76c7a..f31283a0331b 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c +++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c @@ -1857,5 +1857,13 @@ const struct intel_ddi_buf_trans *intel_ddi_buf_trans_get(struct intel_encoder * const struct intel_crtc_state *crtc_state, int *n_entries) { + if (encoder->get_buf_trans_override) { + const struct intel_ddi_buf_trans *override; + + override = encoder->get_buf_trans_override(encoder, crtc_state, n_entries); + if (override) + return intel_get_buf_trans(override, n_entries); + } + return encoder->get_buf_trans(encoder, crtc_state, n_entries); } diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 5f0fe18c0614..9016be52c7ea 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -289,6 +289,9 @@ struct intel_encoder { */ enum icl_port_dpll_id (*port_pll_type)(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state); + const struct intel_ddi_buf_trans *(*get_buf_trans_override)(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + int *n_entries); const struct intel_ddi_buf_trans *(*get_buf_trans)(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, int *n_entries); From e8fe5008ae3da28c06ccdaf63d0621c0c50f39dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Grzelak?= Date: Fri, 4 Sep 2026 14:31:46 +0200 Subject: [PATCH 06/98] drm/i915: override Snps's VS/PE when requested MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add accessor functions for Snps to read requested table from VBT #57. Parse the requested table and transform data into port's buffer. Actual data is fully stored in the lowest byte although each entry is 4 bytes wide. Thus convert u32 into u8 and store the data. 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). 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. v11->v12 - don't set vspeo->num_entries per PHY - don't refer to 1st table as fallback for non-DP for C10 (Sashiko) v10->v11 - remove no-longer-relevant check for NULL devdata (Jani) - initialize local variables at declaration block (Jani) - branch with 'else` instead of initializing twice (Jani) - use blank line before 'return` (Jani) 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 Reviewed-by: Suraj Kandpal Acked-by: Jani Nikula Signed-off-by: Suraj Kandpal Link: https://patch.msgid.link/20260904123148.2165596-7-michal.grzelak@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 91 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_bios.h | 7 ++ .../drm/i915/display/intel_ddi_buf_trans.c | 37 +++++++- 3 files changed, 133 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 1a09f7933e49..be7554c483ad 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -3880,6 +3880,97 @@ 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; + + 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 = devdata->display; + union intel_ddi_buf_trans_entry *entries = devdata->entries; + struct intel_ddi_buf_trans *vspeo = devdata->vspeo; + const u32 *tables = display->vbt.vspeo.tables; + int num_columns = display->vbt.vspeo.num_columns; + int num_rows = display->vbt.vspeo.num_rows; + int idx = is_uhbr ? 5 : 4; + size_t offset = 0; + int level; + + if (!validate_vspeo(devdata, has_dp)) + return NULL; + + 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; + + offset += num_columns; + } + + vspeo->entries = entries; + + 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 = devdata->display; + union intel_ddi_buf_trans_entry *entries = devdata->entries; + struct intel_ddi_buf_trans *vspeo = devdata->vspeo; + const u32 *tables = display->vbt.vspeo.tables; + int num_columns = display->vbt.vspeo.num_columns; + int num_rows = display->vbt.vspeo.num_rows; + size_t offset = 0; + int level, idx; + + if (!validate_vspeo(devdata, has_dp)) + return NULL; + + if (has_edp) + idx = port_clock > 540000 ? 3 : 2; + else + idx = port_clock > 270000 ? 1 : 0; + + 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; + + offset += num_columns; + } + + vspeo->entries = entries; + + 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) { From 7fdf86e530c7f6655aad0612a8c90ab1559984bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Grzelak?= Date: Mon, 7 Sep 2026 14:27:42 +0200 Subject: [PATCH 07/98] drm/i915: override Combo's VS/PE when requested MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add accessor function for Combo to read requested table from VBT #57. Parse the requested table and transform data into port's buffer. Actual data is fully stored in the lowest byte although each entry is 4 bytes wide. Thus convert u32 into u8 and store the data. For EHL, in cases when eDP encoder uses low vswing, choose 3rd table if encoder supports HBR3. Otherwise use 2nd table for eDP using low vswing. In cases when eDP encoder does not use low vswing, choose 2nd table if encoder supports mode higher or including HBR2. Otherwise use 1st table for eDP not using low vswing. For external DP follow same path and use same indices as in eDP without low vswing case. For JSL, always use 1st table for external DP. For eDPs not using low vswing use 1st table as well. In cases when eDP encoder uses low vswing, choose 1st table if encoder supports HBR3. When encoder supports HBR2 choose 3rd table. When encoder supports modes lower than HBR2 choose 2nd table. 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. Looking from other OSes, in case when encoder does not support DP we could theoretically use 1st table. However, as of now, use default tables. v11->v12 - don't set vspeo->num_entries per PHY/platform - check for low vswing eDP for EHL (Sashiko) - reverse order of indices for JSL (Sashiko) v10->v11 - initialize local variables at declaration block (Jani) - branch with 'else` instead of initializing twice (Jani) 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 - deconstify intel_ddi_buf_trans_entry v6->v7 - handle VS/PE-O's VBT details in intel_bios_* functions (Jani) - remove vspeo's cast to (void *) (Jani) - 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) - check devdata->vspeo if VS/PE-O was requested - inline {jsl,ehl}_combo_get_vspeo_buf_trans() - remove temporarily LT v4->v5 - blend index computation with table parsing - remove enums entirely - add spaces around operators (Suraj) - remove spaces after type casting (Suraj) - remove INTEL_DISPLAY_STATE_WARN (Suraj) Signed-off-by: Michał Grzelak Reviewed-by: Suraj Kandpal Acked-by: Jani Nikula Signed-off-by: Suraj Kandpal Link: https://patch.msgid.link/20260907122742.2512901-1-michal.grzelak@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 93 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_bios.h | 6 ++ .../drm/i915/display/intel_ddi_buf_trans.c | 45 ++++++++- 3 files changed, 140 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index be7554c483ad..11d2cbb78eab 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -3971,6 +3971,99 @@ intel_bios_get_c10_vspeo(const struct intel_bios_encoder_data *devdata, return vspeo; } +const struct intel_ddi_buf_trans * +intel_bios_get_ehl_combo_vspeo(const struct intel_bios_encoder_data *devdata, + bool has_dp, int port_clock, bool low_vswing_edp) +{ + struct intel_display *display = devdata->display; + union intel_ddi_buf_trans_entry *entries = devdata->entries; + struct intel_ddi_buf_trans *vspeo = devdata->vspeo; + const u32 *tables = display->vbt.vspeo.tables; + int num_columns = display->vbt.vspeo.num_columns; + int num_rows = display->vbt.vspeo.num_rows; + size_t offset = 0; + int level, idx; + + if (!validate_vspeo(devdata, has_dp)) + return NULL; + + if (low_vswing_edp) + idx = port_clock > 540000 ? 2 : 1; + else + idx = port_clock > 270000 ? 1 : 0; + + offset += idx * num_rows * num_columns; + + for (level = 0; level < num_rows; level++) { + u32 dw2_swing_sel = tables[offset]; + u32 dw7_n_scalar = tables[offset + 1]; + u32 dw4_cursor_coeff = tables[offset + 2]; + u32 dw4_post_cursor_2 = tables[offset + 3]; + u32 dw4_post_cursor_1 = tables[offset + 4]; + + entries[level].icl.dw2_swing_sel = dw2_swing_sel; + entries[level].icl.dw7_n_scalar = dw7_n_scalar; + entries[level].icl.dw4_cursor_coeff = dw4_cursor_coeff; + entries[level].icl.dw4_post_cursor_2 = dw4_post_cursor_2; + entries[level].icl.dw4_post_cursor_1 = dw4_post_cursor_1; + + offset += num_columns; + } + + vspeo->entries = entries; + + return vspeo; +} + +const struct intel_ddi_buf_trans * +intel_bios_get_jsl_combo_vspeo(const struct intel_bios_encoder_data *devdata, + bool has_dp, int port_clock, bool low_vswing_edp) +{ + struct intel_display *display = devdata->display; + union intel_ddi_buf_trans_entry *entries = devdata->entries; + struct intel_ddi_buf_trans *vspeo = devdata->vspeo; + const u32 *tables = display->vbt.vspeo.tables; + int num_columns = display->vbt.vspeo.num_columns; + int num_rows = display->vbt.vspeo.num_rows; + size_t offset = 0; + int idx = 0; + int level; + + if (!validate_vspeo(devdata, has_dp)) + return NULL; + + if (low_vswing_edp) { + if (port_clock > 540000) + idx = 0; + else if (port_clock > 270000) + idx = 2; + else + idx = 1; + } + + offset += idx * num_rows * num_columns; + + for (level = 0; level < num_rows; level++) { + u32 dw2_swing_sel = tables[offset]; + u32 dw7_n_scalar = tables[offset + 1]; + u32 dw4_cursor_coeff = tables[offset + 2]; + u32 dw4_post_cursor_2 = tables[offset + 3]; + u32 dw4_post_cursor_1 = tables[offset + 4]; + + entries[level].icl.dw2_swing_sel = dw2_swing_sel; + entries[level].icl.dw7_n_scalar = dw7_n_scalar; + entries[level].icl.dw4_cursor_coeff = dw4_cursor_coeff; + entries[level].icl.dw4_post_cursor_2 = dw4_post_cursor_2; + entries[level].icl.dw4_post_cursor_1 = dw4_post_cursor_1; + + offset += num_columns; + } + + vspeo->entries = entries; + + 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 49acf8c405e2..196b8b3f434f 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.h +++ b/drivers/gpu/drm/i915/display/intel_bios.h @@ -79,6 +79,12 @@ intel_bios_get_c20_vspeo(const struct intel_bios_encoder_data *devdata, 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); +const struct intel_ddi_buf_trans * +intel_bios_get_ehl_combo_vspeo(const struct intel_bios_encoder_data *devdata, + bool has_dp, int port_clock, bool low_vswing_edp); +const struct intel_ddi_buf_trans * +intel_bios_get_jsl_combo_vspeo(const struct intel_bios_encoder_data *devdata, + bool has_dp, int port_clock, bool low_vswing_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); 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 92c0d0f933ab..cc5912178d9c 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,40 @@ 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 * +jsl_get_combo_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_jsl_combo_vspeo(devdata, has_dp, port_clock, + has_edp && use_edp_low_vswing(encoder)); +} + +static const struct intel_ddi_buf_trans * +ehl_get_combo_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_ehl_combo_vspeo(devdata, has_dp, port_clock, + has_edp && use_edp_low_vswing(encoder)); +} + static const struct intel_ddi_buf_trans * mtl_get_c10_buf_trans_override(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, @@ -1847,14 +1881,17 @@ void intel_ddi_buf_trans_init(struct intel_encoder *encoder) else encoder->get_buf_trans = tgl_get_dkl_buf_trans; } else if (DISPLAY_VER(display) == 11) { - if (display->platform.jasperlake) + if (display->platform.jasperlake) { encoder->get_buf_trans = jsl_get_combo_buf_trans; - else if (display->platform.elkhartlake) + encoder->get_buf_trans_override = jsl_get_combo_buf_trans_override; + } else if (display->platform.elkhartlake) { encoder->get_buf_trans = ehl_get_combo_buf_trans; - else if (intel_encoder_is_combo(encoder)) + encoder->get_buf_trans_override = ehl_get_combo_buf_trans_override; + } else if (intel_encoder_is_combo(encoder)) { encoder->get_buf_trans = icl_get_combo_buf_trans; - else + } else { encoder->get_buf_trans = icl_get_mg_buf_trans; + } } else if (display->platform.geminilake || display->platform.broxton) { encoder->get_buf_trans = bxt_get_buf_trans; } else if (display->platform.cometlake_ulx || From 4bda5543b3c6697ca435e89aeea655eea9087f96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Grzelak?= Date: Fri, 4 Sep 2026 14:31:48 +0200 Subject: [PATCH 08/98] drm/i915/bios: remove VS/PE-O warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is not much use of warning when port asks to override default VS/PE since it is already logged. Remove drm_WARN() and child_device from print_ddi_port() since drm_WARN() was the only user of it. Signed-off-by: Michał Grzelak Reviewed-by: Suraj Kandpal Acked-by: Jani Nikula Signed-off-by: Suraj Kandpal Link: https://patch.msgid.link/20260904123148.2165596-9-michal.grzelak@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 11d2cbb78eab..7b6a6f8c3cf1 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -2791,7 +2791,6 @@ static bool is_port_valid(struct intel_display *display, enum port port) static void print_ddi_port(const struct intel_bios_encoder_data *devdata) { struct intel_display *display = devdata->display; - const struct child_device_config *child = &devdata->child; bool is_dvi, is_hdmi, is_dp, is_edp, is_dsi, is_crt, supports_typec_usb, supports_tbt; int dp_boost_level, dp_max_link_rate, hdmi_boost_level, hdmi_level_shift, max_tmds_clock; enum port port; @@ -2864,14 +2863,6 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata) drm_dbg_kms(display->drm, "Port %c VBT DP max link rate: %d\n", port_name(port), dp_max_link_rate); - - /* - * FIXME need to implement support for VBT - * vswing/preemph tables should this ever trigger. - */ - drm_WARN(display->drm, child->use_vbt_vswing, - "Port %c asks to use VBT vswing/preemph tables\n", - port_name(port)); } static void parse_ddi_port(struct intel_bios_encoder_data *devdata) From 9977e9d84f46d4f12ad35fbbc0ec4638554bce87 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sun, 23 Aug 2026 22:50:28 +0200 Subject: [PATCH 09/98] drm/i915: Fix memory leak in query_perf_config_list() When krealloc() fails, free the original oa_config_ids before returning to avoid a memory leak. Fixes: 4f6ccc74a85c ("drm/i915: add support for perf configuration queries") Signed-off-by: Thorsten Blum Cc: # v5.5+ Reviewed-by: Andi Shyti Signed-off-by: Andi Shyti Link: https://patch.msgid.link/20260823205028.178597-2-thorsten.blum@linux.dev --- drivers/gpu/drm/i915/i915_query.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c index 0c55fb6e9727..11157fb14db3 100644 --- a/drivers/gpu/drm/i915/i915_query.c +++ b/drivers/gpu/drm/i915/i915_query.c @@ -403,8 +403,10 @@ static int query_perf_config_list(struct drm_i915_private *i915, ids = krealloc(oa_config_ids, n_configs * sizeof(*oa_config_ids), GFP_KERNEL); - if (!ids) + if (!ids) { + kfree(oa_config_ids); return -ENOMEM; + } alloc = fetch_and_zero(&n_configs); From 8dbe5c47ca4254be32e8a7bed16ef911de3101fe Mon Sep 17 00:00:00 2001 From: Uma Shankar Date: Wed, 9 Sep 2026 13:38:07 +0530 Subject: [PATCH 10/98] drm/i915/display: Enable periodic AS SDP skip frames When Panel Replay is active the transcoder timing generator runs at the panel's maximum refresh rate. To drive the panel down to its minimum refresh rate the Adaptive-Sync SDP (AS SDP) only needs to reach the panel once per minimum-rate frame, so transmitting it on every (maximum-rate) frame is redundant and shows up as repeated SDPs on the link. Xe3p_LPD adds a HW skip-frame counter in PR_ALPM_CTL that lets the source send a single AS SDP and then suppress it for a programmed number of frames. Program this counter so that one AS SDP is followed by (max_vrefresh / min_vrefresh - 1) idle frames, i.e. one AS SDP per slowest panel frame, allowing the link to be driven down to as low as 1Hz when the hardware supports it. The maximum and minimum refresh rates come from the panel's adaptive-sync monitor range, so the skip count is a function of the sink's capabilities and independent of the current content/flip rate. If the panel does not advertise a usable range the skip counter is left at zero, i.e. the feature is a no-op and AS SDP continues to be sent on every frame. Periodic AS SDP drives the panel down to its minimum refresh rate on its own, so it is only programmed when VRR is not actively driving the refresh rate. The skip-frame mechanism relies on the AS SDP still being transmitted (just less often) while Panel Replay is active, so when a non-zero skip-frame count is programmed both PR_ALPM_CTL_AS_SDP_TRANSMISSION_IN_ACTIVE_DISABLE and PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL are left cleared. The previous behaviour (honouring disable_as_sdp_when_pr_active and the DC3CO idle protocol) is retained for the non skip-frame case. v3: Fixed Sashiko review findings v2: Decoupled CMMRR dependency and using sink refresh rate range for skip frame claculations. This addresses Dibin's review feedback as well. Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Uma Shankar Reviewed-by: Dibin Moolakadan Subrahmanian Tested-by: Naladala Ramanaidu Link: https://patch.msgid.link/20260909080810.2202879-2-uma.shankar@intel.com --- drivers/gpu/drm/i915/display/intel_alpm.c | 61 +++++++++++++++++-- drivers/gpu/drm/i915/display/intel_psr_regs.h | 2 + 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c index f1383764b702..a6838e0fd3aa 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.c +++ b/drivers/gpu/drm/i915/display/intel_alpm.c @@ -375,6 +375,35 @@ static u32 get_pr_alpm_as_sdp_transmission_time(const struct intel_crtc_state *c } } +/* + * Periodic Adaptive-Sync SDP skip frames. + * + * While Panel Replay is active the transcoder timing generator runs at the + * panel's maximum refresh rate. To drive the panel down to its minimum + * refresh rate the Adaptive-Sync SDP only needs to reach the panel once per + * minimum-rate frame, so transmitting it on every (maximum-rate) frame is + * unnecessary and shows up as repeated SDPs on the link. Program the HW skip + * counter so that a single AS SDP is followed by + * (max_vrefresh / min_vrefresh - 1) idle frames, i.e. one AS SDP per slowest + * panel frame. + * + * The maximum and minimum refresh rates come from the panel's adaptive-sync + * monitor range, so this is independent of the current content/flip rate. + */ +static u32 intel_pr_as_sdp_skip_frames(struct intel_dp *intel_dp) +{ + const struct drm_display_info *info = + &intel_dp->attached_connector->base.display_info; + int max_vrefresh = info->monitor_range.max_vfreq; + int min_vrefresh = info->monitor_range.min_vfreq; + + if (min_vrefresh <= 0 || max_vrefresh <= min_vrefresh) + return 0; + + return min_t(u32, max_vrefresh / min_vrefresh - 1, + REG_FIELD_MAX(PR_ALPM_CTL_AS_SDP_SKIP_FRAMES_MASK)); +} + static void lnl_alpm_configure(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { @@ -399,16 +428,38 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp, if (intel_dp->as_sdp_supported) { u32 pr_alpm_ctl = get_pr_alpm_as_sdp_transmission_time(crtc_state); + u32 skip_frames = 0; + + /* + * AS SDP skip frames field only exists on Xe3p_LPD+, and + * periodic AS SDP is a Panel Replay feature that is only + * used when VRR is not actively driving the refresh rate. + */ + if (DISPLAY_VER(display) >= 35 && crtc_state->has_panel_replay && + !crtc_state->vrr.enable) + skip_frames = intel_pr_as_sdp_skip_frames(intel_dp); if (crtc_state->link_off_after_as_sdp_when_pr_active) pr_alpm_ctl |= PR_ALPM_CTL_ALLOW_LINK_OFF_BETWEEN_AS_SDP_AND_SU; - if (crtc_state->disable_as_sdp_when_pr_active) - pr_alpm_ctl |= PR_ALPM_CTL_AS_SDP_TRANSMISSION_IN_ACTIVE_DISABLE; - if (intel_display_power_dc3co_allowed(display)) - pr_alpm_ctl |= PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL; - else + /* + * Skip frames needs the AS SDP to keep flowing during PR + * active, so it is mutually exclusive with disabling AS SDP + * transmission in active and with the DC3CO idle protocol. + */ + if (skip_frames) { + pr_alpm_ctl |= PR_ALPM_CTL_AS_SDP_SKIP_FRAMES(skip_frames); + pr_alpm_ctl &= ~PR_ALPM_CTL_AS_SDP_TRANSMISSION_IN_ACTIVE_DISABLE; pr_alpm_ctl &= ~PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL; + } else { + pr_alpm_ctl &= ~PR_ALPM_CTL_AS_SDP_SKIP_FRAMES_MASK; + + if (crtc_state->disable_as_sdp_when_pr_active) + pr_alpm_ctl |= PR_ALPM_CTL_AS_SDP_TRANSMISSION_IN_ACTIVE_DISABLE; + + if (intel_display_power_dc3co_allowed(display)) + pr_alpm_ctl |= PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL; + } intel_de_write(display, PR_ALPM_CTL(display, cpu_transcoder), pr_alpm_ctl); diff --git a/drivers/gpu/drm/i915/display/intel_psr_regs.h b/drivers/gpu/drm/i915/display/intel_psr_regs.h index 16a9e3af198d..bb577e7e3bbd 100644 --- a/drivers/gpu/drm/i915/display/intel_psr_regs.h +++ b/drivers/gpu/drm/i915/display/intel_psr_regs.h @@ -276,6 +276,8 @@ #define PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1_OR_T2 REG_FIELD_PREP(PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_MASK, 0) #define PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T1 REG_FIELD_PREP(PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_MASK, 1) #define PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_T2 REG_FIELD_PREP(PR_ALPM_CTL_ADAPTIVE_SYNC_SDP_POSITION_MASK, 2) +#define PR_ALPM_CTL_AS_SDP_SKIP_FRAMES_MASK REG_GENMASK(27, 16) +#define PR_ALPM_CTL_AS_SDP_SKIP_FRAMES(frames) REG_FIELD_PREP(PR_ALPM_CTL_AS_SDP_SKIP_FRAMES_MASK, (frames)) #define _ALPM_CTL_A 0x60950 #define ALPM_CTL(dev_priv, tran) _MMIO_TRANS2(dev_priv, tran, _ALPM_CTL_A) From dc0fd724e13a313b64773200f84137bf81167a9c Mon Sep 17 00:00:00 2001 From: Uma Shankar Date: Wed, 9 Sep 2026 13:38:08 +0530 Subject: [PATCH 11/98] drm/i915/display: Force disable DC3co when AS SDP skip frames is enabled Periodic AS SDP (skip frames) relies on the AS SDP still being transmitted while Panel Replay is active. DC3co uses the idle protocol which suppresses AS SDP transmission entirely, so the two are mutually exclusive: leaving DC3co enabled while skip frames is programmed breaks the periodic AS SDP and the panel never sees the slower refresh. Add intel_alpm_pr_as_sdp_skip_frames_enabled() as the single predicate for "skip frames will be programmed" (mirroring the gating in lnl_alpm_configure(), including that it only applies when VRR is not active) and use it in intel_display_power_dc3co_compute() to force the DC3co trigger to NONE. This drops the pipe onto the DC_STATE_EN_UPTO_DC6 target instead of DC3co whenever skip frames is active, without touching the DC state module parameter or the allowed DC mask, and only for the skip-frame case. v2: Fixed Sashiko review findings Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Uma Shankar Reviewed-by: Dibin Moolakadan Subrahmanian Tested-by: Naladala Ramanaidu Link: https://patch.msgid.link/20260909080810.2202879-3-uma.shankar@intel.com --- drivers/gpu/drm/i915/display/intel_alpm.c | 23 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_alpm.h | 2 ++ .../drm/i915/display/intel_display_power.c | 9 ++++++++ 3 files changed, 34 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c index a6838e0fd3aa..0a33a89975bc 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.c +++ b/drivers/gpu/drm/i915/display/intel_alpm.c @@ -404,6 +404,29 @@ static u32 intel_pr_as_sdp_skip_frames(struct intel_dp *intel_dp) REG_FIELD_MAX(PR_ALPM_CTL_AS_SDP_SKIP_FRAMES_MASK)); } +/* + * Whether periodic AS SDP transmission (AS SDP skip frames) will be programmed + * for this Panel Replay config. The skip counter needs the AS SDP to keep + * flowing during PR active, which is incompatible with DC3co, so this is used + * to keep DC3co disabled while skip frames is enabled. + */ +bool intel_alpm_pr_as_sdp_skip_frames_enabled(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(intel_dp); + + /* + * The AS SDP skip frames field only exists on Xe3p_LPD+. Periodic AS SDP + * drives the panel down to its minimum refresh rate on its own, so it is + * only used when VRR is not actively driving the refresh rate. + */ + if (DISPLAY_VER(display) < 35 || !intel_dp->as_sdp_supported || + !crtc_state->has_panel_replay || crtc_state->vrr.enable) + return false; + + return intel_pr_as_sdp_skip_frames(intel_dp) > 0; +} + static void lnl_alpm_configure(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h b/drivers/gpu/drm/i915/display/intel_alpm.h index 1cf70668ab1b..328920027f1c 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.h +++ b/drivers/gpu/drm/i915/display/intel_alpm.h @@ -34,6 +34,8 @@ bool intel_alpm_aux_wake_supported(struct intel_dp *intel_dp); bool intel_alpm_aux_less_wake_supported(struct intel_dp *intel_dp); bool intel_alpm_is_alpm_aux_less(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state); +bool intel_alpm_pr_as_sdp_skip_frames_enabled(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state); void intel_alpm_disable(struct intel_dp *intel_dp); bool intel_alpm_get_error(struct intel_dp *intel_dp); void intel_alpm_lobf_compute_config_late(struct intel_dp *intel_dp, diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 0ebec6e0c240..1b60ce2dd00c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -10,6 +10,7 @@ #include #include +#include "intel_alpm.h" #include "intel_backlight_regs.h" #include "intel_cdclk.h" #include "intel_clock_gating.h" @@ -488,6 +489,14 @@ void intel_display_power_dc3co_compute(struct intel_atomic_state *state) if (crtc_state->has_sel_update) trigger |= DC3CO_TRIGGER_PSR2; + /* + * Periodic AS SDP (skip frames) needs the AS SDP to keep flowing during + * PR active, which is incompatible with DC3co. Keep DC3co disabled while + * skip frames is enabled. + */ + if (intel_alpm_pr_as_sdp_skip_frames_enabled(intel_dp, crtc_state)) + trigger = DC3CO_TRIGGER_NONE; + done: intel_display_power_dc3co_update(display, trigger); } From eddf77ff1a237f394364259108ff38d21be938cb Mon Sep 17 00:00:00 2001 From: Uma Shankar Date: Wed, 9 Sep 2026 13:38:09 +0530 Subject: [PATCH 12/98] drm/i915/display: Reprogram AS SDP skip frames on seamless VRR transitions The AS SDP skip-frame count is written to PR_ALPM_CTL only from lnl_alpm_configure(), which runs from intel_psr_enable_locked() on a Panel Replay disabled->enabled transition. VRR, however, can be enabled and disabled seamlessly - without a modeset and without cycling Panel Replay (intel_crtc_vrr_enabling()/disabling() in the pipe update path). As a result, when a panel comes up with VRR off the non-zero skip count is programmed, and when VRR is later turned on seamlessly PR stays enabled, lnl_alpm_configure() is not re-invoked, and the stale skip count is left in the register. This also leaves the coupled AS SDP transmission / DC3CO idle-protocol bits inconsistent with the DC3co state, which is recomputed on every commit. Factor the PR_ALPM_CTL AS SDP programming out of lnl_alpm_configure() into intel_alpm_configure_pr_as_sdp() and expose intel_alpm_pr_as_sdp_update(), which recomputes those fields for the current VRR state. Call it from the seamless VRR enable and disable sites (non-modeset only; a modeset re-runs PR enable anyway) so the skip counter always matches whether VRR is actively driving the refresh rate. v2: Fixed Sashiko review comments Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Uma Shankar Reviewed-by: Dibin Moolakadan Subrahmanian Tested-by: Naladala Ramanaidu Link: https://patch.msgid.link/20260909080810.2202879-4-uma.shankar@intel.com --- drivers/gpu/drm/i915/display/intel_alpm.c | 119 +++++++++++++------ drivers/gpu/drm/i915/display/intel_alpm.h | 1 + drivers/gpu/drm/i915/display/intel_display.c | 18 +++ 3 files changed, 100 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c index 0a33a89975bc..c784e77f610b 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.c +++ b/drivers/gpu/drm/i915/display/intel_alpm.c @@ -427,6 +427,85 @@ bool intel_alpm_pr_as_sdp_skip_frames_enabled(struct intel_dp *intel_dp, return intel_pr_as_sdp_skip_frames(intel_dp) > 0; } +/* + * Program the AS SDP portion of PR_ALPM_CTL: the transmission position, the + * skip-frame counter and the coupled AS SDP transmission / DC3CO idle-protocol + * bits. This is a full recompute of those fields (the base value is built from + * scratch, not read back), so it can be called both at PR enable time and when + * VRR is toggled seamlessly - which changes whether periodic AS SDP is used. + * + * Caller must hold intel_dp->alpm.lock. + */ +static void intel_alpm_configure_pr_as_sdp(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(intel_dp); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + u32 pr_alpm_ctl = get_pr_alpm_as_sdp_transmission_time(crtc_state); + u32 skip_frames = 0; + + if (intel_alpm_pr_as_sdp_skip_frames_enabled(intel_dp, crtc_state)) + skip_frames = intel_pr_as_sdp_skip_frames(intel_dp); + + if (crtc_state->link_off_after_as_sdp_when_pr_active) + pr_alpm_ctl |= PR_ALPM_CTL_ALLOW_LINK_OFF_BETWEEN_AS_SDP_AND_SU; + + /* + * Skip frames needs the AS SDP to keep flowing during PR active, so it + * is mutually exclusive with disabling AS SDP transmission in active and + * with the DC3CO idle protocol. + */ + if (skip_frames) { + pr_alpm_ctl |= PR_ALPM_CTL_AS_SDP_SKIP_FRAMES(skip_frames); + pr_alpm_ctl &= ~PR_ALPM_CTL_AS_SDP_TRANSMISSION_IN_ACTIVE_DISABLE; + pr_alpm_ctl &= ~PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL; + } else { + pr_alpm_ctl &= ~PR_ALPM_CTL_AS_SDP_SKIP_FRAMES_MASK; + + if (crtc_state->disable_as_sdp_when_pr_active) + pr_alpm_ctl |= PR_ALPM_CTL_AS_SDP_TRANSMISSION_IN_ACTIVE_DISABLE; + + if (intel_display_power_dc3co_allowed(display)) + pr_alpm_ctl |= PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL; + } + + intel_de_write(display, PR_ALPM_CTL(display, cpu_transcoder), pr_alpm_ctl); +} + +/* + * VRR can be enabled or disabled seamlessly, i.e. without a modeset and without + * cycling Panel Replay, so the AS SDP skip-frame programming done at PR enable + * time would otherwise go stale across a VRR toggle. Reprogram it here so the + * skip counter (and the coupled bits) matches the new VRR state. + */ +void intel_alpm_pr_as_sdp_update(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + struct intel_encoder *encoder; + + /* AS SDP skip frames field only exists on Xe3p_LPD+ */ + if (DISPLAY_VER(display) < 35) + return; + + for_each_intel_encoder_mask(display->drm, encoder, + crtc_state->uapi.encoder_mask) { + struct intel_dp *intel_dp; + + if (!intel_encoder_is_dp(encoder)) + continue; + + intel_dp = enc_to_intel_dp(encoder); + + if (!intel_dp->as_sdp_supported || + !intel_alpm_is_alpm_aux_less(intel_dp, crtc_state)) + continue; + + mutex_lock(&intel_dp->alpm.lock); + intel_alpm_configure_pr_as_sdp(intel_dp, crtc_state); + mutex_unlock(&intel_dp->alpm.lock); + } +} + static void lnl_alpm_configure(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { @@ -449,44 +528,8 @@ static void lnl_alpm_configure(struct intel_dp *intel_dp, ALPM_CTL_AUX_LESS_SLEEP_HOLD_TIME_50_SYMBOLS | ALPM_CTL_AUX_LESS_WAKE_TIME(crtc_state->alpm_state.aux_less_wake_lines); - if (intel_dp->as_sdp_supported) { - u32 pr_alpm_ctl = get_pr_alpm_as_sdp_transmission_time(crtc_state); - u32 skip_frames = 0; - - /* - * AS SDP skip frames field only exists on Xe3p_LPD+, and - * periodic AS SDP is a Panel Replay feature that is only - * used when VRR is not actively driving the refresh rate. - */ - if (DISPLAY_VER(display) >= 35 && crtc_state->has_panel_replay && - !crtc_state->vrr.enable) - skip_frames = intel_pr_as_sdp_skip_frames(intel_dp); - - if (crtc_state->link_off_after_as_sdp_when_pr_active) - pr_alpm_ctl |= PR_ALPM_CTL_ALLOW_LINK_OFF_BETWEEN_AS_SDP_AND_SU; - - /* - * Skip frames needs the AS SDP to keep flowing during PR - * active, so it is mutually exclusive with disabling AS SDP - * transmission in active and with the DC3CO idle protocol. - */ - if (skip_frames) { - pr_alpm_ctl |= PR_ALPM_CTL_AS_SDP_SKIP_FRAMES(skip_frames); - pr_alpm_ctl &= ~PR_ALPM_CTL_AS_SDP_TRANSMISSION_IN_ACTIVE_DISABLE; - pr_alpm_ctl &= ~PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL; - } else { - pr_alpm_ctl &= ~PR_ALPM_CTL_AS_SDP_SKIP_FRAMES_MASK; - - if (crtc_state->disable_as_sdp_when_pr_active) - pr_alpm_ctl |= PR_ALPM_CTL_AS_SDP_TRANSMISSION_IN_ACTIVE_DISABLE; - - if (intel_display_power_dc3co_allowed(display)) - pr_alpm_ctl |= PR_ALPM_CTL_USE_DC3CO_IDLE_PROTOCOL; - } - - intel_de_write(display, PR_ALPM_CTL(display, cpu_transcoder), - pr_alpm_ctl); - } + if (intel_dp->as_sdp_supported) + intel_alpm_configure_pr_as_sdp(intel_dp, crtc_state); } else { alpm_ctl = ALPM_CTL_EXTENDED_FAST_WAKE_ENABLE | diff --git a/drivers/gpu/drm/i915/display/intel_alpm.h b/drivers/gpu/drm/i915/display/intel_alpm.h index 328920027f1c..f8f605d94f96 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.h +++ b/drivers/gpu/drm/i915/display/intel_alpm.h @@ -36,6 +36,7 @@ bool intel_alpm_is_alpm_aux_less(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state); bool intel_alpm_pr_as_sdp_skip_frames_enabled(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state); +void intel_alpm_pr_as_sdp_update(const struct intel_crtc_state *crtc_state); void intel_alpm_disable(struct intel_dp *intel_dp); bool intel_alpm_get_error(struct intel_dp *intel_dp); void intel_alpm_lobf_compute_config_late(struct intel_dp *intel_dp, diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index fc30a455bed3..9151ea6c15ab 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1232,6 +1232,14 @@ static void intel_pre_plane_update(struct intel_atomic_state *state, intel_vrr_disable(old_crtc_state); intel_vrr_dcb_reset(old_crtc_state, crtc); intel_crtc_update_active_timings(old_crtc_state, false); + + /* + * VRR is being disabled seamlessly (no modeset, Panel Replay + * stays enabled), so re-apply the AS SDP skip-frame programming + * for the new (VRR off) state. + */ + if (!intel_crtc_needs_modeset(new_crtc_state)) + intel_alpm_pr_as_sdp_update(new_crtc_state); } if (audio_disabling(old_crtc_state, new_crtc_state)) @@ -6971,6 +6979,16 @@ static void intel_update_crtc(struct intel_atomic_state *state, intel_crtc_update_active_timings(new_crtc_state, new_crtc_state->vrr.enable); + /* + * VRR is being enabled seamlessly (no modeset, Panel Replay stays + * enabled), so re-apply the AS SDP skip-frame programming for the new + * (VRR on) state. Done here, outside the vblank-evasion critical section + * (which runs with interrupts disabled), because it takes alpm.lock. + */ + if (intel_crtc_vrr_enabling(state, crtc) && + !intel_crtc_needs_modeset(new_crtc_state)) + intel_alpm_pr_as_sdp_update(new_crtc_state); + if (new_crtc_state->vrr.dc_balance.enable) intel_vrr_dcb_increment_flip_count(new_crtc_state, crtc); From 9ed39b7d74b43825dbe3932d41d75294b0295064 Mon Sep 17 00:00:00 2001 From: Uma Shankar Date: Wed, 9 Sep 2026 13:38:10 +0530 Subject: [PATCH 13/98] drm/i915/display: Gate periodic AS SDP skip frames behind a debugfs knob Periodic AS SDP (skip frames) drives a Panel Replay panel down toward its minimum refresh rate. It is a new, panel- and platform-sensitive behaviour, so keep it opt-in rather than enabling it unconditionally. Expose it as a per-device debugfs knob, enable_periodic_assdp, rather than a module parameter. The behaviour is panel-specific, so the correct granularity is per-device, not per-module. The knob is added through the intel_display_params infrastructure (shared by i915 and xe) with a debugfs entry only. It defaults to false (feature disabled); write 1 to the debugfs file to enable periodic AS SDP at runtime. Gate the feature at its single choke point, intel_pr_as_sdp_skip_frames(): returning a zero skip count when the knob is off makes both the PR_ALPM_CTL programming (intel_alpm_configure_pr_as_sdp()) and the DC3co force-disable predicate (intel_alpm_pr_as_sdp_skip_frames_enabled()) a no-op, so AS SDP continues to be sent on every frame as before. v2: Switch to debugfs entry and drop module param Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Uma Shankar Reviewed-by: Dibin Moolakadan Subrahmanian Tested-by: Naladala Ramanaidu Link: https://patch.msgid.link/20260909080810.2202879-5-uma.shankar@intel.com --- drivers/gpu/drm/i915/display/intel_alpm.c | 5 +++++ drivers/gpu/drm/i915/display/intel_display_params.h | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c index c784e77f610b..10943539bc7c 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.c +++ b/drivers/gpu/drm/i915/display/intel_alpm.c @@ -392,11 +392,16 @@ static u32 get_pr_alpm_as_sdp_transmission_time(const struct intel_crtc_state *c */ static u32 intel_pr_as_sdp_skip_frames(struct intel_dp *intel_dp) { + struct intel_display *display = to_intel_display(intel_dp); const struct drm_display_info *info = &intel_dp->attached_connector->base.display_info; int max_vrefresh = info->monitor_range.max_vfreq; int min_vrefresh = info->monitor_range.min_vfreq; + /* Off by default; gated by the enable_periodic_assdp debugfs knob. */ + if (!display->params.enable_periodic_assdp) + return 0; + if (min_vrefresh <= 0 || max_vrefresh <= min_vrefresh) return 0; diff --git a/drivers/gpu/drm/i915/display/intel_display_params.h b/drivers/gpu/drm/i915/display/intel_display_params.h index b95ecf728daa..ba01aeaf8944 100644 --- a/drivers/gpu/drm/i915/display/intel_display_params.h +++ b/drivers/gpu/drm/i915/display/intel_display_params.h @@ -50,6 +50,11 @@ struct drm_printer; param(bool, psr_safest_params, false, 0400) \ param(bool, enable_psr2_sel_fetch, true, 0400) \ param(int, enable_dmc_wl, -1, 0400) \ + /* + * Debugfs-only knob (per-device): no matching module_param is registered + * in intel_display_params.c on purpose. Runtime-toggle via debugfs. + */ \ + param(bool, enable_periodic_assdp, false, 0600) \ #define MEMBER(T, member, ...) T member; struct intel_display_params { From fe05cb9b9fb0ecc10409c4c6133257214b6cd8c8 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 8 Sep 2026 13:06:51 +0300 Subject: [PATCH 14/98] drm/i915/display: check configuration index before shifting The calc_allowed_config_filter() function passes the return value of iter_pos_to_idx() directly to BIT(), but the helper can return -1 for an invalid iterator. The iterator already rejects negative indices before doing a configuration, so this should not matter in normal flows. In any case, for robustness, check the index explicitly and warn if it is negative, avoiding an undefined shift. Fixes: 39e30bdf2f92 ("drm/i915/dp_link_caps: Add link configuration iterator") Reviewed-by: Imre Deak Link: https://patch.msgid.link/20260908100659.113555-1-luciano.coelho@intel.com Signed-off-by: Luca Coelho --- drivers/gpu/drm/i915/display/intel_dp_link_caps.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_caps.c b/drivers/gpu/drm/i915/display/intel_dp_link_caps.c index 7b6cc6055da8..98657aa4d3d5 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_caps.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_caps.c @@ -426,12 +426,15 @@ calc_allowed_config_filter(struct intel_dp_link_caps *link_caps, const struct intel_dp_link_config *forced_params) { struct intel_dp_link_caps_filter allowed_configs = INTEL_DP_LINK_CAPS_FILTER_NONE; + struct intel_display *display = to_intel_display(link_caps->dp); struct intel_dp_link_caps_order order = bw_desc_config_order(); struct intel_dp_link_caps_iter iter; struct intel_dp_link_config config; iter_start(&iter, link_caps, order, enabled_configs); for_each_dp_link_config(&iter, &config) { + int config_idx; + if (forced_params->rate && forced_params->rate != config.rate) continue; @@ -446,7 +449,11 @@ calc_allowed_config_filter(struct intel_dp_link_caps *link_caps, if (config.lane_count > max_limits->lane_count) continue; - allowed_configs.config_mask |= BIT(iter_pos_to_idx(link_caps, order, iter.pos)); + config_idx = iter_pos_to_idx(link_caps, order, iter.pos); + if (drm_WARN_ON(display->drm, config_idx < 0)) + continue; + + allowed_configs.config_mask |= BIT(config_idx); } intel_dp_link_caps_iter_end(&iter); From 3aef9c94c02b3e66cfacd70492b6604947010d35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 3 Sep 2026 16:01:16 +0300 Subject: [PATCH 15/98] drm/i915: Perform full wedge on display reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We lost the proper display reset deadlock handling in commit d59cf7bb73f3 ("drm/i915/display: Use dma_fence interfaces instead of i915_sw_fence"). Currently the only thing that eventually breaks the deadlock is the 10 second fence timeout, which is very slow. I tried to essentially restore the previous mechanism via a custom dma_fence in https://lore.kernel.org/intel-gfx/20260408233458.22666-6-ville.syrjala@linux.intel.com/ but Christian didn't want it. The ideal solution would be to allow the reset time modesets to proceed ahead of any already queued atomic commits, but that is quite involved since we need to be able to track the already committed (to the hardware) atomic states in addition to the userspace queued atomic states. Years ago I did implement something like that in https://lore.kernel.org/intel-gfx/20170629134948.5614-1-ville.syrjala@linux.intel.com/ but Sima didn't want it. In order to get rid of the dependency on the timeout, and make things faster, let's just effectively revert the remainders of commit 9db529aac938 ("drm/i915: More surgically unbreak the modeset vs reset deadlock"). The upside is that the reset is fast again, but the downside is that we now do a full wedge on all display resets, which will also kill innocent batches. But perhaps no one really cares since this is currently only needed for old pre-g4x hardware. But if anyone has plans on using eg. FLR as a backup GPU reset on new hardware then we probably need to come up with something better... Signed-off-by: Ville Syrjälä Link: https://patch.msgid.link/20260903130116.19089-1-ville.syrjala@linux.intel.com Acked-by: Jani Nikula --- drivers/gpu/drm/i915/gt/intel_reset.c | 8 +------- drivers/gpu/drm/i915/i915_dpt.c | 2 -- drivers/gpu/drm/i915/i915_drv.h | 2 -- drivers/gpu/drm/i915/i915_fb_pin.c | 6 ------ drivers/gpu/drm/i915/i915_overlay.c | 5 ----- 5 files changed, 1 insertion(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index b2cf672564dd..0968932c0b4f 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -1433,13 +1433,7 @@ static void intel_gt_reset_global(struct intel_gt *gt, need_display_reset; if (reset_display) { - if (atomic_read(&i915->pending_fb_pin)) { - drm_dbg_kms(&i915->drm, - "Modeset potentially stuck, unbreaking through wedging\n"); - - intel_gt_set_wedged(gt); - } - + intel_gt_set_wedged(gt); intel_display_reset_prepare(display); } diff --git a/drivers/gpu/drm/i915/i915_dpt.c b/drivers/gpu/drm/i915/i915_dpt.c index e01dc4de1788..85d872c0f387 100644 --- a/drivers/gpu/drm/i915/i915_dpt.c +++ b/drivers/gpu/drm/i915/i915_dpt.c @@ -139,7 +139,6 @@ struct i915_vma *i915_dpt_pin_to_ggtt(struct intel_dpt *dpt, unsigned int alignm pin_flags |= PIN_MAPPABLE; wakeref = intel_runtime_pm_get(&i915->runtime_pm); - atomic_inc(&i915->pending_fb_pin); for_i915_gem_ww(&ww, err, true) { err = i915_gem_object_lock(dpt->obj, &ww); @@ -169,7 +168,6 @@ struct i915_vma *i915_dpt_pin_to_ggtt(struct intel_dpt *dpt, unsigned int alignm dpt->obj->mm.dirty = true; - atomic_dec(&i915->pending_fb_pin); intel_runtime_pm_put(&i915->runtime_pm, wakeref); return err ? ERR_PTR(err) : vma; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 844ed79e7211..dafee3dcd1c5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -315,8 +315,6 @@ struct drm_i915_private { /* The TTM device structure. */ struct ttm_device bdev; - atomic_t pending_fb_pin; - I915_SELFTEST_DECLARE(struct i915_selftest_stash selftest;) /* diff --git a/drivers/gpu/drm/i915/i915_fb_pin.c b/drivers/gpu/drm/i915/i915_fb_pin.c index 1034cb767e9f..63be136f1a05 100644 --- a/drivers/gpu/drm/i915/i915_fb_pin.c +++ b/drivers/gpu/drm/i915/i915_fb_pin.c @@ -35,8 +35,6 @@ intel_fb_pin_to_dpt(struct drm_gem_object *_obj, struct intel_dpt *dpt, if (WARN_ON(!i915_gem_object_is_framebuffer(obj))) return ERR_PTR(-EINVAL); - atomic_inc(&i915->pending_fb_pin); - for_i915_gem_ww(&ww, ret, true) { ret = i915_gem_object_lock(obj, &ww); if (ret) @@ -98,7 +96,6 @@ intel_fb_pin_to_dpt(struct drm_gem_object *_obj, struct intel_dpt *dpt, */ drm_WARN_ON(&i915->drm, i915_dpt_offset(vma)); err: - atomic_dec(&i915->pending_fb_pin); return vma; } @@ -132,8 +129,6 @@ intel_fb_pin_to_ggtt(struct drm_gem_object *_obj, */ wakeref = intel_runtime_pm_get(&i915->runtime_pm); - atomic_inc(&i915->pending_fb_pin); - pinctl = 0; /* PIN_MAPPABLE limits the address to GMADR size */ if (pin_params->needs_low_address) @@ -206,7 +201,6 @@ intel_fb_pin_to_ggtt(struct drm_gem_object *_obj, if (ret) vma = ERR_PTR(ret); - atomic_dec(&i915->pending_fb_pin); intel_runtime_pm_put(&i915->runtime_pm, wakeref); return vma; } diff --git a/drivers/gpu/drm/i915/i915_overlay.c b/drivers/gpu/drm/i915/i915_overlay.c index 6de550a17756..c1a7920c6324 100644 --- a/drivers/gpu/drm/i915/i915_overlay.c +++ b/drivers/gpu/drm/i915/i915_overlay.c @@ -354,14 +354,11 @@ static struct i915_vma *i915_overlay_pin_fb(struct drm_device *drm, struct drm_gem_object *obj, u32 *offset) { - struct drm_i915_private *i915 = to_i915(drm); struct drm_i915_gem_object *new_bo = to_intel_bo(obj); struct i915_gem_ww_ctx ww; struct i915_vma *vma; int ret; - atomic_inc(&i915->pending_fb_pin); - i915_gem_ww_ctx_init(&ww, true); retry: ret = i915_gem_object_lock(new_bo, &ww); @@ -377,8 +374,6 @@ static struct i915_vma *i915_overlay_pin_fb(struct drm_device *drm, } i915_gem_ww_ctx_fini(&ww); - atomic_dec(&i915->pending_fb_pin); - if (ret) return ERR_PTR(ret); From d393529394167e0f5f706657eebe84d8529ce4fc Mon Sep 17 00:00:00 2001 From: Nemesa Garg Date: Wed, 9 Sep 2026 16:33:31 +0530 Subject: [PATCH 16/98] Revert "drm/i915/display: Clear SEL_FETCH_PLANE_CTL on plane disable" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 7f1172a2ac0d7e50850785e2e65789c8aac8411a. This commit replaced the crtc_state->enable_psr2_sel_fetch guard in icl_plane_disable_sel_fetch_arm() and i9xx_cursor_disable_sel_fetch_arm() with HAS_PSR2_SEL_FETCH(). This is a display version check and says nothing about the pipe, so every plane and cursor disable on a display 12+ platform started writing SEL_FETCH_PLANE_CTL() / SEL_FETCH_CUR_CTL(), including on pipes that do not implement them. It shows up as an unclaimed register access on pipes driving HDMI where selective fetch was never enabled. The stale selective fetch enable bit that commit addressed is handled in the next patch. Fixes: 7f1172a2ac0d ("drm/i915/display: Clear SEL_FETCH_PLANE_CTL on plane disable") Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/work_items/16876 Cc: stable@vger.kernel.org Signed-off-by: Nemesa Garg Reviewed-by: Jouni Högander Signed-off-by: Suraj Kandpal Link: https://patch.msgid.link/20260909110332.3528029-2-nemesa.garg@intel.com --- drivers/gpu/drm/i915/display/intel_cursor.c | 15 +++++---------- .../gpu/drm/i915/display/skl_universal_plane.c | 15 +++++---------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index cce041e1da51..90173040d825 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -531,18 +531,13 @@ static int i9xx_check_cursor(struct intel_crtc_state *crtc_state, } static void i9xx_cursor_disable_sel_fetch_arm(struct intel_dsb *dsb, - struct intel_plane *plane) + struct intel_plane *plane, + const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(plane); enum pipe pipe = plane->pipe; - /* - * Clear this whenever the hardware has selective fetch, not just when - * the current state uses it. The cursor may have been enabled with - * selective fetch earlier and had its enable bit orphaned when the - * feature was switched off. - */ - if (!HAS_PSR2_SEL_FETCH(display)) + if (!crtc_state->enable_psr2_sel_fetch) return; intel_de_write_dsb(display, dsb, SEL_FETCH_CUR_CTL(pipe), 0); @@ -592,7 +587,7 @@ static void i9xx_cursor_update_sel_fetch_arm(struct intel_dsb *dsb, if (crtc_state->enable_psr2_su_region_et) wa_16021440873(dsb, plane, crtc_state, plane_state); else - i9xx_cursor_disable_sel_fetch_arm(dsb, plane); + i9xx_cursor_disable_sel_fetch_arm(dsb, plane, crtc_state); } } @@ -701,7 +696,7 @@ static void i9xx_cursor_update_arm(struct intel_dsb *dsb, if (plane_state) i9xx_cursor_update_sel_fetch_arm(dsb, plane, crtc_state, plane_state); else - i9xx_cursor_disable_sel_fetch_arm(dsb, plane); + i9xx_cursor_disable_sel_fetch_arm(dsb, plane, crtc_state); if (plane->cursor.base != base || plane->cursor.size != fbc_ctl || diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 5cda1ab90e40..07a683293352 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -879,18 +879,13 @@ skl_plane_disable_arm(struct intel_dsb *dsb, } static void icl_plane_disable_sel_fetch_arm(struct intel_dsb *dsb, - struct intel_plane *plane) + struct intel_plane *plane, + const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(plane); enum pipe pipe = plane->pipe; - /* - * Clear this whenever the hardware has selective fetch, not just when - * the current state uses it. The plane may have been enabled with - * selective fetch earlier and had its enable bit orphaned when the - * feature was switched off. - */ - if (!HAS_PSR2_SEL_FETCH(display)) + if (!crtc_state->enable_psr2_sel_fetch) return; intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id), 0); @@ -926,7 +921,7 @@ icl_plane_disable_arm(struct intel_dsb *dsb, skl_write_plane_wm(dsb, plane, crtc_state); - icl_plane_disable_sel_fetch_arm(dsb, plane); + icl_plane_disable_sel_fetch_arm(dsb, plane, crtc_state); if (plane_has_normalizer(plane)) intel_de_write_dsb(display, dsb, @@ -1646,7 +1641,7 @@ static void icl_plane_update_sel_fetch_arm(struct intel_dsb *dsb, intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id), SEL_FETCH_PLANE_CTL_ENABLE); else - icl_plane_disable_sel_fetch_arm(dsb, plane); + icl_plane_disable_sel_fetch_arm(dsb, plane, crtc_state); } static void From a4c0e7f80429eda6990960971aebd4e4b9533cc6 Mon Sep 17 00:00:00 2001 From: Nemesa Garg Date: Wed, 9 Sep 2026 16:33:32 +0530 Subject: [PATCH 17/98] drm/i915/psr: Clear stale sel fetch enable bits on sel fetch disable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Selective fetch is dropped while pipe CRC is active, and the planes keep their SEL_FETCH_PLANE_CTL / SEL_FETCH_CUR_CTL enable bit set in hardware over that. A plane disabled while selective fetch is off never gets the bit cleared, as the disable path is guarded by enable_psr2_sel_fetch. Once selective fetch comes back the hardware resumes fetching for a plane that is no longer enabled and keeps its DDB range reserved. Clear the bits as selective fetch is turned off instead. Atomic check has both the old and the new crtc state, so record the transition there and let the plane and cursor arm paths write the registers to 0 for that commit. v2: Drop the old_crtc_state->hw.active check. [Jouni] Fixes: b1f5279b5981 ("drm/i915/psr: Move plane sel fetch configuration into plane source files") Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/work_items/8739 Assisted-by: Copilot:Claude-Opus-5 Signed-off-by: Nemesa Garg Reviewed-by: Jouni Högander Signed-off-by: Suraj Kandpal Link: https://patch.msgid.link/20260909110332.3528029-3-nemesa.garg@intel.com --- drivers/gpu/drm/i915/display/intel_cursor.c | 7 +++++-- .../gpu/drm/i915/display/intel_display_types.h | 2 ++ drivers/gpu/drm/i915/display/intel_psr.c | 15 +++++++++++++++ .../gpu/drm/i915/display/skl_universal_plane.c | 9 ++++----- 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index 90173040d825..4afd275de86e 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -537,7 +537,8 @@ static void i9xx_cursor_disable_sel_fetch_arm(struct intel_dsb *dsb, struct intel_display *display = to_intel_display(plane); enum pipe pipe = plane->pipe; - if (!crtc_state->enable_psr2_sel_fetch) + if (!crtc_state->enable_psr2_sel_fetch && + !crtc_state->clear_psr2_sel_fetch) return; intel_de_write_dsb(display, dsb, SEL_FETCH_CUR_CTL(pipe), 0); @@ -570,8 +571,10 @@ static void i9xx_cursor_update_sel_fetch_arm(struct intel_dsb *dsb, struct intel_display *display = to_intel_display(plane); enum pipe pipe = plane->pipe; - if (!crtc_state->enable_psr2_sel_fetch) + if (!crtc_state->enable_psr2_sel_fetch) { + i9xx_cursor_disable_sel_fetch_arm(dsb, plane, crtc_state); return; + } if (drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0) { if (crtc_state->enable_psr2_su_region_et) { diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 9016be52c7ea..ec99ff10391c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1190,6 +1190,8 @@ struct intel_crtc_state { bool has_sel_update; bool enable_psr2_sel_fetch; bool enable_psr2_su_region_et; + /* Drop the stale selective fetch enable bits as selective fetch is turned off */ + bool clear_psr2_sel_fetch; bool req_psr2_sdp_prior_scanline; bool has_panel_replay; bool link_off_after_as_sdp_when_pr_active; diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index f490beb66629..872e253db178 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -2889,6 +2889,8 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, struct intel_crtc *crtc) { struct intel_display *display = to_intel_display(state); + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); struct intel_plane_state *new_plane_state, *old_plane_state; struct intel_plane *plane; @@ -2901,6 +2903,19 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, bool full_update = false, su_area_changed; int i, ret; + /* + * Selective fetch is not always usable, for instance it is dropped + * while pipe CRC is active. The planes keep their selective fetch + * enable bit set in hardware over that, and a plane disabled while + * selective fetch is off never gets the bit cleared. Once selective + * fetch comes back the hardware would resume fetching for a plane that + * is no longer enabled and keep its DDB range reserved, so have the + * plane update drop the bit for every plane of the pipe as selective + * fetch is turned off. + */ + crtc_state->clear_psr2_sel_fetch = old_crtc_state->enable_psr2_sel_fetch && + !crtc_state->enable_psr2_sel_fetch; + if (!crtc_state->enable_psr2_sel_fetch) return 0; diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 07a683293352..eb5ed981b40f 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -885,7 +885,8 @@ static void icl_plane_disable_sel_fetch_arm(struct intel_dsb *dsb, struct intel_display *display = to_intel_display(plane); enum pipe pipe = plane->pipe; - if (!crtc_state->enable_psr2_sel_fetch) + if (!crtc_state->enable_psr2_sel_fetch && + !crtc_state->clear_psr2_sel_fetch) return; intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id), 0); @@ -1634,10 +1635,8 @@ static void icl_plane_update_sel_fetch_arm(struct intel_dsb *dsb, struct intel_display *display = to_intel_display(plane); enum pipe pipe = plane->pipe; - if (!crtc_state->enable_psr2_sel_fetch) - return; - - if (drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0) + if (crtc_state->enable_psr2_sel_fetch && + drm_rect_height(&plane_state->psr2_sel_fetch_area) > 0) intel_de_write_dsb(display, dsb, SEL_FETCH_PLANE_CTL(pipe, plane->id), SEL_FETCH_PLANE_CTL_ENABLE); else From 985bc8ee612328771308761822fbc4c62a21a0d8 Mon Sep 17 00:00:00 2001 From: Chaitanya Kumar Borah Date: Wed, 2 Sep 2026 13:24:09 +0530 Subject: [PATCH 18/98] drm/i915/color: Add CSC on SDR plane color pipeline Add the fixed-function CSC block to color pipeline in SDR planes as a DRM_COLOROP_FIXED_MATRIX colorop. v2: - s/DRM_COLOROP_FM_YCBCR2020_FULL_RGB_NC/ DRM_COLOROP_FM_YCBCR2020_NC_FULL_RGB - Inline icl_is_hdr_plane() instead of storing in local variable v3: - In preparation of a simple pipeline [YUV Full/Limited -> RGB] Make the Fixed Matrix ColorOp support Limited Range enums (DRM_COLOROP_FM_YCBCRXXX_LIMITED_RGB) too. - Therefore s/sdr_plane_pipeline/sdr_plane_yuv_pipeline Signed-off-by: Chaitanya Kumar Borah Reviewed-by: Uma Shankar Link: https://patch.msgid.link/20260902075417.656673-2-chaitanya.kumar.borah@intel.com --- .../drm/i915/display/intel_color_pipeline.c | 23 ++++++++++++++++++- .../drm/i915/display/intel_display_limits.h | 1 + 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_color_pipeline.c b/drivers/gpu/drm/i915/display/intel_color_pipeline.c index 6cf8080ee800..efd4375c4331 100644 --- a/drivers/gpu/drm/i915/display/intel_color_pipeline.c +++ b/drivers/gpu/drm/i915/display/intel_color_pipeline.c @@ -43,6 +43,18 @@ static const enum intel_color_block hdr_plane_pipeline[] = { INTEL_PLANE_CB_POST_CSC_LUT, }; +static const enum intel_color_block sdr_plane_yuv_pipeline[] = { + INTEL_PLANE_CB_CSC_FF, +}; + +static const u64 intel_plane_supported_csc_ff = + BIT(DRM_COLOROP_FM_YCBCR601_FULL_RGB) | + BIT(DRM_COLOROP_FM_YCBCR601_LIMITED_RGB) | + BIT(DRM_COLOROP_FM_YCBCR709_FULL_RGB) | + BIT(DRM_COLOROP_FM_YCBCR709_LIMITED_RGB) | + BIT(DRM_COLOROP_FM_YCBCR2020_NC_FULL_RGB) | + BIT(DRM_COLOROP_FM_YCBCR2020_NC_LIMITED_RGB); + static bool plane_has_3dlut(struct intel_display *display, enum pipe pipe, struct drm_plane *plane) { @@ -92,6 +104,12 @@ struct intel_colorop *intel_color_pipeline_plane_add_colorop(struct drm_plane *p DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR, DRM_COLOROP_FLAG_ALLOW_BYPASS); break; + case INTEL_PLANE_CB_CSC_FF: + ret = drm_plane_colorop_fixed_matrix_init(dev, &colorop->base, plane, + &intel_colorop_funcs, + intel_plane_supported_csc_ff, + DRM_COLOROP_FLAG_ALLOW_BYPASS); + break; default: drm_err(plane->dev, "Invalid colorop id [%d]", id); ret = -EINVAL; @@ -126,9 +144,12 @@ int _intel_color_pipeline_plane_init(struct drm_plane *plane, struct drm_prop_en if (plane_has_3dlut(display, pipe, plane)) { pipeline = xe3plpd_primary_plane_pipeline; pipeline_len = ARRAY_SIZE(xe3plpd_primary_plane_pipeline); - } else { + } else if (icl_is_hdr_plane(display, to_intel_plane(plane)->id)) { pipeline = hdr_plane_pipeline; pipeline_len = ARRAY_SIZE(hdr_plane_pipeline); + } else { + pipeline = sdr_plane_yuv_pipeline; + pipeline_len = ARRAY_SIZE(sdr_plane_yuv_pipeline); } for (i = 0; i < pipeline_len; i++) { diff --git a/drivers/gpu/drm/i915/display/intel_display_limits.h b/drivers/gpu/drm/i915/display/intel_display_limits.h index ea89473c177f..7ba7360c574e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_limits.h +++ b/drivers/gpu/drm/i915/display/intel_display_limits.h @@ -169,6 +169,7 @@ enum aux_ch { enum intel_color_block { INTEL_PLANE_CB_PRE_CSC_LUT, INTEL_PLANE_CB_CSC, + INTEL_PLANE_CB_CSC_FF, INTEL_PLANE_CB_POST_CSC_LUT, INTEL_PLANE_CB_3DLUT, From 0bc13827b3dac986124d81c0d3ef840f664d5308 Mon Sep 17 00:00:00 2001 From: Chaitanya Kumar Borah Date: Wed, 2 Sep 2026 13:24:10 +0530 Subject: [PATCH 19/98] drm/i915/display: extract glk_plane_color_ctl_input_csc helper Extract the input CSC and YUV range correction logic from glk_plane_color_ctl() into a dedicated glk_plane_color_ctl_input_csc() helper. No functional change. Signed-off-by: Chaitanya Kumar Borah Reviewed-by: Uma Shankar Link: https://patch.msgid.link/20260902075417.656673-3-chaitanya.kumar.borah@intel.com --- .../drm/i915/display/skl_universal_plane.c | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index eb5ed981b40f..e5384d2e5e8e 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -1241,37 +1241,43 @@ static u32 glk_plane_color_ctl_crtc(const struct intel_crtc_state *crtc_state) return plane_color_ctl; } -static u32 glk_plane_color_ctl(const struct intel_plane_state *plane_state) +static u32 glk_plane_color_ctl_input_csc(const struct intel_plane_state *plane_state) { struct intel_display *display = to_intel_display(plane_state); const struct drm_framebuffer *fb = plane_state->hw.fb; struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); - u32 plane_color_ctl = 0; - - plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; - plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state); + u32 ctl = 0; if (fb->format->is_yuv && !icl_is_hdr_plane(display, plane->id)) { switch (plane_state->hw.color_encoding) { case DRM_COLOR_YCBCR_BT709: - plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709; + ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709; break; case DRM_COLOR_YCBCR_BT2020: - plane_color_ctl |= - PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020; + ctl |= PLANE_COLOR_CSC_MODE_YUV2020_TO_RGB2020; break; default: - plane_color_ctl |= - PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601; + ctl |= PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601; } if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) - plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; + ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; } else if (fb->format->is_yuv) { - plane_color_ctl |= PLANE_COLOR_INPUT_CSC_ENABLE; + ctl |= PLANE_COLOR_INPUT_CSC_ENABLE; if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) - plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; + ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; } + return ctl; +} + +static u32 glk_plane_color_ctl(const struct intel_plane_state *plane_state) +{ + u32 plane_color_ctl = 0; + + plane_color_ctl |= PLANE_COLOR_PLANE_GAMMA_DISABLE; + plane_color_ctl |= glk_plane_color_ctl_alpha(plane_state); + plane_color_ctl |= glk_plane_color_ctl_input_csc(plane_state); + if (plane_state->force_black) plane_color_ctl |= PLANE_COLOR_PLANE_CSC_ENABLE; From f4a41051c370987cabff3504ff9c1f6e0e66fe53 Mon Sep 17 00:00:00 2001 From: Chaitanya Kumar Borah Date: Wed, 2 Sep 2026 13:24:11 +0530 Subject: [PATCH 20/98] drm/i915/display: simplify glk_plane_color_ctl_input_csc Add early return for non-YUV formats and hoist the duplicated color_range check out of the if/else branches. No functional change. Signed-off-by: Chaitanya Kumar Borah Reviewed-by: Uma Shankar Link: https://patch.msgid.link/20260902075417.656673-4-chaitanya.kumar.borah@intel.com --- drivers/gpu/drm/i915/display/skl_universal_plane.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index e5384d2e5e8e..4aafd9ff3ac6 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -1248,7 +1248,10 @@ static u32 glk_plane_color_ctl_input_csc(const struct intel_plane_state *plane_s struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); u32 ctl = 0; - if (fb->format->is_yuv && !icl_is_hdr_plane(display, plane->id)) { + if (!fb->format->is_yuv) + return 0; + + if (!icl_is_hdr_plane(display, plane->id)) { switch (plane_state->hw.color_encoding) { case DRM_COLOR_YCBCR_BT709: ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709; @@ -1259,14 +1262,13 @@ static u32 glk_plane_color_ctl_input_csc(const struct intel_plane_state *plane_s default: ctl |= PLANE_COLOR_CSC_MODE_YUV601_TO_RGB601; } - if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) - ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; - } else if (fb->format->is_yuv) { + } else { ctl |= PLANE_COLOR_INPUT_CSC_ENABLE; - if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) - ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; } + if (plane_state->hw.color_range == DRM_COLOR_YCBCR_FULL_RANGE) + ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE; + return ctl; } From f1bc49ff6209f7256ddb1f3804b374e033ff8379 Mon Sep 17 00:00:00 2001 From: Chaitanya Kumar Borah Date: Wed, 2 Sep 2026 13:24:12 +0530 Subject: [PATCH 21/98] drm/i915/display: Program CSC on SDR planes based on Fixed Matrix Colorop When a color pipeline is active, program the SDR plane fixed-function CSC based on the Fixed Matrix Colorop's state. Re-use the existing plane state variables for color_range and color_encoding. Track the bypass state explicitly as a boolean since bypass is managed separately from the FIXED_MATRIX enum value in the colorop framework. Keep the programming based on color_encoding/color_range legacy properties intact. Signed-off-by: Chaitanya Kumar Borah Reviewed-by: Uma Shankar Link: https://patch.msgid.link/20260902075417.656673-5-chaitanya.kumar.borah@intel.com --- .../drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_plane.c | 53 ++++++++++++++++++- .../drm/i915/display/skl_universal_plane.c | 4 +- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index ec99ff10391c..a5f18ac8a7d0 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -686,6 +686,7 @@ struct intel_plane_state { enum drm_color_range color_range; enum drm_scaling_filter scaling_filter; struct drm_property_blob *ctm, *degamma_lut, *gamma_lut, *lut_3d; + bool csc_ff_enable; } hw; struct i915_vma *ggtt_vma; diff --git a/drivers/gpu/drm/i915/display/intel_plane.c b/drivers/gpu/drm/i915/display/intel_plane.c index d0f99a87c42e..25ca049009ef 100644 --- a/drivers/gpu/drm/i915/display/intel_plane.c +++ b/drivers/gpu/drm/i915/display/intel_plane.c @@ -462,6 +462,42 @@ intel_plane_colorop_replace_blob(struct intel_plane_state *plane_state, return false; } +static u32 +fixedmatrix_colorop_to_encoding(enum drm_colorop_fixed_matrix_type fm_type) +{ + switch (fm_type) { + case DRM_COLOROP_FM_YCBCR709_FULL_RGB: + case DRM_COLOROP_FM_YCBCR709_LIMITED_RGB: + return DRM_COLOR_YCBCR_BT709; + + case DRM_COLOROP_FM_YCBCR2020_NC_FULL_RGB: + case DRM_COLOROP_FM_YCBCR2020_NC_LIMITED_RGB: + return DRM_COLOR_YCBCR_BT2020; + + case DRM_COLOROP_FM_YCBCR601_FULL_RGB: + case DRM_COLOROP_FM_YCBCR601_LIMITED_RGB: + default: + return DRM_COLOR_YCBCR_BT601; + } +} + +static u32 +fixedmatrix_colorop_to_range(enum drm_colorop_fixed_matrix_type fm_type) +{ + switch (fm_type) { + case DRM_COLOROP_FM_YCBCR601_FULL_RGB: + case DRM_COLOROP_FM_YCBCR709_FULL_RGB: + case DRM_COLOROP_FM_YCBCR2020_NC_FULL_RGB: + return DRM_COLOR_YCBCR_FULL_RANGE; + + case DRM_COLOROP_FM_YCBCR601_LIMITED_RGB: + case DRM_COLOROP_FM_YCBCR709_LIMITED_RGB: + case DRM_COLOROP_FM_YCBCR2020_NC_LIMITED_RGB: + default: + return DRM_COLOR_YCBCR_LIMITED_RANGE; + } +} + static void intel_plane_color_copy_uapi_to_hw_state(struct intel_atomic_state *state, struct intel_plane_state *plane_state, @@ -474,6 +510,7 @@ intel_plane_color_copy_uapi_to_hw_state(struct intel_atomic_state *state, struct drm_property_blob *blob; struct intel_crtc_state *new_crtc_state = state ? intel_atomic_get_new_crtc_state(state, crtc) : NULL; + enum drm_colorop_fixed_matrix_type fm_type; bool changed = false; int i = 0; @@ -485,11 +522,23 @@ intel_plane_color_copy_uapi_to_hw_state(struct intel_atomic_state *state, while (iter_colorop) { for_each_new_colorop_in_state(&state->base, colorop, new_colorop_state, i) { if (new_colorop_state->colorop == iter_colorop) { - blob = new_colorop_state->bypass ? NULL : new_colorop_state->data; intel_colorop = to_intel_colorop(colorop); - changed |= intel_plane_colorop_replace_blob(plane_state, + if (intel_colorop->id == INTEL_PLANE_CB_CSC_FF) { + fm_type = new_colorop_state->fixed_matrix_type; + + plane_state->hw.csc_ff_enable = + !new_colorop_state->bypass; + plane_state->hw.color_encoding = + fixedmatrix_colorop_to_encoding(fm_type); + plane_state->hw.color_range = + fixedmatrix_colorop_to_range(fm_type); + } else { + blob = new_colorop_state->bypass ? + NULL : new_colorop_state->data; + changed |= intel_plane_colorop_replace_blob(plane_state, intel_colorop, blob); + } } } iter_colorop = iter_colorop->next; diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 4aafd9ff3ac6..07d9ab5a3786 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -1246,9 +1246,11 @@ static u32 glk_plane_color_ctl_input_csc(const struct intel_plane_state *plane_s struct intel_display *display = to_intel_display(plane_state); const struct drm_framebuffer *fb = plane_state->hw.fb; struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); + bool color_pipeline = !!plane_state->uapi.color_pipeline; + bool needs_csc = color_pipeline ? plane_state->hw.csc_ff_enable : fb->format->is_yuv; u32 ctl = 0; - if (!fb->format->is_yuv) + if (!needs_csc) return 0; if (!icl_is_hdr_plane(display, plane->id)) { From 8249ceb6bb4c05825517d13eca28a5b572350946 Mon Sep 17 00:00:00 2001 From: Chaitanya Kumar Borah Date: Wed, 2 Sep 2026 13:24:13 +0530 Subject: [PATCH 22/98] drm/i915/color: Add support for 1D LUT in SDR planes Extend the SDR plane color pipeline to post-CSC 1D LUT block. v2: - In preparation of a simple pipeline [YUV Full/Limited -> RGB] -> [1D LUT] Drop pre-CSC LUT from the pipeline as it has no use in a YUV -> RGB pipeline. This makes the pipeline simple since the block lies between the YUV range correct block and Fixed function CSC. It can be added back when [RGB709 -> RGB2020] capability is added. Then it can be used for linearization. Signed-off-by: Chaitanya Kumar Borah Reviewed-by: Uma Shankar Link: https://patch.msgid.link/20260902075417.656673-6-chaitanya.kumar.borah@intel.com --- drivers/gpu/drm/i915/display/intel_color_pipeline.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/display/intel_color_pipeline.c b/drivers/gpu/drm/i915/display/intel_color_pipeline.c index efd4375c4331..53e55ce0a5a3 100644 --- a/drivers/gpu/drm/i915/display/intel_color_pipeline.c +++ b/drivers/gpu/drm/i915/display/intel_color_pipeline.c @@ -45,6 +45,7 @@ static const enum intel_color_block hdr_plane_pipeline[] = { static const enum intel_color_block sdr_plane_yuv_pipeline[] = { INTEL_PLANE_CB_CSC_FF, + INTEL_PLANE_CB_POST_CSC_LUT, }; static const u64 intel_plane_supported_csc_ff = From 2a8563b84c806ef4b2f919b09089e10a92da447c Mon Sep 17 00:00:00 2001 From: Pranay Samala Date: Wed, 2 Sep 2026 13:24:14 +0530 Subject: [PATCH 23/98] drm/i915/color: Extract HDR post-CSC LUT programming to helper function Move HDR plane post-CSC LUT programming to improve code organization. While at it, remove the segment 0 index register writes as it is not currently programmed. Signed-off-by: Pranay Samala Signed-off-by: Chaitanya Kumar Borah Reviewed-by: Uma Shankar Link: https://patch.msgid.link/20260902075417.656673-7-chaitanya.kumar.borah@intel.com --- drivers/gpu/drm/i915/display/intel_color.c | 35 ++++++++++++---------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 87ced9f6ff40..36c8688ed28e 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -3998,25 +3998,17 @@ xelpd_program_plane_pre_csc_lut(struct intel_dsb *dsb, } static void -xelpd_program_plane_post_csc_lut(struct intel_dsb *dsb, - const struct intel_plane_state *plane_state) +xelpd_load_hdr_post_csc_lut(struct intel_display *display, + struct intel_dsb *dsb, + enum pipe pipe, + enum plane_id plane, + const struct drm_color_lut32 *post_csc_lut) { - struct intel_display *display = to_intel_display(plane_state); - const struct drm_plane_state *state = &plane_state->uapi; - enum pipe pipe = to_intel_plane(state->plane)->pipe; - enum plane_id plane = to_intel_plane(state->plane)->id; - const struct drm_color_lut32 *post_csc_lut = plane_state->hw.gamma_lut->data; int i, lut_size = 32; u32 lut_val; - if (!icl_is_hdr_plane(display, plane)) - return; - intel_de_write_dsb(display, dsb, PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, 0), PLANE_PAL_PREC_AUTO_INCREMENT); - /* TODO: Add macro */ - intel_de_write_dsb(display, dsb, PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH(pipe, plane, 0), - PLANE_PAL_PREC_AUTO_INCREMENT); for (i = 0; i < lut_size + 3; i++) { if (post_csc_lut) { @@ -4036,8 +4028,21 @@ xelpd_program_plane_post_csc_lut(struct intel_dsb *dsb, } intel_de_write_dsb(display, dsb, PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, 0), 0); - intel_de_write_dsb(display, dsb, - PLANE_POST_CSC_GAMC_SEG0_INDEX_ENH(pipe, plane, 0), 0); +} + +static void +xelpd_program_plane_post_csc_lut(struct intel_dsb *dsb, + const struct intel_plane_state *plane_state) +{ + struct intel_display *display = to_intel_display(plane_state); + const struct drm_plane_state *state = &plane_state->uapi; + enum pipe pipe = to_intel_plane(state->plane)->pipe; + enum plane_id plane = to_intel_plane(state->plane)->id; + const struct drm_color_lut32 *post_csc_lut = plane_state->hw.gamma_lut ? + plane_state->hw.gamma_lut->data : NULL; + + if (icl_is_hdr_plane(display, plane)) + xelpd_load_hdr_post_csc_lut(display, dsb, pipe, plane, post_csc_lut); } static void From d547b3237f014d50bd1a4ae558c9865c0a6c1c3d Mon Sep 17 00:00:00 2001 From: Pranay Samala Date: Wed, 2 Sep 2026 13:24:15 +0530 Subject: [PATCH 24/98] drm/i915/color: Program Plane Post CSC registers for SDR planes Implement plane post-CSC LUT support for SDR planes. v2: - Restructure loop to match HDR function pattern Assisted-by: Claude:claude-opus-4.6 Signed-off-by: Pranay Samala Co-developed-by: Chaitanya Kumar Borah Signed-off-by: Chaitanya Kumar Borah Reviewed-by: Uma Shankar Link: https://patch.msgid.link/20260902075417.656673-8-chaitanya.kumar.borah@intel.com --- drivers/gpu/drm/i915/display/intel_color.c | 41 ++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index 36c8688ed28e..f1df0f9ba762 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -4030,6 +4030,45 @@ xelpd_load_hdr_post_csc_lut(struct intel_display *display, intel_de_write_dsb(display, dsb, PLANE_POST_CSC_GAMC_INDEX_ENH(pipe, plane, 0), 0); } +static void +xelpd_load_sdr_post_csc_lut(struct intel_display *display, + struct intel_dsb *dsb, + enum pipe pipe, + enum plane_id plane, + const struct drm_color_lut32 *post_csc_lut) +{ + int i, lut_size = 32; + u32 lut_val; + + /* + * First 3 planes are HDR, so reduce by 3 to get to the right + * SDR plane offset + */ + plane = plane - 3; + + intel_de_write_dsb(display, dsb, PLANE_POST_CSC_GAMC_INDEX(pipe, plane, 0), + PLANE_PAL_PREC_AUTO_INCREMENT); + + for (i = 0; i < lut_size + 3; i++) { + if (post_csc_lut) { + if (i < lut_size) + lut_val = drm_color_lut32_extract(post_csc_lut[i].green, 16); + /* else duplicate last lut_val */ + } else { + if (i < lut_size) + lut_val = (i * ((1 << 16) - 1)) / (lut_size - 1); + else + lut_val = 1 << 16; + } + + intel_de_write_dsb(display, dsb, + PLANE_POST_CSC_GAMC_DATA(pipe, plane, 0), + lut_val); + } + + intel_de_write_dsb(display, dsb, PLANE_POST_CSC_GAMC_INDEX(pipe, plane, 0), 0); +} + static void xelpd_program_plane_post_csc_lut(struct intel_dsb *dsb, const struct intel_plane_state *plane_state) @@ -4043,6 +4082,8 @@ xelpd_program_plane_post_csc_lut(struct intel_dsb *dsb, if (icl_is_hdr_plane(display, plane)) xelpd_load_hdr_post_csc_lut(display, dsb, pipe, plane, post_csc_lut); + else + xelpd_load_sdr_post_csc_lut(display, dsb, pipe, plane, post_csc_lut); } static void From 334a8c2290603205eaa56f20bfa40c395df6dce0 Mon Sep 17 00:00:00 2001 From: Chaitanya Kumar Borah Date: Wed, 2 Sep 2026 13:24:16 +0530 Subject: [PATCH 25/98] drm/i915/color: Add color pipeline support for SDR planes Now that everything is in place expose the SDR plane color pipeline to user-space. Signed-off-by: Chaitanya Kumar Borah Reviewed-by: Uma Shankar Link: https://patch.msgid.link/20260902075417.656673-9-chaitanya.kumar.borah@intel.com --- drivers/gpu/drm/i915/display/intel_color_pipeline.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color_pipeline.c b/drivers/gpu/drm/i915/display/intel_color_pipeline.c index 53e55ce0a5a3..38cfd6ed585d 100644 --- a/drivers/gpu/drm/i915/display/intel_color_pipeline.c +++ b/drivers/gpu/drm/i915/display/intel_color_pipeline.c @@ -177,17 +177,11 @@ int _intel_color_pipeline_plane_init(struct drm_plane *plane, struct drm_prop_en int intel_color_pipeline_plane_init(struct drm_plane *plane, enum pipe pipe) { - struct drm_device *dev = plane->dev; - struct intel_display *display = to_intel_display(dev); struct drm_prop_enum_list pipelines[MAX_COLOR_PIPELINES] = {}; int len = 0; int ret = 0; int i; - /* Currently expose pipeline only for HDR planes */ - if (!icl_is_hdr_plane(display, to_intel_plane(plane)->id)) - return 0; - /* Add pipeline consisting of transfer functions */ ret = _intel_color_pipeline_plane_init(plane, &pipelines[len], pipe); if (ret) From a4e6c6a761f6699a2a1a84c0fe491bdb71d6a2d9 Mon Sep 17 00:00:00 2001 From: Chaitanya Kumar Borah Date: Wed, 2 Sep 2026 13:24:17 +0530 Subject: [PATCH 26/98] drm/i915/color: Add YUV buffer support on HDR planes Add the INTEL_PLANE_CB_CSC_FF (fixed function CSC) color block as the first stage for the HDR planes. This enables YUV-to-RGB color space conversion on HDR planes via the color pipeline. Also in icl_program_input_csc(), account for the color pipeline programming, in addition to FB format. v2: - Increase MAX_COLOROP to 5 (Sashiko) Signed-off-by: Chaitanya Kumar Borah Reviewed-by: Uma Shankar Link: https://patch.msgid.link/20260902075417.656673-10-chaitanya.kumar.borah@intel.com --- drivers/gpu/drm/i915/display/intel_color_pipeline.c | 4 +++- drivers/gpu/drm/i915/display/skl_universal_plane.c | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color_pipeline.c b/drivers/gpu/drm/i915/display/intel_color_pipeline.c index 38cfd6ed585d..7fc31fe891a8 100644 --- a/drivers/gpu/drm/i915/display/intel_color_pipeline.c +++ b/drivers/gpu/drm/i915/display/intel_color_pipeline.c @@ -12,7 +12,7 @@ #include "skl_universal_plane.h" #define MAX_COLOR_PIPELINES 1 -#define MAX_COLOROP 4 +#define MAX_COLOROP 5 #define PLANE_DEGAMMA_SIZE 128 #define PLANE_GAMMA_SIZE 32 @@ -31,6 +31,7 @@ static const struct drm_colorop_funcs intel_colorop_funcs = { * the pipeline totally unusable. */ static const enum intel_color_block xe3plpd_primary_plane_pipeline[] = { + INTEL_PLANE_CB_CSC_FF, INTEL_PLANE_CB_PRE_CSC_LUT, INTEL_PLANE_CB_CSC, INTEL_PLANE_CB_3DLUT, @@ -38,6 +39,7 @@ static const enum intel_color_block xe3plpd_primary_plane_pipeline[] = { }; static const enum intel_color_block hdr_plane_pipeline[] = { + INTEL_PLANE_CB_CSC_FF, INTEL_PLANE_CB_PRE_CSC_LUT, INTEL_PLANE_CB_CSC, INTEL_PLANE_CB_POST_CSC_LUT, diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 07d9ab5a3786..2636eba2ba46 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -1622,7 +1622,8 @@ icl_plane_update_noarm(struct intel_dsb *dsb, intel_de_write_dsb(display, dsb, PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl); - if (fb->format->is_yuv && icl_is_hdr_plane(display, plane_id)) + if (icl_is_hdr_plane(display, plane_id) && + (fb->format->is_yuv || plane_state->hw.csc_ff_enable)) icl_program_input_csc(dsb, plane, plane_state); skl_write_plane_wm(dsb, plane, crtc_state); From 820b255537d98d888eb36b44b8edc78c6f7ff3ab Mon Sep 17 00:00:00 2001 From: Lalit Shankar Chowdhury Date: Thu, 10 Sep 2026 15:58:45 +0000 Subject: [PATCH 27/98] drm/i915/fb: replace kmalloc_array with kmalloc_objs Replace the remaining kmalloc_array instance with kmalloc_objs. Signed-off-by: Lalit Shankar Chowdhury Link: https://patch.msgid.link/20260910155846.79513-1-lalitshankarch@gmail.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 1c0859d5f829..c3e4c3f6d8cf 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -596,7 +596,7 @@ u64 *intel_fb_plane_get_modifiers(struct intel_display *display, count++; } - list = kmalloc_array(count, sizeof(*list), GFP_KERNEL); + list = kmalloc_objs(*list, count); if (drm_WARN_ON(display->drm, !list)) return NULL; From 550b703fdbb2a2022faa75b4b11ab135241afbd9 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Mon, 7 Sep 2026 09:15:55 +0530 Subject: [PATCH 28/98] drm/i915/quirks: Limit eDP rate to HBR2 on HP Pavilion Plus 14-ew1 The eDP panel on the HP Pavilion Plus Laptop 14-ew1xxx advertises HBR3 while leaving the TPS4 support bit clear. The output however flickers, once link is trained with HBR3. Until commit 8c9006283e4b ("Revert "drm/i915/dp: Reject HBR3 when sink doesn't support TPS4"") such sinks were capped at HBR2 by the TPS4 check which incidentally kept this panel stable. That check was reverted because other panels legitimately need HBR3 without advertising TPS4, and the per-machine QUIRK_EDP_LIMIT_RATE_HBR2 was introduced to handle the affected machines instead. Add the machine to the list of devices that need the QUIRK_EDP_LIMIT_RATE_HBR2. Fixes: 8c9006283e4b ("Revert "drm/i915/dp: Reject HBR3 when sink doesn't support TPS4"") Reported-by: Annoy Cc Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/work_items/16743 Cc: # v6.18+ Tested-by: Annoy Cc Signed-off-by: Ankit Nautiyal Reviewed-by: Nemesa Garg Link: https://patch.msgid.link/20260907034555.2753846-1-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_quirks.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_quirks.c b/drivers/gpu/drm/i915/display/intel_quirks.c index 33245f44c0d5..7d7db774d8c7 100644 --- a/drivers/gpu/drm/i915/display/intel_quirks.c +++ b/drivers/gpu/drm/i915/display/intel_quirks.c @@ -257,6 +257,9 @@ static struct intel_quirk intel_quirks[] = { /* Dell XPS 13 7390 2-in-1 */ { 0x8a52, 0x1028, 0x08b0, quirk_edp_limit_rate_hbr2 }, + /* HP Pavilion Plus Laptop 14-ew1xxx */ + { 0x7d55, 0x103c, 0x8c31, quirk_edp_limit_rate_hbr2 }, + /* Xiaomi Book Pro 14 2026 */ { 0xb081, 0x1d72, 0x2424, quirk_disable_psr2 }, }; From 270681fbffbba2b6ccf5b7e3c34b8b563b36167f Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 7 Sep 2026 20:44:12 +0300 Subject: [PATCH 29/98] drm/i915/dp_mst: Fix configuring FEC for a disconnected stream During an atomic commit after all the MST stream CRTC state is computed the driver ensures that the FEC is configured the same way (enabled or disabled) for all the streams on a given MST topology's link. drm_dp_mst_port_downstream_of_parent() used to determine if a stream is downstream of an MST port will return false if the whole topology is disconnected, since in that case it can't verify that the port/ parent_port passed to it is in the given MST topology. This is a problem during the above FEC configuration check, since intel_dp_mst_check_dsc_change()->get_pipes_downstream_of_mst_ports() will not return all the stream CRTCs/pipes for the topology as expected. Since passing parent_port==NULL to get_pipes_downstream_of_mst_port() is meant to return all the streams for the given topology (i.e. mst_mgr) skip checking if an MST port is downstream of a parent port in this case. This fixes a problem where the FEC configuration check explained above failed to ensure that all streams' FEC is configured the same way if the topology was disconnected, leading to a FEC state mismatch error. Cc: stable@vger.kernel.org # v6.10+ Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/work_items/16073 Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/work_items/16384 Reviewed-by: Luca Coelho Signed-off-by: Imre Deak Link: https://patch.msgid.link/20260907174413.741851-1-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 6a869d0f6ffc..20766b6c0bcf 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -856,7 +856,8 @@ static u8 get_pipes_downstream_of_mst_port(struct intel_atomic_state *state, if (&connector->mst.dp->mst.mgr != mst_mgr) continue; - if (connector->mst.port != parent_port && + if (parent_port && + connector->mst.port != parent_port && !drm_dp_mst_port_downstream_of_parent(mst_mgr, connector->mst.port, parent_port)) From ee00f8fbb2b202002ab90834e02e9ba372773a36 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 7 Sep 2026 20:44:13 +0300 Subject: [PATCH 30/98] drm/i915/dp_mst: Fix configuring TUs for a disconnected stream During an atomic commit after all the MST stream CRTC state is computed the driver ensures that the sum of TUs of all the streams on a given MST topology link is within limits (63 for 8b10 and 64 for 128b132b). For a disconnected stream the DRM MST core's BW verification doesn't ensure this, because the topology state it uses for this is destroyed as soon as the stream (i.e. MST connector/port) is disconnected. The driver should keep the link state valid even for such disconnected streams, as userspace may disable them one-by-one only in a deferred way. Ensure the link's sum of TUs stays within limits in this case by simply reusing the maximum link BPP limit from the stream's (i.e. CRTC's) old state. The disconnection can happen either via the whole topology getting disconnected or via only the given stream's port getting disconnected. Check for both of these conditions separately, as a connector gets unregistered after a link disconnect event only in a deferred way. Cc: stable@vger.kernel.org # v6.10+ Link: https://gitlab.freedesktop.org/drm/i915/kernel/-/work_items/16073 Link: https://gitlab.freedesktop.org/drm/i915/kernel/-/work_items/16384 Reviewed-by: Luca Coelho Signed-off-by: Imre Deak Link: https://patch.msgid.link/20260907174413.741851-2-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 21 ++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dp_mst.h | 2 ++ drivers/gpu/drm/i915/display/intel_link_bw.c | 3 ++- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 20766b6c0bcf..0c362784afe4 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -2172,6 +2172,27 @@ bool intel_dp_mst_crtc_needs_modeset(struct intel_atomic_state *state, return false; } +bool intel_dp_mst_stream_disconnected(struct intel_atomic_state *state, + const struct intel_crtc *crtc) +{ + struct intel_connector *connector; + + connector = get_connector_in_state_for_crtc(state, crtc); + if (!connector) + return false; + + if (!connector->mst.dp) + return false; + + if (!connector->mst.dp->mst.mgr.mst_state) + return true; + + if (drm_connector_is_unregistered(&connector->base)) + return true; + + return false; +} + /** * intel_dp_mst_prepare_probe - Prepare an MST link for topology probing * @intel_dp: DP port object diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.h b/drivers/gpu/drm/i915/display/intel_dp_mst.h index ab09b487c6bb..8ce89242c05c 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.h +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.h @@ -28,6 +28,8 @@ int intel_dp_mst_atomic_check_link(struct intel_atomic_state *state, struct intel_link_bw_limits *limits); bool intel_dp_mst_crtc_needs_modeset(struct intel_atomic_state *state, struct intel_crtc *crtc); +bool intel_dp_mst_stream_disconnected(struct intel_atomic_state *state, + const struct intel_crtc *crtc); void intel_dp_mst_prepare_probe(struct intel_dp *intel_dp); bool intel_dp_mst_verify_dpcd_state(struct intel_dp *intel_dp); diff --git a/drivers/gpu/drm/i915/display/intel_link_bw.c b/drivers/gpu/drm/i915/display/intel_link_bw.c index b47474a3e9fe..e71e76d6fd3e 100644 --- a/drivers/gpu/drm/i915/display/intel_link_bw.c +++ b/drivers/gpu/drm/i915/display/intel_link_bw.c @@ -64,7 +64,8 @@ void intel_link_bw_init_limits(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); int forced_bpp_x16 = get_forced_link_bpp_x16(state, crtc); - if (state->base.duplicated && crtc_state) { + if ((state->base.duplicated && crtc_state) || + intel_dp_mst_stream_disconnected(state, crtc)) { limits->max_bpp_x16[pipe] = crtc_state->max_link_bpp_x16; if (intel_dsc_enabled_on_link(crtc_state)) limits->link_dsc_pipes |= BIT(pipe); From 4ffdb772716e4279d63dfaaadf965da73e799aeb Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 15 Sep 2026 19:06:20 +0300 Subject: [PATCH 31/98] drm/i915/dp: use EXPORT_SYMBOL_IF_KUNIT() for kunit helpers Use EXPORT_SYMBOL_IF_KUNIT() instead of the regular EXPORT_SYMBOL() to export the symbols to the kunit namespace. Otherwise, the symbols get exported for all the kernel to see, and the corresponding MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING") in the tests is meaningless. Fixes: 2eb9982ff179 ("drm/i915/kunit: Export link training and caps funcs for testing") Cc: Imre Deak Reviewed-by: Imre Deak Link: https://patch.msgid.link/20260915160620.779372-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp_link_caps.c | 6 ++++-- drivers/gpu/drm/i915/display/intel_dp_link_training.c | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_caps.c b/drivers/gpu/drm/i915/display/intel_dp_link_caps.c index 98657aa4d3d5..abec3e2519ca 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_caps.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_caps.c @@ -3,6 +3,8 @@ * Copyright © 2026 Intel Corporation */ +#include + #include #include #include @@ -1302,14 +1304,14 @@ void intel_dp_link_caps_cleanup(struct intel_dp_link_caps *link_caps) const struct intel_dp_link_caps_test_ops i915_display_dp_link_caps_test_ops = { INTEL_DP_LINK_CAPS_TEST_OPS_INIT }; -EXPORT_SYMBOL(i915_display_dp_link_caps_test_ops); +EXPORT_SYMBOL_IF_KUNIT(i915_display_dp_link_caps_test_ops); #else const struct intel_dp_link_caps_test_ops intel_display_dp_link_caps_test_ops = { INTEL_DP_LINK_CAPS_TEST_OPS_INIT }; -EXPORT_SYMBOL(intel_display_dp_link_caps_test_ops); +EXPORT_SYMBOL_IF_KUNIT(intel_display_dp_link_caps_test_ops); #endif /* I915 */ diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index cb92cff90614..9a692f4fdfee 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -2825,14 +2825,14 @@ void intel_dp_link_training_cleanup(struct intel_dp_link_training *link_training const struct intel_dp_link_training_test_ops i915_display_dp_link_training_test_ops = { INTEL_DP_LINK_TRAINING_TEST_OPS_INIT }; -EXPORT_SYMBOL(i915_display_dp_link_training_test_ops); +EXPORT_SYMBOL_IF_KUNIT(i915_display_dp_link_training_test_ops); #else const struct intel_dp_link_training_test_ops intel_display_dp_link_training_test_ops = { INTEL_DP_LINK_TRAINING_TEST_OPS_INIT }; -EXPORT_SYMBOL(intel_display_dp_link_training_test_ops); +EXPORT_SYMBOL_IF_KUNIT(intel_display_dp_link_training_test_ops); #endif /* I915 */ From 41dae8ac5a3e1709ccba9dc5bac184826711c03f Mon Sep 17 00:00:00 2001 From: Vinod Govindapillai Date: Tue, 15 Sep 2026 12:25:13 +0300 Subject: [PATCH 32/98] drm/xe/pm: introduce PM PME support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce PME support for PME capable devices. Whether device is PME capable is assessed during PCI probe routine. And the whether PME is enabled for a specific context is assessed during the PM runtime suspend call if the device is PME capable. If the PME is enabled, HPDs can generate PME which in turn call the runtime resume call and do the wakeup routines. Till now the driver was relying on HPD polling to wakeup in case of any HPDs. HPD polling can be avoided in platforms with PME support and instead rely on this PCI PME for HPD induced wakeup. v2: access functions for xe.pme.enabled status and clear the pme. enabled in case of error in xe_pm_runtime_suspend() v3: use the local pme_enabled flag to clear the device wakeup incase of error v4: call the devm_device_init_wakeup() only if device is PME capable to avoid false wakeup capable reporting in platforms where PME is not supported. Squash the patch which handled the lockdep deadlock handling Bspec: 52979, 52980, 68857, 68867, 68970 Assisted-by: GitHub_Copilot:claude-opus-5 Signed-off-by: Vinod Govindapillai Reviewed-by: Jouni Högander Link: https://patch.msgid.link/20260915092518.639448-2-vinod.govindapillai@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/xe_device_types.h | 13 ++++++++ drivers/gpu/drm/xe/xe_pci.c | 22 +++++++++++++- drivers/gpu/drm/xe/xe_pm.c | 45 ++++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_pm.h | 2 ++ 4 files changed, 81 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 180d450a6deb..a489a8d73991 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -453,6 +453,19 @@ struct xe_device { struct mutex lock; } d3cold; + /** @pme: Encapsulate pme related stuff */ + struct { + /** @pme.capable: Indicates if device is PME capable */ + bool capable; + + /** @pme.enabled: + * + * Indicates if PME is enabled - depends on user controllable + * sysfs interface as well + */ + bool enabled; + } pme; + /** @pm_notifier: Our PM notifier to perform actions in response to various PM events. */ struct notifier_block pm_notifier; /** @pm_block: Completion to block validating tasks on suspend / hibernate prepare */ diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index 1e04e8ef2611..b134d90c01a1 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -1380,6 +1380,8 @@ static int xe_pci_runtime_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct xe_device *xe = pdev_to_xe_device(pdev); + unsigned int flags; + bool pme_enabled; int err; /* @@ -1391,9 +1393,25 @@ static int xe_pci_runtime_suspend(struct device *dev) xe_assert(xe, !IS_SRIOV_VF(xe)); xe_assert(xe, !pci_num_vf(pdev)); + flags = memalloc_noreclaim_save(); + pme_enabled = xe->pme.capable && !xe->d3cold.allowed && + pci_enable_wake(pdev, PCI_D3hot, true) == 0; + memalloc_noreclaim_restore(flags); + + xe_pm_update_pme_enabled(xe, pme_enabled); + err = xe_pm_runtime_suspend(xe); - if (err) + if (err) { + if (pme_enabled) { + flags = memalloc_noreclaim_save(); + pci_enable_wake(pdev, PCI_D3hot, false); + memalloc_noreclaim_restore(flags); + + xe_pm_update_pme_enabled(xe, false); + } + return err; + } pci_save_state(pdev); @@ -1422,6 +1440,8 @@ static int xe_pci_runtime_resume(struct device *dev) pci_restore_state(pdev); + xe_pm_update_pme_enabled(xe, false); + if (xe->d3cold.allowed) { err = pci_enable_device(pdev); if (err) diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c index f517bf453b54..e71bb90c9b80 100644 --- a/drivers/gpu/drm/xe/xe_pm.c +++ b/drivers/gpu/drm/xe/xe_pm.c @@ -78,6 +78,8 @@ * management (RPS). */ +#define HAS_PM_PME_SUPPORT(xe) (GRAPHICS_VERx100(xe) >= 3500) + #ifdef CONFIG_LOCKDEP static struct lockdep_map xe_pm_runtime_d3cold_map = { .name = "xe_rpm_d3cold_map" @@ -384,6 +386,14 @@ int xe_pm_init_early(struct xe_device *xe) } ALLOW_ERROR_INJECTION(xe_pm_init_early, ERRNO); /* See xe_pci_probe() */ +static bool xe_pm_pci_pme_capable(struct xe_device *xe) +{ + struct pci_dev *pdev = to_pci_dev(xe->drm.dev); + + return HAS_PM_PME_SUPPORT(xe) ? + pci_pme_capable(pdev, PCI_D3hot) : false; +} + /** * xe_pm_probe() - Initialize Xe Power Management * @xe: the &xe_device instance @@ -397,6 +407,16 @@ int xe_pm_probe(struct xe_device *xe) xe->d3cold.capable = xe_pm_pci_d3cold_capable(xe); xe_dbg(xe, "d3cold: capable=%s\n", str_yes_no(xe->d3cold.capable)); + xe->pme.capable = xe_pm_pci_pme_capable(xe); + xe_dbg(xe, "pme: capable=%s\n", str_yes_no(xe->pme.capable)); + + if (xe->pme.capable) { + int err = devm_device_init_wakeup(xe->drm.dev); + + if (err) + return err; + } + return 0; } @@ -650,6 +670,7 @@ int xe_pm_runtime_suspend(struct xe_device *xe) return 0; out_resume: + xe_pm_update_pme_enabled(xe, false); xe_display_pm_runtime_resume(xe); xe_pxp_pm_resume(xe->pxp); out: @@ -993,6 +1014,30 @@ int xe_pm_set_vram_threshold(struct xe_device *xe, u32 threshold) return 0; } +/** + * xe_pm_pme_enabled - get the current status of PME enabled + * @xe: xe device instance + * + * Returns: True if PME is enabled, false otherwise. + */ +bool xe_pm_pme_enabled(struct xe_device *xe) +{ + return xe->pme.enabled; +} + +/** + * xe_pm_update_pme_enabled - Update the PME enabled state + * @xe: xe device instance + * @status: New PME enabled status + * + * Called during runtime suspend / resume. Status is set to True if PME is + * enabled during runtime_suspend. Cleared on runtime_resume. + */ +void xe_pm_update_pme_enabled(struct xe_device *xe, bool status) +{ + xe->pme.enabled = status; +} + /** * xe_pm_d3cold_allowed_toggle - Check conditions to toggle d3cold.allowed * @xe: xe device instance diff --git a/drivers/gpu/drm/xe/xe_pm.h b/drivers/gpu/drm/xe/xe_pm.h index 6d5ab09cb769..037c73ea4342 100644 --- a/drivers/gpu/drm/xe/xe_pm.h +++ b/drivers/gpu/drm/xe/xe_pm.h @@ -33,6 +33,8 @@ bool xe_pm_runtime_resume_and_get(struct xe_device *xe); void xe_pm_assert_unbounded_bridge(struct xe_device *xe); int xe_pm_set_vram_threshold(struct xe_device *xe, u32 threshold); void xe_pm_d3cold_allowed_toggle(struct xe_device *xe); +bool xe_pm_pme_enabled(struct xe_device *xe); +void xe_pm_update_pme_enabled(struct xe_device *xe, bool status); bool xe_rpm_reclaim_safe(const struct xe_device *xe); struct task_struct *xe_pm_read_callback_task(struct xe_device *xe); int xe_pm_block_on_suspend(struct xe_device *xe); From 90e07834704f29e63ecfa598d2167ed9cbfb0a98 Mon Sep 17 00:00:00 2001 From: Vinod Govindapillai Date: Tue, 15 Sep 2026 12:25:14 +0300 Subject: [PATCH 33/98] drm/i915: add pme_enabled() to the parent interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PME capabiliy need to be assessed very early during runtime suspend routine to avoid resetting HPDs during IRQ resets. As display runtime pm routines are being executed in the independent intel display driver entry points, we need to have independent access to the pme status as well. Add a provision to query the optional pme_enabled to the parent interface so that it could be called independently based on xe/i915's pme_enabled() implementation. Assisted-by: GitHub_Copilot:claude-opus-5 Signed-off-by: Vinod Govindapillai Reviewed-by: Jouni Högander Link: https://patch.msgid.link/20260915092518.639448-3-vinod.govindapillai@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_display_rpm.c | 7 +++++++ drivers/gpu/drm/i915/display/intel_display_rpm.h | 1 + include/drm/intel/display_parent_interface.h | 1 + 3 files changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_rpm.c b/drivers/gpu/drm/i915/display/intel_display_rpm.c index 0a331f89b4db..9927119a0fd1 100644 --- a/drivers/gpu/drm/i915/display/intel_display_rpm.c +++ b/drivers/gpu/drm/i915/display/intel_display_rpm.c @@ -46,6 +46,13 @@ bool intel_display_rpm_suspended(struct intel_display *display) return display->parent->rpm->suspended(display->drm); } +bool intel_display_rpm_pme_enabled(struct intel_display *display) +{ + const struct intel_display_rpm_interface *rpm = display->parent->rpm; + + return rpm->pme_enabled && rpm->pme_enabled(display->drm); +} + void assert_display_rpm_held(struct intel_display *display) { display->parent->rpm->assert_held(display->drm); diff --git a/drivers/gpu/drm/i915/display/intel_display_rpm.h b/drivers/gpu/drm/i915/display/intel_display_rpm.h index 6ef48515f84b..5d9a1cdddfa7 100644 --- a/drivers/gpu/drm/i915/display/intel_display_rpm.h +++ b/drivers/gpu/drm/i915/display/intel_display_rpm.h @@ -21,6 +21,7 @@ void intel_display_rpm_put(struct intel_display *display, struct ref_tracker *wa /* Only for special cases. */ bool intel_display_rpm_suspended(struct intel_display *display); +bool intel_display_rpm_pme_enabled(struct intel_display *display); void assert_display_rpm_held(struct intel_display *display); void intel_display_rpm_assert_block(struct intel_display *display); diff --git a/include/drm/intel/display_parent_interface.h b/include/drm/intel/display_parent_interface.h index 5e44c022d1ae..f36134e89cb6 100644 --- a/include/drm/intel/display_parent_interface.h +++ b/include/drm/intel/display_parent_interface.h @@ -196,6 +196,7 @@ struct intel_display_rpm_interface { void (*put_unchecked)(const struct drm_device *drm); bool (*suspended)(const struct drm_device *drm); + bool (*pme_enabled)(const struct drm_device *drm); /* Optional */ void (*assert_held)(const struct drm_device *drm); void (*assert_block)(const struct drm_device *drm); void (*assert_unblock)(const struct drm_device *drm); From e468a2117f413bea664b096b21521c5faa9606ea Mon Sep 17 00:00:00 2001 From: Vinod Govindapillai Date: Tue, 15 Sep 2026 12:25:15 +0300 Subject: [PATCH 34/98] drm/i915/xe: plug the pme_enabed implementation for xe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plug the pme_enabled query for xe. It will return the current PME status for the device. For supported platforms, PME is enabled during runtime suspend calls if the device is PME is capable. v2: use the xe_pm_pme_enabled() Assisted-by: GitHub_Copilot:claude-opus-5 Signed-off-by: Vinod Govindapillai Reviewed-by: Jouni Högander Link: https://patch.msgid.link/20260915092518.639448-4-vinod.govindapillai@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/xe/display/xe_display_rpm.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/xe/display/xe_display_rpm.c b/drivers/gpu/drm/xe/display/xe_display_rpm.c index 548b503aa024..57bcfb41bdda 100644 --- a/drivers/gpu/drm/xe/display/xe_display_rpm.c +++ b/drivers/gpu/drm/xe/display/xe_display_rpm.c @@ -45,6 +45,11 @@ static bool xe_display_rpm_suspended(const struct drm_device *drm) return pm_runtime_suspended(xe->drm.dev); } +static bool xe_display_rpm_pme_enabled(const struct drm_device *drm) +{ + return xe_pm_pme_enabled(to_xe_device(drm)); +} + static void xe_display_rpm_assert_held(const struct drm_device *drm) { /* FIXME */ @@ -69,6 +74,7 @@ const struct intel_display_rpm_interface xe_display_rpm_interface = { .put_raw = xe_display_rpm_put, .put_unchecked = xe_display_rpm_put_unchecked, .suspended = xe_display_rpm_suspended, + .pme_enabled = xe_display_rpm_pme_enabled, .assert_held = xe_display_rpm_assert_held, .assert_block = xe_display_rpm_assert_block, .assert_unblock = xe_display_rpm_assert_unblock From 56aa1f0f9465f34542f7691a42b60614cbfac437 Mon Sep 17 00:00:00 2001 From: Vinod Govindapillai Date: Tue, 15 Sep 2026 12:25:16 +0300 Subject: [PATCH 35/98] drm/i915/irq: conditional HPD IRQ resets based on PME capability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a device supports generating PME from HPDs, resetting HPD IRQs will be counter productive as HPDs itself will be lost. During suspend routines, all the IRQs are reset. So if the device is capable of generating PME rom HPDs, keep the HPD related IRQs from reset based on the PME capability of the device on a target power state. PME capability will be assessed and updated separately. v2: change keep_hpd to reset_hpd v3: use intel_display_rpm_pme_enabled() directly (JaniN) v4: remove the unused include file from the previous revision Bspec: 52979, 52980, 68857, 68867, 68970 Assisted-by: GitHub_Copilot:claude-opus-5 Signed-off-by: Vinod Govindapillai Reviewed-by: Jouni Högander Link: https://patch.msgid.link/20260915092518.639448-5-vinod.govindapillai@intel.com Signed-off-by: Rodrigo Vivi --- .../gpu/drm/i915/display/intel_display_irq.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c index a59b75830bd1..8ce30112de97 100644 --- a/drivers/gpu/drm/i915/display/intel_display_irq.c +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c @@ -2217,8 +2217,10 @@ static void gen11_display_irq_reset(struct intel_display *display) enum pipe pipe; u32 trans_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C) | BIT(TRANSCODER_D); + bool reset_hpd = !intel_display_rpm_pme_enabled(display); - intel_de_write(display, GEN11_DISPLAY_INT_CTL, 0); + if (reset_hpd) + intel_de_write(display, GEN11_DISPLAY_INT_CTL, 0); if (DISPLAY_VER(display) >= 12) { enum transcoder trans; @@ -2250,13 +2252,15 @@ static void gen11_display_irq_reset(struct intel_display *display) irq_reset(display, GEN8_DE_PORT_IRQ_REGS); irq_reset(display, GEN8_DE_MISC_IRQ_REGS); - if (DISPLAY_VER(display) >= 14) - irq_reset(display, PICAINTERRUPT_IRQ_REGS); - else - irq_reset(display, GEN11_DE_HPD_IRQ_REGS); + if (reset_hpd) { + if (DISPLAY_VER(display) >= 14) + irq_reset(display, PICAINTERRUPT_IRQ_REGS); + else + irq_reset(display, GEN11_DE_HPD_IRQ_REGS); - if (INTEL_PCH_TYPE(display) >= PCH_ICP) - irq_reset(display, SDE_IRQ_REGS); + if (INTEL_PCH_TYPE(display) >= PCH_ICP) + irq_reset(display, SDE_IRQ_REGS); + } } void gen8_irq_power_well_post_enable(struct intel_display *display, From f6d6d0ba4e9f7d3c5e80b7fa98b903c213e00e69 Mon Sep 17 00:00:00 2001 From: Vinod Govindapillai Date: Tue, 15 Sep 2026 12:25:17 +0300 Subject: [PATCH 36/98] drm/i915/hotplug: avoid HPD polling if the device is PME capable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In supported devices, HPDs can generate PME and which in turn can invoke runtime resume calls for xe. No need to keep the HPD polling in such PME capable devices. v2: use intel_display_rpm_pme_enabled() directly (JaniN) Bspec: 52979, 52980, 68857, 68867, 68970 Assisted-by: GitHub_Copilot:claude-opus-5 Signed-off-by: Vinod Govindapillai Reviewed-by: Jouni Högander Link: https://patch.msgid.link/20260915092518.639448-6-vinod.govindapillai@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_hotplug.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c index 970aa95ee344..d095eb13dc06 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug.c @@ -867,6 +867,11 @@ void intel_hpd_poll_enable(struct intel_display *display) if (!HAS_DISPLAY(display) || !intel_display_device_enabled(display)) return; + if (intel_display_rpm_pme_enabled(display)) { + drm_dbg_kms(display->drm, "PME wake capable device, skipping HPD polling.\n"); + return; + } + WRITE_ONCE(display->hotplug.poll_enabled, true); /* From 908f1be9c34392d858c5159851421a3b9b954a17 Mon Sep 17 00:00:00 2001 From: Arun R Murthy Date: Tue, 15 Sep 2026 09:53:00 +0530 Subject: [PATCH 37/98] drm/i915/dp: On DPCD init wake the DPRx for eDP Its observed that on AUX_CH failure, even if the retry is increased to 1000, it does not succeed. Either the command might be wrong or sink in an unknown/sleep state can cause this. So try waking the sink device. Before reading the DPCD caps wake the sink for eDP. v2: Use poll_timeout_us (Jani N) Add the reason, why this change is required (Ville) v3: Wake sink only for eDP Remove the dpcd probe set to true/false in wake_sink (Imre) v4: make edp_wake_sinc() static and dpcd_readb -> dpcd_reab_byte (Suraj) v5: Drop poll_timeout_us. drm_dp_dpcd_read_byte() already retries the AUX transaction internally (up to ~16ms), so the outer 6ms poll could never iterate and only added a pre-read delay on the hot path; read DP_SET_POWER once instead. Wake the sink before reading the DPCD caps, otherwise a sleeping sink fails the caps read and returns early before the wake ever runs. (Suraj, Jani, Sashiko) v6: Mask and write DP_SET_POWER (Sashiko) Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/4391 Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/work_items/16654 Signed-off-by: Arun R Murthy Reviewed-by: Suraj Kandpal Signed-off-by: Suraj Kandpal Link: https://patch.msgid.link/20260915042300.2201757-1-arun.r.murthy@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 38 +++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 0cd5e6b5034c..c44d584cc07a 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4779,6 +4779,38 @@ intel_edp_set_sink_rates(struct intel_dp *intel_dp) intel_edp_set_data_override_rates(intel_dp); } +static void intel_edp_wake_sink(struct intel_dp *intel_dp) +{ + u8 value = 0; + int ret; + + /* + * Read the current sink power state. drm_dp_dpcd_read_byte() already + * retries the AUX transaction internally, so a single read suffices. + * First commercial eDP panels are Ver1.0 or 1.1, on which DPCD + * DP_SET_POWER is supported. + */ + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_SET_POWER, &value); + + /* + * If the AUX read failed the sink may be asleep and not responding, + * or it read back D3; in either case wake it up to D0. + * In case of AUX read failure which is usually a POR case, the + * remaining bits of register 0x600 is set to '0' on POR. So a bare + * write should be fine. + */ + if (ret < 0 || value == DP_SET_POWER_D3) { + value &= ~DP_SET_POWER_MASK; + value |= DP_SET_POWER_D0; + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_SET_POWER, + value); + /* After setting to D0 need a min of 1ms to wake (Spec DP2.1 sec 2.3.1.2) */ + fsleep(1000); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_SET_POWER, + value); + } +} + static bool intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector) { @@ -4789,6 +4821,12 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector /* this function is meant to be called only once */ drm_WARN_ON(display->drm, intel_dp->dpcd[DP_DPCD_REV] != 0); + /* + * Spec DP2.1 Section 3.5.2.16 page 966. + * Also if sink is asleep, this will wake the sink. + */ + intel_edp_wake_sink(intel_dp); + if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd) != 0) return false; From 552e0bb24d5e6bf4bee6dcaade3e1c1ca89a6f58 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 10 Sep 2026 22:42:33 +0300 Subject: [PATCH 38/98] drm/i915/display: stop using the configurable fence timeout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit i915 has the Kconfig option DRM_I915_FENCE_TIMEOUT, defaulting to 10 seconds. xe doesn't use it, instead defaulting to MAX_SCHEDULE_TIMEOUT. Unify the behaviour by switching to dma_fence_wait() which defaults to MAX_SCHEDULE_TIMEOUT. As dma_fence_wait() returns 0 when the fence was signaled, update the return value check. This should be possible now that commit 3aef9c94c02b ("drm/i915: Perform full wedge on display reset") has been merged, and we no longer rely on the timeout. v3: Try this again with full wedge v2: Use dma_fence_wait(), fix return value check (Maarten) Reviewed-by: Maarten Lankhorst Cc: Ville Syrjälä Link: https://patch.msgid.link/1880e49c9270049d5dfd944a1cbf712d664d02aa.1789069102.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.c | 6 ++---- .../gpu/drm/xe/compat-i915-headers/i915_config.h | 16 ---------------- 2 files changed, 2 insertions(+), 20 deletions(-) delete mode 100644 drivers/gpu/drm/xe/compat-i915-headers/i915_config.h diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 9151ea6c15ab..579b03034c46 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -50,7 +50,6 @@ #include "g4x_dp.h" #include "g4x_hdmi.h" #include "hsw_ips.h" -#include "i915_config.h" #include "i9xx_plane.h" #include "i9xx_plane_regs.h" #include "i9xx_wm.h" @@ -7298,9 +7297,8 @@ static void intel_atomic_commit_fence_wait(struct intel_atomic_state *intel_stat for_each_new_plane_in_state(&intel_state->base, plane, new_plane_state, i) { if (new_plane_state->fence) { - ret = dma_fence_wait_timeout(new_plane_state->fence, false, - i915_fence_timeout()); - if (ret <= 0) + ret = dma_fence_wait(new_plane_state->fence, false); + if (ret < 0) break; dma_fence_put(new_plane_state->fence); diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_config.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_config.h deleted file mode 100644 index d4522203e2dd..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/i915_config.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#ifndef __I915_CONFIG_H__ -#define __I915_CONFIG_H__ - -#include - -static inline unsigned long i915_fence_timeout(void) -{ - return MAX_SCHEDULE_TIMEOUT; -} - -#endif /* __I915_CONFIG_H__ */ From c2e1495aff758181d420100f0a42abbc779109c0 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 10 Sep 2026 22:42:34 +0300 Subject: [PATCH 39/98] drm/i915/display: use struct intel_atomic_state *state variable naming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The struct intel_atomic_state * pointer variables and parameters are named "state" everywhere. Follow suit in intel_atomic_commit_fence_wait(). Cc: Ville Syrjälä Cc: Maarten Lankhorst Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/988f1253004e68d565f3915cbd24182ca95dee49.1789069102.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 579b03034c46..1c2e50c6d98a 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7288,14 +7288,14 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) drm_WARN_ON(display->drm, update_pipes); } -static void intel_atomic_commit_fence_wait(struct intel_atomic_state *intel_state) +static void intel_atomic_commit_fence_wait(struct intel_atomic_state *state) { struct drm_plane *plane; struct drm_plane_state *new_plane_state; long ret; int i; - for_each_new_plane_in_state(&intel_state->base, plane, new_plane_state, i) { + for_each_new_plane_in_state(&state->base, plane, new_plane_state, i) { if (new_plane_state->fence) { ret = dma_fence_wait(new_plane_state->fence, false); if (ret < 0) From 855c59d537e4505e2c50062a8f0c39dd49897f38 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 10 Sep 2026 22:42:35 +0300 Subject: [PATCH 40/98] drm/i915/display: reduce indent in intel_atomic_commit_fence_wait() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Continue early in the loop for no fence in order to reduce indent. v2: Rebase Cc: Ville Syrjälä Cc: Maarten Lankhorst Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/8ee588437fb214a20c57d8c181f28c57b81cacaa.1789069102.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 1c2e50c6d98a..983e84bca1ee 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7296,14 +7296,15 @@ static void intel_atomic_commit_fence_wait(struct intel_atomic_state *state) int i; for_each_new_plane_in_state(&state->base, plane, new_plane_state, i) { - if (new_plane_state->fence) { - ret = dma_fence_wait(new_plane_state->fence, false); - if (ret < 0) - break; + if (!new_plane_state->fence) + continue; - dma_fence_put(new_plane_state->fence); - new_plane_state->fence = NULL; - } + ret = dma_fence_wait(new_plane_state->fence, false); + if (ret < 0) + break; + + dma_fence_put(new_plane_state->fence); + new_plane_state->fence = NULL; } } From e6e7a4b15efe0a3f43e52d27355d0383c0391fcd Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 10 Sep 2026 22:42:36 +0300 Subject: [PATCH 41/98] drm/i915/display: debug log about fence wait errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently there's no indication if fence wait failed. Debug log about it. v2: Rebase, no timeout anymore Cc: Ville Syrjälä Cc: Maarten Lankhorst Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/6b670a146bfcfd0cc2c7641cc8d72df96e356ef9.1789069102.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 983e84bca1ee..edaa29944d23 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7290,6 +7290,7 @@ static void skl_commit_modeset_enables(struct intel_atomic_state *state) static void intel_atomic_commit_fence_wait(struct intel_atomic_state *state) { + struct intel_display *display = to_intel_display(state); struct drm_plane *plane; struct drm_plane_state *new_plane_state; long ret; @@ -7300,8 +7301,11 @@ static void intel_atomic_commit_fence_wait(struct intel_atomic_state *state) continue; ret = dma_fence_wait(new_plane_state->fence, false); - if (ret < 0) + if (ret < 0) { + drm_dbg_kms(display->drm, "[PLANE:%d:%s] fence wait failed (%pe)\n", + plane->base.id, plane->name, ERR_PTR(ret)); break; + } dma_fence_put(new_plane_state->fence); new_plane_state->fence = NULL; From 24b09db25f4ca2ec801d6c7b28473687b7ee18ad Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Tue, 15 Sep 2026 22:16:42 +0530 Subject: [PATCH 42/98] drm/i915/dip: Add new file to handle Data Island Packet hardware Add new files intel_dip.c, intel_dip.h, and intel_dip_regs.h to handle low level hardware programming related to Data Island Packets. Currently only programming of the Transmission Line for HDMI 2.1 Extended Metadata Packet (EMP) and DP Adaptive-Sync Secondary Data Packet (SDP) is added (MMIO register EMP_AS_SDP_TL). This will serve as a common place for DIP related code, which is currently scattered across DP and HDMI files. A TODO has been added for extracting the remaining DIP helpers. Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/20260915164657.3429075-2-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/display/intel_dip.c | 39 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dip.h | 38 ++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dip_regs.h | 18 +++++++++ drivers/gpu/drm/i915/display/intel_vrr.c | 1 + drivers/gpu/drm/i915/display/intel_vrr_regs.h | 6 --- drivers/gpu/drm/xe/Makefile | 1 + 7 files changed, 98 insertions(+), 6 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_dip.c create mode 100644 drivers/gpu/drm/i915/display/intel_dip.h create mode 100644 drivers/gpu/drm/i915/display/intel_dip_regs.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index a83fa8be0aba..d4e7764621e1 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -349,6 +349,7 @@ i915-y += \ display/intel_cx0_phy.o \ display/intel_ddi.o \ display/intel_ddi_buf_trans.o \ + display/intel_dip.o \ display/intel_display_device.o \ display/intel_display_trace.o \ display/intel_dkl_phy.o \ diff --git a/drivers/gpu/drm/i915/display/intel_dip.c b/drivers/gpu/drm/i915/display/intel_dip.c new file mode 100644 index 000000000000..2e2bdb2b199c --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dip.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2026 Intel Corporation + * + */ + +#include "intel_de.h" +#include "intel_dip.h" +#include "intel_dip_regs.h" +#include "intel_display_types.h" + +u16 intel_dip_read_emp_as_sdp_tl(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + u32 val; + + if (!HAS_EMP_AS_SDP_TL(display)) + return 0; + + val = intel_de_read(display, EMP_AS_SDP_TL(display, cpu_transcoder)); + return REG_FIELD_GET(EMP_AS_SDP_DB_TL_MASK, val); +} + +void intel_dip_write_emp_as_sdp_tl(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + + if (!HAS_EMP_AS_SDP_TL(display)) + return; + /* + * Since currently we support VRR only for DP/eDP, so this is programmed + * only for Adaptive Sync SDP to Vsync start. + */ + intel_de_write(display, + EMP_AS_SDP_TL(display, cpu_transcoder), + EMP_AS_SDP_DB_TL(crtc_state->vrr.vsync_start)); +} diff --git a/drivers/gpu/drm/i915/display/intel_dip.h b/drivers/gpu/drm/i915/display/intel_dip.h new file mode 100644 index 000000000000..25bae4a04d6b --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dip.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef __INTEL_DIP_H__ +#define __INTEL_DIP_H__ + +#include "intel_display_device.h" + +/* + * Video DIP (Data Island Packet) helpers. + * + * This file contains helpers for programming video DIP related hardware. + * + * TODO: Currently, this is only used for programming EMP_AS_SDP_TL i.e. to + * program Transmission Line for HDMI 2.1 Extended Metadata Packet (EMP) and + * DP Adaptive Sync (AS) Secondary Data Packet (SDP). However, all low level + * DIP buffer read/write and related helpers should be extracted here later. + */ + +struct intel_crtc_state; + +/* + * EMP AS SDP TL: Extended Metadata Packet (EMP) Adaptive Sync (AS) + * Secondary Data Packet (SDP) Transmission Line (TL). + * + * Starting with BMG (display ver 14.01) and LNL+ (display ver 20+), + * the AS SDP transmission line is programmable via the EMP AS SDP TL + * register. + */ +#define HAS_EMP_AS_SDP_TL(__display) (DISPLAY_VERx100(__display) == 1401 || \ + DISPLAY_VER(__display) >= 20) + +u16 intel_dip_read_emp_as_sdp_tl(const struct intel_crtc_state *crtc_state); +void intel_dip_write_emp_as_sdp_tl(const struct intel_crtc_state *crtc_state); + +#endif /* __INTEL_DIP_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dip_regs.h b/drivers/gpu/drm/i915/display/intel_dip_regs.h new file mode 100644 index 000000000000..c4e1dab1ea46 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dip_regs.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2026 Intel Corporation + */ + +#ifndef __INTEL_DIP_REGS_H__ +#define __INTEL_DIP_REGS_H__ + +#include "intel_display_reg_defs.h" + +/* EMP (Extended Metadata Packet) AS (Adaptive Sync) SDP Transmission Line */ +#define _EMP_AS_SDP_TL_A 0x60204 +#define EMP_AS_SDP_TL(display, trans) _MMIO_TRANS2((display), (trans), _EMP_AS_SDP_TL_A) +#define EMP_AS_SDP_DB_TL_MASK REG_GENMASK(12, 0) +#define EMP_AS_SDP_DB_TL(db_transmit_line) REG_FIELD_PREP(EMP_AS_SDP_DB_TL_MASK, \ + (db_transmit_line)) + +#endif /* __INTEL_DIP_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index e36db1174440..fd8b6f829cfe 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -17,6 +17,7 @@ #include "intel_cmtg.h" #include "intel_crtc.h" #include "intel_de.h" +#include "intel_dip_regs.h" #include "intel_display_limits.h" #include "intel_display_regs.h" #include "intel_display_types.h" diff --git a/drivers/gpu/drm/i915/display/intel_vrr_regs.h b/drivers/gpu/drm/i915/display/intel_vrr_regs.h index 9d4d6573a149..ba8631cbc672 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr_regs.h +++ b/drivers/gpu/drm/i915/display/intel_vrr_regs.h @@ -174,12 +174,6 @@ #define VRR_VSYNC_START_MASK REG_GENMASK(12, 0) #define VRR_VSYNC_START(vsync_start) REG_FIELD_PREP(VRR_VSYNC_START_MASK, (vsync_start)) -/* Common register for HDMI EMP and DP AS SDP */ -#define _EMP_AS_SDP_TL_A 0x60204 -#define EMP_AS_SDP_TL(display, trans) _MMIO_TRANS2((display), (trans), _EMP_AS_SDP_TL_A) -#define EMP_AS_SDP_DB_TL_MASK REG_GENMASK(12, 0) -#define EMP_AS_SDP_DB_TL(db_transmit_line) REG_FIELD_PREP(EMP_AS_SDP_DB_TL_MASK, (db_transmit_line)) - #define _TRANS_CMRR_M_LO_A 0x604F0 #define TRANS_CMRR_M_LO(display, trans) _MMIO_TRANS2((display), (trans), _TRANS_CMRR_M_LO_A) diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index 67b8b5477639..ba4404896f2f 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -259,6 +259,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_ddi.o \ i915-display/intel_ddi_buf_trans.o \ i915-display/intel_de.o \ + i915-display/intel_dip.o \ i915-display/intel_display.o \ i915-display/intel_display_conversion.o \ i915-display/intel_display_device.o \ From 7310befb0593cf8953b893a3c45c0bc3766aaf30 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Tue, 15 Sep 2026 22:16:43 +0530 Subject: [PATCH 43/98] drm/i915/vrr: Use the helper to write EMP_AS_SDP_TL register Now that intel_dip_write_emp_as_sdp_tl() exists, use it instead of the open-coded EMP_AS_SDP_TL programming sequence in intel_vrr_set_transcoder_timings(). Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/20260915164657.3429075-3-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_vrr.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index fd8b6f829cfe..a516ba34e0d0 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -17,6 +17,7 @@ #include "intel_cmtg.h" #include "intel_crtc.h" #include "intel_de.h" +#include "intel_dip.h" #include "intel_dip_regs.h" #include "intel_display_limits.h" #include "intel_display_regs.h" @@ -711,17 +712,7 @@ void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state) VRR_VSYNC_END(crtc_state->vrr.vsync_end) | VRR_VSYNC_START(crtc_state->vrr.vsync_start)); - /* - * For BMG and LNL+ onwards the EMP_AS_SDP_TL is used for programming - * double buffering point and transmission line for VRR packets for - * HDMI2.1/DP/eDP/DP->HDMI2.1 PCON. - * Since currently we support VRR only for DP/eDP, so this is programmed - * to for Adaptive Sync SDP to Vsync start. - */ - if (DISPLAY_VERx100(display) == 1401 || DISPLAY_VER(display) >= 20) - intel_de_write(display, - EMP_AS_SDP_TL(display, cpu_transcoder), - EMP_AS_SDP_DB_TL(crtc_state->vrr.vsync_start)); + intel_dip_write_emp_as_sdp_tl(crtc_state); } void From c23ee65d20ff2afcf6108106a58ff0155e48e10e Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Tue, 15 Sep 2026 22:16:44 +0530 Subject: [PATCH 44/98] drm/i915/intel_dip: Add check for DP encoder At the moment, the common register for programming Transmission line for Extended Metadata Packet and Adaptive-Sync Secondary Data Packet (EMP_AS_SDP_TL) is only used to program Adaptive-Sync SDP (AS SDP). Since VRR and Video Timing Extended Metadat Packet (VTEMP) are not yet implemented for HDMI, add an explicit check to write the register only for DP encoders (that may use AS SDP) and reset the register for non-DP encoders. In subsequent changes, instead of directly writing the value, appropriate helpers will be called, that will supply the transmission line for these packets. Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/20260915164657.3429075-4-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_dip.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dip.c b/drivers/gpu/drm/i915/display/intel_dip.c index 2e2bdb2b199c..b28352a9e23f 100644 --- a/drivers/gpu/drm/i915/display/intel_dip.c +++ b/drivers/gpu/drm/i915/display/intel_dip.c @@ -26,14 +26,19 @@ void intel_dip_write_emp_as_sdp_tl(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + u32 transmission_line = 0; if (!HAS_EMP_AS_SDP_TL(display)) return; /* - * Since currently we support VRR only for DP/eDP, so this is programmed - * only for Adaptive Sync SDP to Vsync start. + * Since we currently support VRR only for DP/eDP, program the register + * for Adaptive Sync SDP using vsync start. For non-DP encoders, + * the register is reset to 0. */ + if (intel_crtc_has_dp_encoder(crtc_state)) + transmission_line = crtc_state->vrr.vsync_start; + intel_de_write(display, EMP_AS_SDP_TL(display, cpu_transcoder), - EMP_AS_SDP_DB_TL(crtc_state->vrr.vsync_start)); + EMP_AS_SDP_DB_TL(transmission_line)); } From 538f65410ee580e8ffaed4eb60a7b7de824442c7 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Tue, 15 Sep 2026 22:16:45 +0530 Subject: [PATCH 45/98] drm/i915/dip: Add helper to get AS SDP Transmission Line Introduce a DIP helper to compute the Adaptive Sync SDP transmission line and use it when programming the EMP_AS_SDP_TL register. Currently the AS SDP transmission line is programmed to the T1 position. This can be extended in the future to support programming the T2 position as well. While at it, improve the documentation: the AS SDP transmission line corresponds to the T1 position, which maps to the start of the VSYNC pulse. v2: - Move the helper into intel_dip.c and make it static, since intel_dip.c is its only caller. - Drop the now unused prototype from intel_dp.h. - Add the check HAS_EMP_AS_SDP_TL(). (Suraj) Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal (#v1) Link: https://patch.msgid.link/20260915164657.3429075-5-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_dip.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dip.c b/drivers/gpu/drm/i915/display/intel_dip.c index b28352a9e23f..0277b15e1c82 100644 --- a/drivers/gpu/drm/i915/display/intel_dip.c +++ b/drivers/gpu/drm/i915/display/intel_dip.c @@ -9,6 +9,23 @@ #include "intel_dip_regs.h" #include "intel_display_types.h" +static int intel_dip_get_as_sdp_transmission_line(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + + if (!HAS_EMP_AS_SDP_TL(display)) + return 0; + + /* + * EMP_AS_SDP_TL defines the T1 position as the default AS SDP + * Transmission Line, which corresponds to the start of the + * VSYNC pulse. + * + * Use the T1 position for now. + */ + return crtc_state->vrr.vsync_start; +} + u16 intel_dip_read_emp_as_sdp_tl(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); @@ -36,7 +53,7 @@ void intel_dip_write_emp_as_sdp_tl(const struct intel_crtc_state *crtc_state) * the register is reset to 0. */ if (intel_crtc_has_dp_encoder(crtc_state)) - transmission_line = crtc_state->vrr.vsync_start; + transmission_line = intel_dip_get_as_sdp_transmission_line(crtc_state); intel_de_write(display, EMP_AS_SDP_TL(display, cpu_transcoder), From 5aa79d2e99f6f9e2e94b77c74a9eabf2fad03030 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Tue, 15 Sep 2026 22:16:46 +0530 Subject: [PATCH 46/98] drm/i915/display: Add crtc state for DIP transmission lines The Adaptive Sync SDP is currently the only packet with a programmable transmission line. Make a structure struct intel_dip for Data Island Packets. Add a member to track Adaptive-Sync SDP transmission line. Include the new member in the pipe configuration comparison. This will pave the way for supporting more packets' programmable transmission lines, including the common base SDP transmission line introduced with Xe3p_lpd. v2: - Move struct intel_dip from intel_dip.h to intel_display_types.h (Jani) - Move PIPE_CONF_CHECK for emp_as_sdp_tl in !fastset block. (Sashiko) Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal (#v1) Link: https://patch.msgid.link/20260915164657.3429075-6-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 1 + drivers/gpu/drm/i915/display/intel_display_types.h | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index edaa29944d23..3a495da360c6 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5601,6 +5601,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_I(vrr.dc_balance.max_increase); PIPE_CONF_CHECK_I(vrr.dc_balance.max_decrease); PIPE_CONF_CHECK_I(vrr.dc_balance.vblank_target); + PIPE_CONF_CHECK_I(dip.emp_as_sdp_tl); } if (!fastset || intel_vrr_always_use_vrr_tg(display)) { diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index a5f18ac8a7d0..334179685ea2 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1007,6 +1007,14 @@ struct intel_casf { bool enable; }; +struct intel_dip { + /* + * DIP Transmission line, relative to the Vtotal. + * The programmed transmit line is (Vtotal - value) + */ + u16 emp_as_sdp_tl; +}; + struct intel_crtc_state { /* * uapi (drm) state. This is the software state shown to userspace. @@ -1315,6 +1323,8 @@ struct intel_crtc_state { struct drm_dp_as_sdp as_sdp; } infoframes; + struct intel_dip dip; + u8 eld[MAX_ELD_BYTES]; /* HDMI scrambling status */ From 50dae5bab56e25458a53b4869434789e29517034 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Tue, 15 Sep 2026 22:16:47 +0530 Subject: [PATCH 47/98] drm/i915/dip: Store and use AS SDP transmission line from crtc state The driver currently computes the Adaptive Sync SDP transmission line directly at programming time. Instead, compute and store the AS SDP transmission line in the crtc state and use it when programming the EMP_AS_SDP_TL register. We get the clear picture about the SDPs and guardband only in intel_dp_sdp_compute_config_late() therefore we must configure the AS SDP transmission line at this point when AS SDP is enabled in crtc_state. This prepares the ground for supporting programmable transmission lines for additional DP SDPs. While moving the helper into intel_dip.c, drop the intel_crtc_has_dp_encoder() check instead of relocating it. It was needed in the old VRR write path shared by other encoderes as well, but intel_dip_sdp_tl_compute_config_late() is only reached via DP, so HDMI never sets crtc_state->dip.emp_as_sdp_tl and it stays 0 by default. v2: - Move the helper into intel_dip.c and drop the intel_crtc_has_dp_encoder() check. - Drop the redundant checks. (Suraj) Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/20260915164657.3429075-7-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 2 ++ drivers/gpu/drm/i915/display/intel_dip.c | 20 +++++++++++--------- drivers/gpu/drm/i915/display/intel_dip.h | 3 +++ drivers/gpu/drm/i915/display/intel_dp.c | 3 +++ 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 9b3b526e5e55..dacb4b7588a0 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -49,6 +49,7 @@ #include "intel_ddi.h" #include "intel_ddi_buf_trans.h" #include "intel_de.h" +#include "intel_dip.h" #include "intel_display_power.h" #include "intel_display_regs.h" #include "intel_display_types.h" @@ -4235,6 +4236,7 @@ static void intel_ddi_get_config(struct intel_encoder *encoder, intel_read_dp_sdp(encoder, pipe_config, HDMI_PACKET_TYPE_GAMUT_METADATA); intel_read_dp_sdp(encoder, pipe_config, DP_SDP_VSC); intel_read_dp_sdp(encoder, pipe_config, DP_SDP_ADAPTIVE_SYNC); + intel_dip_sdp_transmission_line_get_config(pipe_config); intel_audio_codec_get_config(encoder, pipe_config); } diff --git a/drivers/gpu/drm/i915/display/intel_dip.c b/drivers/gpu/drm/i915/display/intel_dip.c index 0277b15e1c82..d1acc7eb5a39 100644 --- a/drivers/gpu/drm/i915/display/intel_dip.c +++ b/drivers/gpu/drm/i915/display/intel_dip.c @@ -43,19 +43,21 @@ void intel_dip_write_emp_as_sdp_tl(const struct intel_crtc_state *crtc_state) { struct intel_display *display = to_intel_display(crtc_state); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - u32 transmission_line = 0; if (!HAS_EMP_AS_SDP_TL(display)) return; - /* - * Since we currently support VRR only for DP/eDP, program the register - * for Adaptive Sync SDP using vsync start. For non-DP encoders, - * the register is reset to 0. - */ - if (intel_crtc_has_dp_encoder(crtc_state)) - transmission_line = intel_dip_get_as_sdp_transmission_line(crtc_state); intel_de_write(display, EMP_AS_SDP_TL(display, cpu_transcoder), - EMP_AS_SDP_DB_TL(transmission_line)); + EMP_AS_SDP_DB_TL(crtc_state->dip.emp_as_sdp_tl)); +} + +void intel_dip_sdp_tl_compute_config_late(struct intel_crtc_state *crtc_state) +{ + crtc_state->dip.emp_as_sdp_tl = intel_dip_get_as_sdp_transmission_line(crtc_state); +} + +void intel_dip_sdp_transmission_line_get_config(struct intel_crtc_state *crtc_state) +{ + crtc_state->dip.emp_as_sdp_tl = intel_dip_read_emp_as_sdp_tl(crtc_state); } diff --git a/drivers/gpu/drm/i915/display/intel_dip.h b/drivers/gpu/drm/i915/display/intel_dip.h index 25bae4a04d6b..20f9aeb85c39 100644 --- a/drivers/gpu/drm/i915/display/intel_dip.h +++ b/drivers/gpu/drm/i915/display/intel_dip.h @@ -35,4 +35,7 @@ struct intel_crtc_state; u16 intel_dip_read_emp_as_sdp_tl(const struct intel_crtc_state *crtc_state); void intel_dip_write_emp_as_sdp_tl(const struct intel_crtc_state *crtc_state); +void intel_dip_sdp_tl_compute_config_late(struct intel_crtc_state *crtc_state); +void intel_dip_sdp_transmission_line_get_config(struct intel_crtc_state *crtc_state); + #endif /* __INTEL_DIP_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index c44d584cc07a..f55ae30bebf8 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -61,6 +61,7 @@ #include "intel_cx0_phy.h" #include "intel_ddi.h" #include "intel_de.h" +#include "intel_dip.h" #include "intel_display_driver.h" #include "intel_display_jiffies.h" #include "intel_display_utils.h" @@ -7362,6 +7363,8 @@ int intel_dp_sdp_compute_config_late(struct intel_crtc_state *crtc_state) return -EINVAL; } + intel_dip_sdp_tl_compute_config_late(crtc_state); + return 0; } From ba4062e3d4d454bf422c8a748254e9a635fe716c Mon Sep 17 00:00:00 2001 From: Arun R Murthy Date: Tue, 15 Sep 2026 22:16:48 +0530 Subject: [PATCH 48/98] drm/i915/dip_regs: Add register definitions for common SDP Transmission Line Add registers definitions for common SDP transmission line CMN_SDP_TL and CMN_SDP_TL_STGR_CTL. v2: Move all registers to intel_dip_regs.h (Ankit) Bspec: 74384 Signed-off-by: Arun R Murthy Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/20260915164657.3429075-8-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_dip_regs.h | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dip_regs.h b/drivers/gpu/drm/i915/display/intel_dip_regs.h index c4e1dab1ea46..d7e40a613913 100644 --- a/drivers/gpu/drm/i915/display/intel_dip_regs.h +++ b/drivers/gpu/drm/i915/display/intel_dip_regs.h @@ -15,4 +15,24 @@ #define EMP_AS_SDP_DB_TL(db_transmit_line) REG_FIELD_PREP(EMP_AS_SDP_DB_TL_MASK, \ (db_transmit_line)) +/* COMMON SDP TRANSMISSION LINE */ +#define _CMN_SDP_TL_A 0x6020c +#define CMN_SDP_TL(display, trans) _MMIO_TRANS2(display, (trans), _CMN_SDP_TL_A) +#define TRANSMISSION_LINE_ENABLE REG_BIT(31) +#define BASE_TRANSMISSION_LINE_MASK REG_GENMASK(12, 0) +#define BASE_TRANSMISSION_LINE(x) REG_FIELD_PREP(BASE_TRANSMISSION_LINE_MASK, x) + +#define _CMN_SDP_TL_STGR_CTL_A 0x60214 +#define CMN_SDP_TL_STGR_CTL(display, trans) _MMIO_TRANS2(display, (trans), \ + _CMN_SDP_TL_STGR_CTL_A) +#define VSC_EXT_STAGGER_MASK REG_GENMASK(11, 8) +#define VSC_EXT_STAGGER(x) REG_FIELD_PREP(VSC_EXT_STAGGER_MASK, x) +#define VSC_EXT_STAGGER_DEFAULT 0x2 +#define PPS_STAGGER_MASK REG_GENMASK(7, 4) +#define PPS_STAGGER(x) REG_FIELD_PREP(PPS_STAGGER_MASK, x) +#define PPS_STAGGER_DEFAULT 0x1 +#define GMP_STAGGER_MASK REG_GENMASK(3, 0) +#define GMP_STAGGER(x) REG_FIELD_PREP(GMP_STAGGER_MASK, x) +#define GMP_STAGGER_DEFAULT 0x0 + #endif /* __INTEL_DIP_REGS_H__ */ From 45b6a7f1b82261400d53b8d9edba93f59c3a0b7a Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Tue, 15 Sep 2026 22:16:49 +0530 Subject: [PATCH 49/98] drm/i915/dip: Add HAS_COMMON_SDP_TL macro Add a helper macro to detect CMN SDP TL support on platforms with display version 35 and above. v2: Use prefix drm/i915/dip. (Suraj) Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/20260915164657.3429075-9-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_dip.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dip.h b/drivers/gpu/drm/i915/display/intel_dip.h index 20f9aeb85c39..8ff22eb5663b 100644 --- a/drivers/gpu/drm/i915/display/intel_dip.h +++ b/drivers/gpu/drm/i915/display/intel_dip.h @@ -32,6 +32,16 @@ struct intel_crtc_state; #define HAS_EMP_AS_SDP_TL(__display) (DISPLAY_VERx100(__display) == 1401 || \ DISPLAY_VER(__display) >= 20) +/* + * CMN SDP TL: Common Secondary Data Packet Transmission Line. + * + * Xe3p_lpd introduces new register CMN_SDP_TL to program a common SDP + * Transmission line that will be used by the Hardware to position the + * SDPs. Along with this, another new register CMN_SDP_TL_STGR_CTL is + * also added to stagger the different SDPs. + */ +#define HAS_COMMON_SDP_TL(__display) (DISPLAY_VER(__display) >= 35) + u16 intel_dip_read_emp_as_sdp_tl(const struct intel_crtc_state *crtc_state); void intel_dip_write_emp_as_sdp_tl(const struct intel_crtc_state *crtc_state); From 8aeed61a7d64c2e6bf1337848bc4960fadf9dfd1 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Tue, 15 Sep 2026 22:16:50 +0530 Subject: [PATCH 50/98] drm/i915/dip: Store SDP transmission lines in crtc_state Currently the driver only programs the transmission line for the Adaptive-Sync SDP, while the hardware controls the transmission lines for other SDPs. Starting with Xe3p_lpd, the hardware allows the driver to program transmission lines for additional DP SDPs. Prepare for this by adding fields to struct intel_crtc_state to store SDP transmission lines, and include them in pipe config comparison. The SDP transmission line fields track vrr.vsync_start/vtotal, which are allowed to change during a seamless LRR fastset. Guard their pipe config comparison under !fastset, same as vrr.vsync_start/vsync_end, so a fastset is not unnecessarily turned into a full modeset. Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/20260915164657.3429075-10-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 5 +++++ drivers/gpu/drm/i915/display/intel_display_types.h | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 3a495da360c6..e3e0d2f8faef 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5602,6 +5602,11 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_I(vrr.dc_balance.max_decrease); PIPE_CONF_CHECK_I(vrr.dc_balance.vblank_target); PIPE_CONF_CHECK_I(dip.emp_as_sdp_tl); + PIPE_CONF_CHECK_I(dip.gmp_sdp_tl); + PIPE_CONF_CHECK_I(dip.pps_sdp_tl); + PIPE_CONF_CHECK_I(dip.vsc_sdp_tl); + PIPE_CONF_CHECK_I(dip.vsc_ext_sdp_tl); + PIPE_CONF_CHECK_I(dip.cmn_sdp_tl); } if (!fastset || intel_vrr_always_use_vrr_tg(display)) { diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 334179685ea2..79f30660c2b6 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1013,6 +1013,12 @@ struct intel_dip { * The programmed transmit line is (Vtotal - value) */ u16 emp_as_sdp_tl; + u16 gmp_sdp_tl; + u16 pps_sdp_tl; + u16 vsc_sdp_tl; + u16 vsc_ext_sdp_tl; + /* Common SDP Base transmission line (Xe3p_lpd+) */ + u16 cmn_sdp_tl; }; struct intel_crtc_state { From 589a07df22d6e150571eea49b606fde120545846 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Tue, 15 Sep 2026 22:16:51 +0530 Subject: [PATCH 51/98] drm/i915/dp: Introduce helpers to enable/disable CMN SDP Transmission line Introduce helpers to program or disable CMN_SDP_TL and stagger registers using the state stored in crtc_state. v2: - Use HAS_COMMON_SDP_TL(display) instead of checking crtc_state->dip.cmn_sdp_tl, since 0 is a valid transmission line value. (Sashiko) Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/20260915164657.3429075-11-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_dip.c | 56 ++++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dip.h | 2 + 2 files changed, 58 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dip.c b/drivers/gpu/drm/i915/display/intel_dip.c index d1acc7eb5a39..f8e8577b2755 100644 --- a/drivers/gpu/drm/i915/display/intel_dip.c +++ b/drivers/gpu/drm/i915/display/intel_dip.c @@ -4,6 +4,8 @@ * */ +#include + #include "intel_de.h" #include "intel_dip.h" #include "intel_dip_regs.h" @@ -61,3 +63,57 @@ void intel_dip_sdp_transmission_line_get_config(struct intel_crtc_state *crtc_st { crtc_state->dip.emp_as_sdp_tl = intel_dip_read_emp_as_sdp_tl(crtc_state); } + +static int intel_dip_sdp_tl_to_stagger(const struct intel_crtc_state *crtc_state, + u16 sdp_transmission_line) +{ + return sdp_transmission_line - crtc_state->dip.cmn_sdp_tl; +} + +void intel_dip_cmn_sdp_transmission_line_enable(const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + int gmp_stagger; + int pps_stagger; + int vsc_ext_stagger; + + if (!HAS_COMMON_SDP_TL(display)) + return; + + gmp_stagger = intel_dip_sdp_tl_to_stagger(crtc_state, + crtc_state->dip.gmp_sdp_tl); + + pps_stagger = intel_dip_sdp_tl_to_stagger(crtc_state, + crtc_state->dip.pps_sdp_tl); + + vsc_ext_stagger = intel_dip_sdp_tl_to_stagger(crtc_state, + crtc_state->dip.vsc_ext_sdp_tl); + + if (drm_WARN_ON(display->drm, gmp_stagger < 0)) + return; + if (drm_WARN_ON(display->drm, pps_stagger < 0)) + return; + if (drm_WARN_ON(display->drm, vsc_ext_stagger < 0)) + return; + + intel_de_write(display, CMN_SDP_TL_STGR_CTL(display, cpu_transcoder), + GMP_STAGGER(gmp_stagger) | + PPS_STAGGER(pps_stagger) | + VSC_EXT_STAGGER(vsc_ext_stagger)); + + intel_de_write(display, CMN_SDP_TL(display, cpu_transcoder), + TRANSMISSION_LINE_ENABLE | + BASE_TRANSMISSION_LINE(crtc_state->dip.cmn_sdp_tl)); +} + +void intel_dip_cmn_sdp_transmission_line_disable(const struct intel_crtc_state *old_crtc_state) +{ + struct intel_display *display = to_intel_display(old_crtc_state); + enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; + + if (!HAS_COMMON_SDP_TL(display)) + return; + + intel_de_write(display, CMN_SDP_TL(display, cpu_transcoder), 0); +} diff --git a/drivers/gpu/drm/i915/display/intel_dip.h b/drivers/gpu/drm/i915/display/intel_dip.h index 8ff22eb5663b..7c64c84cb1be 100644 --- a/drivers/gpu/drm/i915/display/intel_dip.h +++ b/drivers/gpu/drm/i915/display/intel_dip.h @@ -47,5 +47,7 @@ void intel_dip_write_emp_as_sdp_tl(const struct intel_crtc_state *crtc_state); void intel_dip_sdp_tl_compute_config_late(struct intel_crtc_state *crtc_state); void intel_dip_sdp_transmission_line_get_config(struct intel_crtc_state *crtc_state); +void intel_dip_cmn_sdp_transmission_line_enable(const struct intel_crtc_state *crtc_state); +void intel_dip_cmn_sdp_transmission_line_disable(const struct intel_crtc_state *old_crtc_state); #endif /* __INTEL_DIP_H__ */ From bfa597238073d1859bef12bdd530d6e8258eec3b Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Tue, 15 Sep 2026 22:16:52 +0530 Subject: [PATCH 52/98] drm/i915/dip: Enable Common SDP Transmission line Enable programming of the common SDP transmission line on platforms that support it. Compute and program the common base transmission line and per-SDP stagger values from the crtc state during modeset, and disable the feature on pipe disable. Currently, the stagger values are set as per the default policy of the Hardware. This can be optimized later if we come up with a specific driver policy to sequence the SDPs better. v2: Add WARN if the Common Transmission Line is more than Guardband + SCL. (Suraj) Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/20260915164657.3429075-12-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 3 + drivers/gpu/drm/i915/display/intel_dip.c | 96 ++++++++++++++++++++++++ 2 files changed, 99 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index dacb4b7588a0..3cdb06e81130 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2737,6 +2737,8 @@ static void mtl_ddi_pre_enable_dp(struct intel_atomic_state *state, /* 6.o Configure and enable FEC if needed */ intel_ddi_enable_fec(encoder, crtc_state); + intel_dip_cmn_sdp_transmission_line_enable(crtc_state); + /* 7.a 128b/132b SST. */ if (!is_mst && intel_dp_is_uhbr(crtc_state)) { /* VCPID 1, start slot 0 for 128b/132b, tu slots */ @@ -3124,6 +3126,7 @@ static void intel_ddi_buf_disable(struct intel_encoder *encoder, DP_TP_CTL_ENABLE, 0); } + intel_dip_cmn_sdp_transmission_line_disable(crtc_state); intel_ddi_disable_fec(encoder, crtc_state); if (DISPLAY_VER(display) < 14) diff --git a/drivers/gpu/drm/i915/display/intel_dip.c b/drivers/gpu/drm/i915/display/intel_dip.c index f8e8577b2755..f447150ff7bc 100644 --- a/drivers/gpu/drm/i915/display/intel_dip.c +++ b/drivers/gpu/drm/i915/display/intel_dip.c @@ -10,6 +10,7 @@ #include "intel_dip.h" #include "intel_dip_regs.h" #include "intel_display_types.h" +#include "intel_hdmi.h" static int intel_dip_get_as_sdp_transmission_line(const struct intel_crtc_state *crtc_state) { @@ -54,14 +55,109 @@ void intel_dip_write_emp_as_sdp_tl(const struct intel_crtc_state *crtc_state) EMP_AS_SDP_DB_TL(crtc_state->dip.emp_as_sdp_tl)); } +static int intel_dip_sdp_stagger_to_tl(struct intel_crtc_state *crtc_state, + int stagger) +{ + return crtc_state->dip.cmn_sdp_tl + stagger; +} + +static +void intel_dip_cmn_sdp_tl_compute_config_late(struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + bool as_sdp; + + if (!HAS_COMMON_SDP_TL(display)) + return; + + as_sdp = crtc_state->infoframes.enable & + intel_hdmi_infoframe_enable(DP_SDP_ADAPTIVE_SYNC); + /* + * When AS SDP is enabled : + * - The common SDP Transmission Line matches the EMP SDP Transmission Line. + * + * When AS SDP is disabled: + * - Bspec mentions the positions as lines of delayed vblank. + * - Guardband = 1st line of delayed vblank + * - Common SDP Transmission line is set to 2nd line of delayed vblank. + */ + + if (as_sdp) + crtc_state->dip.cmn_sdp_tl = crtc_state->dip.emp_as_sdp_tl; + else + crtc_state->dip.cmn_sdp_tl = crtc_state->vrr.guardband - 1; + + if (drm_WARN_ON(display->drm, + crtc_state->dip.cmn_sdp_tl >= + crtc_state->vrr.guardband + crtc_state->set_context_latency)) + return; + + /* + * Currently we are programming the default stagger values, but these + * can be optimized if required, based on number of SDPs enabled. + * + * Default values of the Transmission lines for SDPs other than AS SDP: + * VSC : CMN SDP Transmission line + * GMP : CMN SDP Transmission line + * PPS : CMN SDP Transmission line + 1 + * VSC_EXT: CMN SDP Transmission line + 2 + */ + crtc_state->dip.vsc_sdp_tl = crtc_state->dip.cmn_sdp_tl; + crtc_state->dip.gmp_sdp_tl = + intel_dip_sdp_stagger_to_tl(crtc_state, GMP_STAGGER_DEFAULT); + crtc_state->dip.pps_sdp_tl = + intel_dip_sdp_stagger_to_tl(crtc_state, PPS_STAGGER_DEFAULT); + crtc_state->dip.vsc_ext_sdp_tl = + intel_dip_sdp_stagger_to_tl(crtc_state, VSC_EXT_STAGGER_DEFAULT); +} + void intel_dip_sdp_tl_compute_config_late(struct intel_crtc_state *crtc_state) { crtc_state->dip.emp_as_sdp_tl = intel_dip_get_as_sdp_transmission_line(crtc_state); + + intel_dip_cmn_sdp_tl_compute_config_late(crtc_state); +} + +static +void intel_dip_cmn_sdp_transmission_line_get_config(struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(crtc_state); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + u16 vsc_ext_stagger, pps_stagger, gmp_stagger; + u32 val; + + if (!HAS_COMMON_SDP_TL(display)) + return; + + val = intel_de_read(display, CMN_SDP_TL(display, cpu_transcoder)); + + if (!(val & TRANSMISSION_LINE_ENABLE)) + return; + + crtc_state->dip.cmn_sdp_tl = REG_FIELD_GET(BASE_TRANSMISSION_LINE_MASK, val); + + /* SDP VSC uses same transmission line as CMN base transmission line */ + crtc_state->dip.vsc_sdp_tl = crtc_state->dip.cmn_sdp_tl; + + val = intel_de_read(display, CMN_SDP_TL_STGR_CTL(display, cpu_transcoder)); + + vsc_ext_stagger = REG_FIELD_GET(VSC_EXT_STAGGER_MASK, val); + pps_stagger = REG_FIELD_GET(PPS_STAGGER_MASK, val); + gmp_stagger = REG_FIELD_GET(GMP_STAGGER_MASK, val); + + crtc_state->dip.vsc_ext_sdp_tl = + intel_dip_sdp_stagger_to_tl(crtc_state, vsc_ext_stagger); + crtc_state->dip.pps_sdp_tl = + intel_dip_sdp_stagger_to_tl(crtc_state, pps_stagger); + crtc_state->dip.gmp_sdp_tl = + intel_dip_sdp_stagger_to_tl(crtc_state, gmp_stagger); } void intel_dip_sdp_transmission_line_get_config(struct intel_crtc_state *crtc_state) { crtc_state->dip.emp_as_sdp_tl = intel_dip_read_emp_as_sdp_tl(crtc_state); + + intel_dip_cmn_sdp_transmission_line_get_config(crtc_state); } static int intel_dip_sdp_tl_to_stagger(const struct intel_crtc_state *crtc_state, From d6795b64b172b24622d33a3e0c7c1c7d15870fd2 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Tue, 15 Sep 2026 22:16:53 +0530 Subject: [PATCH 53/98] drm/i915/dp: Account VSC SDP in min guardband The transmission line for VSC SDP is the same as AS SDP (EMP_AS_SDP_TL) when AS SDP is enabled. Otherwise, it uses the second line of delayed vblank. For VSC without AS SDP, this requires 2 lines plus 1 setup line, so the VRR guardband must be at least 3 lines. When both AS SDP and VSC SDP are enabled, the guardband requirement is already accounted for during optimized guardband calculation and the final guardband validation in compute_config_late(). However, when VSC SDP is enabled without AS SDP, the VSC SDP requirement is not checked explicitly. Even in the unlikely case where the optimized guardband is clamped to vblank length, it cannot fall below 5 lines since such modes are already pruned. Still, for completeness, account for VSC SDP and ensure a minimum guardband of 3 lines. Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/20260915164657.3429075-13-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index f55ae30bebf8..27f03f36eabb 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -7397,6 +7397,8 @@ int intel_dp_get_lines_for_sdp(const struct intel_crtc_state *crtc_state, u32 ty return 8; case DP_SDP_PPS: return 7; + case DP_SDP_VSC: + return 3; case DP_SDP_ADAPTIVE_SYNC: return crtc_state->vrr.vsync_start + 1; default: @@ -7428,6 +7430,11 @@ int intel_dp_sdp_min_guardband(const struct intel_crtc_state *crtc_state, sdp_guardband = max(sdp_guardband, intel_dp_get_lines_for_sdp(crtc_state, DP_SDP_ADAPTIVE_SYNC)); + if (crtc_state->infoframes.enable & + intel_hdmi_infoframe_enable(DP_SDP_VSC)) + sdp_guardband = max(sdp_guardband, + intel_dp_get_lines_for_sdp(crtc_state, DP_SDP_VSC)); + return sdp_guardband; } From 571631ac5b30c2156087505be915de67182b3753 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Tue, 15 Sep 2026 22:16:54 +0530 Subject: [PATCH 54/98] drm/i915/dp: Adjust SDP guardband requirement for CMN_SDP_TL Once CMN_SDP_TL is enabled, GMP/PPS/VSC/VSC_EXT/AS SDPs are no longer positioned relative to the guardband: they are anchored via CMN_SDP_TL/CMN_SDP_TL_STGR_CTL instead. As per Bspec 68921, SDP Setup is 0 in this mode, so the old per-packet guardband sizing (based on GMP/PPS/AS-SDP being enabled) no longer applies for GMP/PPS/VSC/VSC_EXT. Since we are using the default stagger values for now, size the guardband such that the max default transmission line can be supported, similar to when CMN SDP TL is not set: base : 2nd line of delayed vblank GMP : 2 + GMP_STAGGER VSC_EXT: 2 + VSC_EXT_STAGGER VSC : 2 PPS : 2 + PPS_STAGGER SDP Setup = 1 + MAX(GMP, VSC_EXT, VSC, PPS setup lines) Add intel_dp_get_lines_for_cmn_sdp_tl() and route it via the existing intel_dp_get_lines_for_sdp(). The AS SDP check in intel_dp_sdp_min_guardband() still adds vrr.vsync_start + 1 to the guardband, since AS SDP positioning is unaffected by CMN_SDP_TL. v2: Add VSC min SDP guardband. (Sashiko) Bspec: 68921 Assisted-by: Copilot:claude-sonnet-4.5 Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/20260915164657.3429075-14-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 52 ++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 27f03f36eabb..50ed615cf0f6 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -62,6 +62,7 @@ #include "intel_ddi.h" #include "intel_de.h" #include "intel_dip.h" +#include "intel_dip_regs.h" #include "intel_display_driver.h" #include "intel_display_jiffies.h" #include "intel_display_utils.h" @@ -7386,9 +7387,58 @@ int intel_dp_compute_config_late(struct intel_encoder *encoder, return 0; } +static +int intel_dp_get_lines_for_cmn_sdp_tl(u32 type) +{ + u32 stagger_val; + + /* + * Since we are using default stagger values similar to the case + * where CMN SDP TL is not set, the different SDP transmission + * lines are: + * base : 2nd line of delayed vblank: + * GMP : 2 + GMP_STAGGER + * VSC_EXT: 2 + VSC_EXT_STAGGER + * VSC : 2 + * PPS : 2 + PPS_STAGGER + * + * SDP Setup = 1 + MAX(GMP, VSC_EXT, VSC, PPS setup lines) + * + * For EMP_AS_SDP_TL guardband should be more than vrr.vsync_start. + */ + + switch (type) { + case DP_SDP_VSC_EXT_VESA: + case DP_SDP_VSC_EXT_CEA: + stagger_val = VSC_EXT_STAGGER_DEFAULT; + break; + case HDMI_PACKET_TYPE_GAMUT_METADATA: + stagger_val = GMP_STAGGER_DEFAULT; + break; + case DP_SDP_PPS: + stagger_val = PPS_STAGGER_DEFAULT; + break; + case DP_SDP_VSC: + stagger_val = 0; + break; + default: + return 0; + } + + return 1 + 2 + stagger_val; +} + static int intel_dp_get_lines_for_sdp(const struct intel_crtc_state *crtc_state, u32 type) { + struct intel_display *display = to_intel_display(crtc_state); + + if (type == DP_SDP_ADAPTIVE_SYNC) + return crtc_state->vrr.vsync_start + 1; + + if (HAS_COMMON_SDP_TL(display)) + return intel_dp_get_lines_for_cmn_sdp_tl(type); + switch (type) { case DP_SDP_VSC_EXT_VESA: case DP_SDP_VSC_EXT_CEA: @@ -7399,8 +7449,6 @@ int intel_dp_get_lines_for_sdp(const struct intel_crtc_state *crtc_state, u32 ty return 7; case DP_SDP_VSC: return 3; - case DP_SDP_ADAPTIVE_SYNC: - return crtc_state->vrr.vsync_start + 1; default: break; } From b452f1fe719c47e06fef219757c50be3e71a20c6 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Tue, 15 Sep 2026 22:16:55 +0530 Subject: [PATCH 55/98] drm/i915/display: Dump DIP Transmission lines Add DIP transmission lines to the CRTC state dump. Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/20260915164657.3429075-15-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_crtc_state_dump.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c index ad4f362e0c09..92675a88b969 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c +++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c @@ -251,6 +251,15 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config, str_enabled_disabled(pipe_config->has_panel_replay), str_enabled_disabled(pipe_config->enable_psr2_sel_fetch)); drm_printf(&p, "minimum hblank: %d\n", pipe_config->min_hblank); + + drm_printf(&p, "DIP Transmission Lines: EMP/AS SDP: %u\n", + pipe_config->dip.emp_as_sdp_tl); + drm_printf(&p, "DIP Transmission Lines: Common Base SDP: %u, GMP SDP: %u, PPS SDP: %u, VSC SDP: %u, VSC_EXT SDP: %u\n", + pipe_config->dip.cmn_sdp_tl, + pipe_config->dip.gmp_sdp_tl, + pipe_config->dip.pps_sdp_tl, + pipe_config->dip.vsc_sdp_tl, + pipe_config->dip.vsc_ext_sdp_tl); } drm_printf(&p, "audio: %i, infoframes: %i, infoframes enabled: 0x%x\n", From 2827c44f148c7540f2982233364cde198b76660f Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Mon, 21 Sep 2026 07:50:17 +0530 Subject: [PATCH 56/98] drm/i915/xe3plpd: Map AUX power domains to DC_off From Xe2Lpd we removed the step to disable DC5/6 because as per Bspec for SNPS PHY Aux will be always up. But from Xe3p LT PHY was introduced which powers down the PHY. Which means we need to make sure "Disable DC5/6" of AUX Programming sequence is honored. Add the AUX power domains to the DC_off power well on Xe3p_LPD+, so that DC5/6 stays disabled for as long as an AUX power domain is held. Bspec: 68851, 68967 Suggested-by: Imre Deak Co-developed-by: Ramanaidu Naladala Signed-off-by: Ramanaidu Naladala Signed-off-by: Suraj Kandpal Reviewed-by: Arun R Murthy Link: https://patch.msgid.link/20260921022016.1525322-1-suraj.kandpal@intel.com --- .../i915/display/intel_display_power_map.c | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power_map.c b/drivers/gpu/drm/i915/display/intel_display_power_map.c index 3400080d78d2..e18eb49983fe 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_map.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_map.c @@ -1759,6 +1759,44 @@ static const struct i915_power_well_desc_list wcl_power_wells[] = { I915_PW_DESCRIPTORS(wcl_power_wells_aux), }; +I915_DECL_PW_DOMAINS(xe3plpd_pwdoms_dc_off, + POWER_DOMAIN_DC_OFF, + XE3LPD_PW_2_POWER_DOMAINS, + XE3LPD_PW_C_POWER_DOMAINS, + XE3LPD_PW_D_POWER_DOMAINS, + POWER_DOMAIN_AUDIO_MMIO, + POWER_DOMAIN_AUDIO_PLAYBACK, + POWER_DOMAIN_AUX_A, + POWER_DOMAIN_AUX_B, + POWER_DOMAIN_AUX_USBC1, + POWER_DOMAIN_AUX_USBC2, + POWER_DOMAIN_AUX_USBC3, + POWER_DOMAIN_AUX_USBC4, + POWER_DOMAIN_AUX_TBT1, + POWER_DOMAIN_AUX_TBT2, + POWER_DOMAIN_AUX_TBT3, + POWER_DOMAIN_AUX_TBT4, + POWER_DOMAIN_INIT); + +static const struct i915_power_well_desc xe3plpd_power_wells_dcoff[] = { + { + .instances = &I915_PW_INSTANCES( + I915_PW("DC_off", &xe3plpd_pwdoms_dc_off, + .id = SKL_DISP_DC_OFF), + ), + .ops = &gen9_dc_off_power_well_ops, + }, +}; + +static const struct i915_power_well_desc_list xe3plpd_power_wells[] = { + I915_PW_DESCRIPTORS(i9xx_power_wells_always_on), + I915_PW_DESCRIPTORS(icl_power_wells_pw_1), + I915_PW_DESCRIPTORS(xe3plpd_power_wells_dcoff), + I915_PW_DESCRIPTORS(xe3lpd_power_wells_main), + I915_PW_DESCRIPTORS(xe2lpd_power_wells_pica), + I915_PW_DESCRIPTORS(xelpdp_power_wells_aux), +}; + static void init_power_well_domains(const struct i915_power_well_instance *inst, struct i915_power_well *power_well) { @@ -1865,7 +1903,9 @@ int intel_display_power_map_init(struct i915_power_domains *power_domains) return 0; } - if (DISPLAY_VERx100(display) == 3002) + if (DISPLAY_VER(display) >= 35) + return set_power_wells(power_domains, xe3plpd_power_wells); + else if (DISPLAY_VERx100(display) == 3002) return set_power_wells(power_domains, wcl_power_wells); else if (DISPLAY_VER(display) >= 30) return set_power_wells(power_domains, xe3lpd_power_wells); From 3d79ea5703c580fa38b4418c5a4fe8cbe9418b53 Mon Sep 17 00:00:00 2001 From: Lalit Shankar Chowdhury Date: Fri, 18 Sep 2026 04:23:18 +0000 Subject: [PATCH 57/98] drm/i915: use string choice helpers Prefer the str_high_low() and str_read_write() helper functions over ternary operators with hardcoded strings. No functional changes. Signed-off-by: Lalit Shankar Chowdhury Reviewed-by: Jani Nikula Link: https://patch.msgid.link/20260918042325.17700-1-lalitshankarch@gmail.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_cx0_phy.c | 5 +++-- drivers/gpu/drm/i915/gvt/aperture_gm.c | 4 +++- drivers/gpu/drm/i915/vlv_iosf_sb.c | 6 ++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c index dbebd7210848..b83f0afaa9b5 100644 --- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c +++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c @@ -5,6 +5,7 @@ #include #include +#include #include @@ -189,7 +190,7 @@ int intel_cx0_wait_for_ack(struct intel_encoder *encoder, drm_dbg_kms(display->drm, "PHY %c Error occurred during %s command. Status: 0x%x\n", phy_name(phy), - command == XELPDP_PORT_P2M_COMMAND_READ_ACK ? "read" : "write", *val); + str_read_write(command == XELPDP_PORT_P2M_COMMAND_READ_ACK), *val); intel_cx0_bus_reset(encoder, lane); return -EINVAL; } @@ -198,7 +199,7 @@ int intel_cx0_wait_for_ack(struct intel_encoder *encoder, drm_dbg_kms(display->drm, "PHY %c Not a %s response. MSGBUS Status: 0x%x.\n", phy_name(phy), - command == XELPDP_PORT_P2M_COMMAND_READ_ACK ? "read" : "write", *val); + str_read_write(command == XELPDP_PORT_P2M_COMMAND_READ_ACK), *val); intel_cx0_bus_reset(encoder, lane); return -EINVAL; } diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c b/drivers/gpu/drm/i915/gvt/aperture_gm.c index 253b41789be9..794fb50e48dd 100644 --- a/drivers/gpu/drm/i915/gvt/aperture_gm.c +++ b/drivers/gpu/drm/i915/gvt/aperture_gm.c @@ -34,6 +34,8 @@ * */ +#include + #include #include "gt/intel_ggtt_fencing.h" @@ -76,7 +78,7 @@ static int alloc_gm(struct intel_vgpu *vgpu, bool high_gm) mutex_unlock(>->ggtt->vm.mutex); if (ret) gvt_err("fail to alloc %s gm space from host\n", - high_gm ? "high" : "low"); + str_high_low(high_gm)); return ret; } diff --git a/drivers/gpu/drm/i915/vlv_iosf_sb.c b/drivers/gpu/drm/i915/vlv_iosf_sb.c index 1f0332b4ad0d..fede1735bc08 100644 --- a/drivers/gpu/drm/i915/vlv_iosf_sb.c +++ b/drivers/gpu/drm/i915/vlv_iosf_sb.c @@ -3,6 +3,8 @@ * Copyright © 2013-2021 Intel Corporation */ +#include + #include #include @@ -101,7 +103,7 @@ static int vlv_sideband_rw(struct drm_i915_private *i915, VLV_IOSF_DOORBELL_REQ, IOSF_SB_BUSY, 0, 5)) { drm_dbg(&i915->drm, "IOSF sideband idle wait (%s) timed out\n", - is_read ? "read" : "write"); + str_read_write(is_read)); return -EAGAIN; } @@ -125,7 +127,7 @@ static int vlv_sideband_rw(struct drm_i915_private *i915, err = 0; } else { drm_dbg(&i915->drm, "IOSF sideband finish wait (%s) timed out\n", - is_read ? "read" : "write"); + str_read_write(is_read)); err = -ETIMEDOUT; } From fd2e337ba66f6de39abad98a656fa6e5ff0c1609 Mon Sep 17 00:00:00 2001 From: Juasheem Sultan Date: Tue, 2 Jun 2026 13:54:02 -0700 Subject: [PATCH 58/98] drm/i915/dp: Handle VSC SDP revision 7 in unpack VSC SDP revision 7 (Panel Replay + Pixel Encoding/Colorimetry Format) unpacking is missing in intel_dp_vsc_sdp_unpack(). This causes pipe state mismatches during state readout because the VSC SDP state is not properly recovered when Panel Replay is active with colorimetry. Add the missing case for revision 7 to intel_dp_vsc_sdp_unpack() so that the state is correctly recovered. v2: Rebase onto latest upstream v3: Fix git commit description Cc: Jani Nikula Cc: Chaitanya Borah Cc: Gil Dekel Signed-off-by: Juasheem Sultan Reviewed-by: Chaitanya Kumar Borah Signed-off-by: Ankit Nautiyal Link: https://patch.msgid.link/20260602205422.1792007-1-jdsultan@google.com --- drivers/gpu/drm/i915/display/intel_dp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 50ed615cf0f6..2480b8ce3bec 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5475,11 +5475,15 @@ static int intel_dp_vsc_sdp_unpack(struct drm_dp_vsc_sdp *vsc, * VSC SDP supporting 3D stereo + Panel Replay. */ return 0; - } else if (sdp->sdp_header.HB2 == 0x5 && sdp->sdp_header.HB3 == 0x13) { + } else if ((sdp->sdp_header.HB2 == 0x5 || sdp->sdp_header.HB2 == 0x7) && + sdp->sdp_header.HB3 == 0x13) { /* * - HB2 = 0x5, HB3 = 0x13 * VSC SDP supporting 3D stereo + PSR2 + Pixel Encoding/Colorimetry * Format. + * - HB2 = 0x7, HB3 = 0x13 + * VSC SDP supporting 3D stereo + Panel Replay + Pixel Encoding/Colorimetry + * Format. */ vsc->pixelformat = (sdp->db[16] >> 4) & 0xf; vsc->colorimetry = sdp->db[16] & 0xf; From d1ef78f0581e856c4238c751e9ae2884ce58c275 Mon Sep 17 00:00:00 2001 From: Mitul Golani Date: Thu, 17 Sep 2026 13:13:22 +0530 Subject: [PATCH 59/98] drm/i915/vrr: Disable DC balance by default Disable VRR DC balance by default due to timing issues observed on some panel/TCON combinations. Keep the module parameter to enable DC balance during debugging and to isolate DC balance effects from underlying VRR/display timing issues. --v2: - Make enable_dc_balance a bool and keep it disabled by default; fix the parameter type/value mismatch and correct the description (Chaitanya Kumar Borah, Jani Nikula) - Explain in the commit message why the feature is gated and why a module parameter is used (Jani Nikula) --v3: - Commit message update (Jani Nikula) Fixes: 555819270707 ("drm/i915/vrr: Enable DC Balance") Cc: # v7.0+ Signed-off-by: Mitul Golani Reviewed-by: Ankit Nautiyal Signed-off-by: Ankit Nautiyal Link: https://patch.msgid.link/20260917074322.2606738-1-mitulkumar.ajitkumar.golani@intel.com --- drivers/gpu/drm/i915/display/intel_display_params.c | 4 ++++ drivers/gpu/drm/i915/display/intel_display_params.h | 1 + drivers/gpu/drm/i915/display/intel_vrr.c | 4 +++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_params.c b/drivers/gpu/drm/i915/display/intel_display_params.c index 2aed110c5b09..ca0ef466bb10 100644 --- a/drivers/gpu/drm/i915/display/intel_display_params.c +++ b/drivers/gpu/drm/i915/display/intel_display_params.c @@ -120,6 +120,10 @@ intel_display_param_named_unsafe(enable_psr, int, 0400, "(0=disabled, 1=enable up to PSR1, 2=enable up to PSR2) " "Default: -1 (use per-chip default)"); +intel_display_param_named_unsafe(enable_dc_balance, bool, 0400, + "Enable VRR DC balance (0=disabled, 1=enabled). " + "Default: 0 (disabled)"); + intel_display_param_named_unsafe(enable_panel_replay, int, 0400, "Enable Panel Replay (0=disabled, 1=enabled). Default: -1 (use per-chip default)"); diff --git a/drivers/gpu/drm/i915/display/intel_display_params.h b/drivers/gpu/drm/i915/display/intel_display_params.h index ba01aeaf8944..5c5a1a1358c3 100644 --- a/drivers/gpu/drm/i915/display/intel_display_params.h +++ b/drivers/gpu/drm/i915/display/intel_display_params.h @@ -46,6 +46,7 @@ struct drm_printer; param(bool, enable_dp_mst, true, 0600) \ param(int, enable_fbc, -1, 0600) \ param(int, enable_psr, -1, 0600) \ + param(bool, enable_dc_balance, false, 0600) \ param(int, enable_panel_replay, -1, 0600) \ param(bool, psr_safest_params, false, 0400) \ param(bool, enable_psr2_sel_fetch, true, 0400) \ diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index a516ba34e0d0..d43a06907d18 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -441,10 +441,12 @@ static bool intel_vrr_dc_balance_possible(const struct intel_crtc_state *crtc_st static void intel_vrr_dc_balance_compute_config(struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(crtc_state); int guardband_usec, adjustment_usec; struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - if (!intel_vrr_dc_balance_possible(crtc_state) || !crtc_state->vrr.enable) + if (!intel_vrr_dc_balance_possible(crtc_state) || + !crtc_state->vrr.enable || !display->params.enable_dc_balance) return; crtc_state->vrr.dc_balance.vmax = crtc_state->vrr.vmax; From 4ffea6c107c835264577bc4ffc30f4fd8debc313 Mon Sep 17 00:00:00 2001 From: Vinod Govindapillai Date: Wed, 16 Sep 2026 22:56:02 +0300 Subject: [PATCH 60/98] drm/i915/fbc: remove uint16 from supported fbc formats in xe3plpd As UINT16 pixel formats are not listed as supported formats in any of the display versions so far, there is no point is having these formats listed as supported for FBC. So remove the UINT16 formats from the supported formats for FBC. v2: removed an unused variable Signed-off-by: Vinod Govindapillai Reviewed-by: Mika Kahola Link: https://patch.msgid.link/20260916195602.939242-1-vinod.govindapillai@intel.com --- drivers/gpu/drm/i915/display/intel_fbc.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index f61b4a218d6e..5694d20773f8 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -1196,23 +1196,13 @@ xe3p_lpd_fbc_fp16_format_is_valid(const struct intel_plane_state *plane_state) static bool xe3p_lpd_fbc_pixel_format_is_valid(const struct intel_plane_state *plane_state) { - const struct drm_framebuffer *fb = plane_state->hw.fb; - if (lnl_fbc_pixel_format_is_valid(plane_state)) return true; if (xe3p_lpd_fbc_fp16_format_is_valid(plane_state)) return true; - switch (fb->format->format) { - case DRM_FORMAT_XRGB16161616: - case DRM_FORMAT_XBGR16161616: - case DRM_FORMAT_ARGB16161616: - case DRM_FORMAT_ABGR16161616: - return true; - default: - return false; - } + return false; } bool intel_fbc_need_pixel_normalizer(const struct intel_plane_state *plane_state) From 40564c8c7bb383c95739b5af62e90766b5d32759 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Sep 2026 11:29:32 +0300 Subject: [PATCH 61/98] drm/i915/lspcon: use u8 variable to hold 1-byte DPCD reads Passing a pointer to a u32 variable for a 1-byte reads is error prone, and only works because it's always initialized to 0 before the read, and the code's running on little-endian CPUs. Switch to u8 variables. In _lspcon_write_avi_infoframe_mca(), add a separate variable to hold the number of bytes written instead of reusing the same variable for two purposes. Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/66a74267a3da7619dda8dc2b1bb1bfcedc25df0d.1789547331.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_lspcon.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index 9ceabbc981a1..b306bf5f6130 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -435,14 +435,14 @@ static bool _lspcon_write_avi_infoframe_parade(struct drm_dp_aux *aux, static bool _lspcon_write_avi_infoframe_mca(struct drm_dp_aux *aux, const u8 *buffer, ssize_t len) { - int ret; - u32 val = 0; + int ret, written = 0; u32 retry; u16 reg; const u8 *data = buffer; + u8 val; reg = LSPCON_MCA_AVI_IF_WRITE_OFFSET; - while (val < len) { + while (written < len) { /* DPCD write for AVI IF can fail on a slow FW day, so retry */ for (retry = 0; retry < 5; retry++) { ret = drm_dp_dpcd_write(aux, reg, (void *)data, 1); @@ -456,7 +456,9 @@ static bool _lspcon_write_avi_infoframe_mca(struct drm_dp_aux *aux, return false; } } - val++; reg++; data++; + written++; + reg++; + data++; } val = 0; @@ -612,8 +614,8 @@ void lspcon_set_infoframes(struct intel_encoder *encoder, static bool _lspcon_read_avi_infoframe_enabled_mca(struct drm_dp_aux *aux) { int ret; - u32 val = 0; u16 reg = LSPCON_MCA_AVI_IF_CTRL; + u8 val; ret = drm_dp_dpcd_read(aux, reg, &val, 1); if (ret < 0) { @@ -627,8 +629,8 @@ static bool _lspcon_read_avi_infoframe_enabled_mca(struct drm_dp_aux *aux) static bool _lspcon_read_avi_infoframe_enabled_parade(struct drm_dp_aux *aux) { int ret; - u32 val = 0; u16 reg = LSPCON_PARADE_AVI_IF_CTRL; + u8 val; ret = drm_dp_dpcd_read(aux, reg, &val, 1); if (ret < 0) { From a2d0701df0fcb4af26db7c576b7ee5f99e4e8fd4 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Sep 2026 11:29:33 +0300 Subject: [PATCH 62/98] drm/i915/lspcon: switch to drm_dp_dpcd_{read_byte, write_byte, write_data} Switch to the modern DPCD access functions that return negative error codes on errors, -EIO for incomplete access, and 0 on success. Use 1-byte accessors where sensible. Use local ret variables for the return value instead of checking inline. Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/a890746215c6c7a1e36a6bc880ae644dd06f1956.1789547331.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_lspcon.c | 34 +++++++++------------ 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index b306bf5f6130..07b5a9d010ff 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -137,9 +137,7 @@ bool intel_lspcon_detect_hdr_capability(struct intel_digital_port *dig_port) u8 hdr_caps; int ret; - ret = drm_dp_dpcd_read(&intel_dp->aux, get_hdr_status_reg(lspcon), - &hdr_caps, 1); - + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, get_hdr_status_reg(lspcon), &hdr_caps); if (ret < 0) { drm_dbg_kms(display->drm, "HDR capability detection failed\n"); lspcon->hdr_supported = false; @@ -244,10 +242,11 @@ static bool lspcon_wake_native_aux_ch(struct intel_lspcon *lspcon) { struct intel_dp *intel_dp = lspcon_to_intel_dp(lspcon); struct intel_display *display = to_intel_display(intel_dp); + int ret; u8 rev; - if (drm_dp_dpcd_readb(&lspcon_to_intel_dp(lspcon)->aux, DP_DPCD_REV, - &rev) != 1) { + ret = drm_dp_dpcd_read_byte(&lspcon_to_intel_dp(lspcon)->aux, DP_DPCD_REV, &rev); + if (ret < 0) { drm_dbg_kms(display->drm, "Native AUX CH down\n"); return false; } @@ -331,15 +330,14 @@ static bool lspcon_parade_fw_ready(struct drm_dp_aux *aux) { u8 avi_if_ctrl; u8 retry; - ssize_t ret; + int ret; /* Check if LSPCON FW is ready for data */ for (retry = 0; retry < 5; retry++) { if (retry) usleep_range(200, 300); - ret = drm_dp_dpcd_read(aux, LSPCON_PARADE_AVI_IF_CTRL, - &avi_if_ctrl, 1); + ret = drm_dp_dpcd_read_byte(aux, LSPCON_PARADE_AVI_IF_CTRL, &avi_if_ctrl); if (ret < 0) { drm_err(aux->drm_dev, "Failed to read AVI IF control\n"); return false; @@ -371,7 +369,7 @@ static bool _lspcon_parade_write_infoframe_blocks(struct drm_dp_aux *aux, reg = LSPCON_PARADE_AVI_IF_WRITE_OFFSET; data = avi_buf + block_count * 8; - ret = drm_dp_dpcd_write(aux, reg, data, 8); + ret = drm_dp_dpcd_write_data(aux, reg, data, 8); if (ret < 0) { drm_err(aux->drm_dev, "Failed to write AVI IF block %d\n", block_count); @@ -386,7 +384,7 @@ static bool _lspcon_parade_write_infoframe_blocks(struct drm_dp_aux *aux, */ reg = LSPCON_PARADE_AVI_IF_CTRL; avi_if_ctrl = LSPCON_PARADE_AVI_IF_KICKOFF | block_count; - ret = drm_dp_dpcd_write(aux, reg, &avi_if_ctrl, 1); + ret = drm_dp_dpcd_write_byte(aux, reg, avi_if_ctrl); if (ret < 0) { drm_err(aux->drm_dev, "Failed to update (0x%x), block %d\n", reg, block_count); @@ -445,8 +443,8 @@ static bool _lspcon_write_avi_infoframe_mca(struct drm_dp_aux *aux, while (written < len) { /* DPCD write for AVI IF can fail on a slow FW day, so retry */ for (retry = 0; retry < 5; retry++) { - ret = drm_dp_dpcd_write(aux, reg, (void *)data, 1); - if (ret == 1) { + ret = drm_dp_dpcd_write_byte(aux, reg, *data); + if (!ret) { break; } else if (retry < 4) { mdelay(50); @@ -461,9 +459,8 @@ static bool _lspcon_write_avi_infoframe_mca(struct drm_dp_aux *aux, data++; } - val = 0; reg = LSPCON_MCA_AVI_IF_CTRL; - ret = drm_dp_dpcd_read(aux, reg, &val, 1); + ret = drm_dp_dpcd_read_byte(aux, reg, &val); if (ret < 0) { drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg); return false; @@ -473,14 +470,13 @@ static bool _lspcon_write_avi_infoframe_mca(struct drm_dp_aux *aux, val &= ~LSPCON_MCA_AVI_IF_HANDLED; val |= LSPCON_MCA_AVI_IF_KICKOFF; - ret = drm_dp_dpcd_write(aux, reg, &val, 1); + ret = drm_dp_dpcd_write_byte(aux, reg, val); if (ret < 0) { drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg); return false; } - val = 0; - ret = drm_dp_dpcd_read(aux, reg, &val, 1); + ret = drm_dp_dpcd_read_byte(aux, reg, &val); if (ret < 0) { drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg); return false; @@ -617,7 +613,7 @@ static bool _lspcon_read_avi_infoframe_enabled_mca(struct drm_dp_aux *aux) u16 reg = LSPCON_MCA_AVI_IF_CTRL; u8 val; - ret = drm_dp_dpcd_read(aux, reg, &val, 1); + ret = drm_dp_dpcd_read_byte(aux, reg, &val); if (ret < 0) { drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg); return false; @@ -632,7 +628,7 @@ static bool _lspcon_read_avi_infoframe_enabled_parade(struct drm_dp_aux *aux) u16 reg = LSPCON_PARADE_AVI_IF_CTRL; u8 val; - ret = drm_dp_dpcd_read(aux, reg, &val, 1); + ret = drm_dp_dpcd_read_byte(aux, reg, &val); if (ret < 0) { drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg); return false; From 8251875cd96257af98e2853788c58d7178d462a9 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Sep 2026 11:29:34 +0300 Subject: [PATCH 63/98] drm/i915/alpm: switch to drm_dp_dpcd_{read_byte, write_byte} Switch to the modern DPCD access functions that return negative error codes on errors, -EIO for incomplete access, and 0 on success. Rename an int r to ret while at it for clarity. Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/67868fd8a8c8e057ba82c4b142fabae2d0fa52d6.1789547331.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_alpm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c index 10943539bc7c..9ef9d0e45258 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.c +++ b/drivers/gpu/drm/i915/display/intel_alpm.c @@ -628,7 +628,7 @@ void intel_alpm_enable_sink(struct intel_dp *intel_dp, intel_alpm_aux_less_wake_supported(intel_dp))) val |= DP_ALPM_MODE_AUX_LESS; - drm_dp_dpcd_writeb(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG, val); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_RECEIVER_ALPM_CONFIG, val); } void intel_alpm_lobf_enable(const struct intel_crtc_state *new_crtc_state) @@ -751,11 +751,11 @@ bool intel_alpm_get_error(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); struct drm_dp_aux *aux = &intel_dp->aux; + int ret; u8 val; - int r; - r = drm_dp_dpcd_readb(aux, DP_RECEIVER_ALPM_STATUS, &val); - if (r != 1) { + ret = drm_dp_dpcd_read_byte(aux, DP_RECEIVER_ALPM_STATUS, &val); + if (ret < 0) { drm_err(display->drm, "Error reading ALPM status\n"); return true; } @@ -764,7 +764,7 @@ bool intel_alpm_get_error(struct intel_dp *intel_dp) drm_dbg_kms(display->drm, "ALPM lock timeout error\n"); /* Clearing error */ - drm_dp_dpcd_writeb(aux, DP_RECEIVER_ALPM_STATUS, val); + drm_dp_dpcd_write_byte(aux, DP_RECEIVER_ALPM_STATUS, val); return true; } From d613fc2cbe609fa55e1c14218f543ae82595c076 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Sep 2026 11:29:35 +0300 Subject: [PATCH 64/98] drm/i915/ddi: switch to drm_dp_dpcd_write_byte() Switch to the modern DPCD access functions that return negative error codes on errors, -EIO for incomplete access, and 0 on success. Use local ret variables for the return value instead of checking inline where sensible. This improves clarity. Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/f0652fabfd6143680decd826ec74cd5d1116195f.1789547331.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_ddi.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 3cdb06e81130..7efd4c4d4994 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2332,12 +2332,14 @@ static void intel_dp_sink_set_msa_timing_par_ignore_state(struct intel_dp *intel bool enable) { struct intel_display *display = to_intel_display(intel_dp); + int ret; if (!crtc_state->vrr.enable) return; - if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_DOWNSPREAD_CTRL, - enable ? DP_MSA_TIMING_PAR_IGNORE_EN : 0) <= 0) + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_DOWNSPREAD_CTRL, + enable ? DP_MSA_TIMING_PAR_IGNORE_EN : 0); + if (ret < 0) drm_dbg_kms(display->drm, "Failed to %s MSA_TIMING_PAR_IGNORE in the sink\n", str_enable_disable(enable)); @@ -2348,18 +2350,20 @@ static void intel_dp_sink_set_fec_ready(struct intel_dp *intel_dp, bool enable) { struct intel_display *display = to_intel_display(intel_dp); + int ret; if (!crtc_state->fec_enable) return; - if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_FEC_CONFIGURATION, - enable ? DP_FEC_READY : 0) <= 0) + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_FEC_CONFIGURATION, + enable ? DP_FEC_READY : 0); + if (ret < 0) drm_dbg_kms(display->drm, "Failed to set FEC_READY to %s in the sink\n", str_enabled_disabled(enable)); if (enable && - drm_dp_dpcd_writeb(&intel_dp->aux, DP_FEC_STATUS, - DP_FEC_DECODE_EN_DETECTED | DP_FEC_DECODE_DIS_DETECTED) <= 0) + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_FEC_STATUS, + DP_FEC_DECODE_EN_DETECTED | DP_FEC_DECODE_DIS_DETECTED) < 0) drm_dbg_kms(display->drm, "Failed to clear FEC detected flags\n"); } From 551dae8362eb18ef9233cef3ccc840502fb6e92c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Sep 2026 11:29:36 +0300 Subject: [PATCH 65/98] drm/i915/lspcon: switch to drm_dp_dpcd_{read_byte, read_data, write_byte, write_data}() Switch to the modern DPCD access functions that return negative error codes on errors, -EIO for incomplete access, and 0 on success. Use local ret variables for the return value instead of checking inline. Use %pe and ERR_PTR() for logging the errors. Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/f16cb57607634d411a42ca6cd80b10a713d7677f.1789547331.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- .../drm/i915/display/intel_dp_aux_backlight.c | 51 ++++++++++--------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 266e042e0023..f30da5f7e3d2 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -120,8 +120,8 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) intel_dp_wait_source_oui(intel_dp); - ret = drm_dp_dpcd_read(aux, INTEL_EDP_HDR_TCON_CAP0, tcon_cap, sizeof(tcon_cap)); - if (ret != sizeof(tcon_cap)) + ret = drm_dp_dpcd_read_data(aux, INTEL_EDP_HDR_TCON_CAP0, tcon_cap, sizeof(tcon_cap)); + if (ret < 0) return false; drm_dbg_kms(display->drm, @@ -178,8 +178,10 @@ intel_dp_aux_hdr_get_backlight(struct intel_connector *connector, enum pipe pipe struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); u8 tmp; u8 buf[2] = {}; + int ret; - if (drm_dp_dpcd_readb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &tmp) != 1) { + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &tmp); + if (ret < 0) { drm_err(display->drm, "[CONNECTOR:%d:%s] Failed to read current backlight mode from DPCD\n", connector->base.base.id, connector->base.name); @@ -197,8 +199,9 @@ intel_dp_aux_hdr_get_backlight(struct intel_connector *connector, enum pipe pipe return panel->backlight.max; } - if (drm_dp_dpcd_read(&intel_dp->aux, INTEL_EDP_BRIGHTNESS_NITS_LSB, buf, - sizeof(buf)) != sizeof(buf)) { + ret = drm_dp_dpcd_read_data(&intel_dp->aux, INTEL_EDP_BRIGHTNESS_NITS_LSB, buf, + sizeof(buf)); + if (ret < 0) { drm_err(display->drm, "[CONNECTOR:%d:%s] Failed to read brightness from DPCD\n", connector->base.base.id, connector->base.name); @@ -215,12 +218,14 @@ intel_dp_aux_hdr_set_aux_backlight(const struct drm_connector_state *conn_state, struct drm_device *dev = connector->base.dev; struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); u8 buf[4] = {}; + int ret; buf[0] = level & 0xFF; buf[1] = (level & 0xFF00) >> 8; - if (drm_dp_dpcd_write(&intel_dp->aux, INTEL_EDP_BRIGHTNESS_NITS_LSB, buf, - sizeof(buf)) != sizeof(buf)) + ret = drm_dp_dpcd_write_data(&intel_dp->aux, INTEL_EDP_BRIGHTNESS_NITS_LSB, buf, + sizeof(buf)); + if (ret < 0) drm_err(dev, "[CONNECTOR:%d:%s] Failed to write brightness level to DPCD\n", connector->base.base.id, connector->base.name); } @@ -258,13 +263,12 @@ intel_dp_aux_write_content_luminance(struct intel_connector *connector, buf[2] = hdr_metadata->hdmi_metadata_type1.max_fall & 0xFF; buf[3] = (hdr_metadata->hdmi_metadata_type1.max_fall & 0xFF00) >> 8; - ret = drm_dp_dpcd_write(&intel_dp->aux, - INTEL_EDP_HDR_CONTENT_LUMINANCE, - buf, sizeof(buf)); + ret = drm_dp_dpcd_write_data(&intel_dp->aux, + INTEL_EDP_HDR_CONTENT_LUMINANCE, + buf, sizeof(buf)); if (ret < 0) drm_dbg_kms(display->drm, - "Content Luminance DPCD reg write failed, err:-%d\n", - ret); + "Content Luminance DPCD reg write failed (%pe)\n", ERR_PTR(ret)); } static void @@ -313,11 +317,11 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state, intel_dp_wait_source_oui(intel_dp); - ret = drm_dp_dpcd_readb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &old_ctrl); - if (ret != 1) { + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &old_ctrl); + if (ret < 0) { drm_err(display->drm, - "[CONNECTOR:%d:%s] Failed to read current backlight control mode: %d\n", - connector->base.base.id, connector->base.name, ret); + "[CONNECTOR:%d:%s] Failed to read current backlight control mode (%pe)\n", + connector->base.base.id, connector->base.name, ERR_PTR(ret)); return; } @@ -338,7 +342,7 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state, intel_dp_aux_fill_hdr_tcon_params(conn_state, &ctrl); if (ctrl != old_ctrl && - drm_dp_dpcd_writeb(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, ctrl) != 1) + drm_dp_dpcd_write_byte(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, ctrl) < 0) drm_err(display->drm, "[CONNECTOR:%d:%s] Failed to configure DPCD brightness controls\n", connector->base.base.id, connector->base.name); @@ -392,13 +396,12 @@ intel_dp_aux_write_panel_luminance_override(struct intel_connector *connector) buf[2] = panel->backlight.max & 0xFF; buf[3] = (panel->backlight.max & 0xFF00) >> 8; - ret = drm_dp_dpcd_write(&intel_dp->aux, - INTEL_EDP_HDR_PANEL_LUMINANCE_OVERRIDE, - buf, sizeof(buf)); + ret = drm_dp_dpcd_write_data(&intel_dp->aux, + INTEL_EDP_HDR_PANEL_LUMINANCE_OVERRIDE, + buf, sizeof(buf)); if (ret < 0) drm_dbg_kms(display->drm, - "Panel Luminance DPCD reg write failed, err:-%d\n", - ret); + "Panel Luminance DPCD reg write failed (%pe)\n", ERR_PTR(ret)); } static int @@ -456,8 +459,8 @@ static u32 intel_dp_aux_vesa_get_backlight(struct intel_connector *connector, en int ret; if (panel->backlight.edp.vesa.luminance_control_support) { - ret = drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_PANEL_TARGET_LUMINANCE_VALUE, buf, - sizeof(buf)); + ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_EDP_PANEL_TARGET_LUMINANCE_VALUE, buf, + sizeof(buf)); if (ret < 0) { drm_err(intel_dp->aux.drm_dev, "[CONNECTOR:%d:%s] Failed to read Luminance from DPCD\n", From b9290ffeb7096a3305891f2af8a4be96a517af59 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Sep 2026 11:29:37 +0300 Subject: [PATCH 66/98] drm/i915/dp: switch to drm_dp_dpcd_{read_byte, read_data, write_byte, write_data} Switch to the modern DPCD access functions that return negative error codes on errors, -EIO for incomplete access, and 0 on success. Use local ret variables for the return value instead of checking inline, where sensible. Rename local int err to ret for clarity and consistency. Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/ad0a642c726436b5d41f2315e1c431d65fe2ea24.1789547331.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp.c | 142 +++++++++++++++--------- 1 file changed, 88 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 2480b8ce3bec..ffddf4b33728 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -3736,19 +3736,19 @@ static bool downstream_hpd_needs_d0(struct intel_dp *intel_dp) static int write_dsc_decompression_flag(struct drm_dp_aux *aux, u8 flag, bool set) { - int err; + int ret; u8 val; - err = drm_dp_dpcd_readb(aux, DP_DSC_ENABLE, &val); - if (err < 0) - return err; + ret = drm_dp_dpcd_read_byte(aux, DP_DSC_ENABLE, &val); + if (ret < 0) + return ret; if (set) val |= flag; else val &= ~flag; - return drm_dp_dpcd_writeb(aux, DP_DSC_ENABLE, val); + return drm_dp_dpcd_write_byte(aux, DP_DSC_ENABLE, val); } static void @@ -3912,6 +3912,7 @@ intel_dp_init_source_oui(struct intel_dp *intel_dp) struct intel_display *display = to_intel_display(intel_dp); u8 oui[] = { 0x00, 0xaa, 0x01 }; u8 buf[3] = {}; + int ret; if (READ_ONCE(intel_dp->oui_valid)) return; @@ -3922,7 +3923,8 @@ intel_dp_init_source_oui(struct intel_dp *intel_dp) * During driver init, we want to be careful and avoid changing the source OUI if it's * already set to what we want, so as to avoid clearing any state by accident */ - if (drm_dp_dpcd_read(&intel_dp->aux, DP_SOURCE_OUI, buf, sizeof(buf)) < 0) + ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_SOURCE_OUI, buf, sizeof(buf)); + if (ret < 0) drm_dbg_kms(display->drm, "Failed to read source OUI\n"); if (memcmp(oui, buf, sizeof(oui)) == 0) { @@ -3931,7 +3933,8 @@ intel_dp_init_source_oui(struct intel_dp *intel_dp) return; } - if (drm_dp_dpcd_write(&intel_dp->aux, DP_SOURCE_OUI, oui, sizeof(oui)) < 0) { + ret = drm_dp_dpcd_write_data(&intel_dp->aux, DP_SOURCE_OUI, oui, sizeof(oui)); + if (ret < 0) { drm_dbg_kms(display->drm, "Failed to write source OUI\n"); WRITE_ONCE(intel_dp->oui_valid, false); } @@ -3973,7 +3976,7 @@ void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode) if (downstream_hpd_needs_d0(intel_dp)) return; - ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, mode); + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_SET_POWER, mode); } else { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); @@ -3987,17 +3990,17 @@ void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode) * time to wake up. */ for (i = 0; i < 3; i++) { - ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, mode); - if (ret == 1) + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_SET_POWER, mode); + if (!ret) break; msleep(1); } - if (ret == 1 && intel_lspcon_active(dig_port)) + if (!ret && intel_lspcon_active(dig_port)) intel_lspcon_wait_pcon_mode(dig_port); } - if (ret != 1) + if (ret < 0) drm_dbg_kms(display->drm, "[ENCODER:%d:%s] Set power to %s failed\n", encoder->base.base.id, encoder->base.name, @@ -4088,6 +4091,7 @@ bool intel_dp_initial_fastset_check(struct intel_encoder *encoder, static void intel_dp_get_pcon_dsc_cap(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); + int ret; /* Clear the cached register set to avoid using stale values */ @@ -4096,9 +4100,10 @@ static void intel_dp_get_pcon_dsc_cap(struct intel_dp *intel_dp) if (!drm_dp_is_branch(intel_dp->dpcd)) return; - if (drm_dp_dpcd_read(&intel_dp->aux, DP_PCON_DSC_ENCODER, - intel_dp->pcon_dsc_dpcd, - sizeof(intel_dp->pcon_dsc_dpcd)) < 0) + ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_PCON_DSC_ENCODER, + intel_dp->pcon_dsc_dpcd, + sizeof(intel_dp->pcon_dsc_dpcd)); + if (ret < 0) drm_err(display->drm, "Failed to read DPCD register 0x%x\n", DP_PCON_DSC_ENCODER); @@ -4257,13 +4262,13 @@ int intel_dp_pcon_set_tmds_mode(struct intel_dp *intel_dp) /* Set PCON source control mode */ buf |= DP_PCON_ENABLE_SOURCE_CTL_MODE; - ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_PCON_HDMI_LINK_CONFIG_1, buf); + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_PCON_HDMI_LINK_CONFIG_1, buf); if (ret < 0) return ret; /* Set HDMI LINK ENABLE */ buf |= DP_PCON_ENABLE_HDMI_LINK; - ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_PCON_HDMI_LINK_CONFIG_1, buf); + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_PCON_HDMI_LINK_CONFIG_1, buf); if (ret < 0) return ret; @@ -4409,6 +4414,7 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp, bool ycbcr444_to_420 = false; bool rgb_to_ycbcr = false; u8 tmp; + int ret; if (intel_dp->dpcd[DP_DPCD_REV] < 0x13) return; @@ -4418,8 +4424,9 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp, tmp = intel_dp_has_hdmi_sink(intel_dp) ? DP_HDMI_DVI_OUTPUT_CONFIG : 0; - if (drm_dp_dpcd_writeb(&intel_dp->aux, - DP_PROTOCOL_CONVERTER_CONTROL_0, tmp) != 1) + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, + DP_PROTOCOL_CONVERTER_CONTROL_0, tmp); + if (ret < 0) drm_dbg_kms(display->drm, "Failed to %s protocol converter HDMI mode\n", str_enable_disable(intel_dp_has_hdmi_sink(intel_dp))); @@ -4454,15 +4461,17 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp, tmp = ycbcr444_to_420 ? DP_CONVERSION_TO_YCBCR420_ENABLE : 0; - if (drm_dp_dpcd_writeb(&intel_dp->aux, - DP_PROTOCOL_CONVERTER_CONTROL_1, tmp) != 1) + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, + DP_PROTOCOL_CONVERTER_CONTROL_1, tmp); + if (ret < 0) drm_dbg_kms(display->drm, "Failed to %s protocol converter YCbCr 4:2:0 conversion mode\n", str_enable_disable(intel_dp->dfp.ycbcr_444_to_420)); tmp = rgb_to_ycbcr ? DP_CONVERSION_BT709_RGB_YCBCR_ENABLE : 0; - if (drm_dp_pcon_convert_rgb_to_ycbcr(&intel_dp->aux, tmp) < 0) + ret = drm_dp_pcon_convert_rgb_to_ycbcr(&intel_dp->aux, tmp); + if (ret < 0) drm_dbg_kms(display->drm, "Failed to %s protocol converter RGB->YCbCr conversion mode\n", str_enable_disable(tmp)); @@ -4472,8 +4481,8 @@ static u8 intel_dp_read_dprx_feature_enum(struct intel_dp *intel_dp) { u8 dprx = 0; - drm_dp_dpcd_read_data(&intel_dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST, - &dprx, sizeof(dprx)); + drm_dp_dpcd_read_byte(&intel_dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST, &dprx); + return dprx; } @@ -4492,9 +4501,8 @@ static int intel_dp_read_dsc_dpcd(struct drm_dp_aux *aux, { int ret; - ret = drm_dp_dpcd_read_data(aux, DP_DSC_SUPPORT, dsc_dpcd, - DP_DSC_RECEIVER_CAP_SIZE); - if (ret) { + ret = drm_dp_dpcd_read_data(aux, DP_DSC_SUPPORT, dsc_dpcd, DP_DSC_RECEIVER_CAP_SIZE); + if (ret < 0) { drm_dbg_kms(aux->drm_dev, "Could not read DSC DPCD register 0x%x Error: %pe\n", DP_DSC_SUPPORT, ERR_PTR(ret)); @@ -4510,7 +4518,7 @@ static int intel_dp_read_dsc_dpcd(struct drm_dp_aux *aux, static void init_dsc_overall_throughput_limits(struct intel_connector *connector, bool is_branch) { u8 branch_caps[DP_DSC_BRANCH_CAP_SIZE]; - int line_width; + int line_width, ret; connector->dp.dsc_branch_caps.overall_throughput.rgb_yuv444 = INT_MAX; connector->dp.dsc_branch_caps.overall_throughput.yuv422_420 = INT_MAX; @@ -4519,9 +4527,10 @@ static void init_dsc_overall_throughput_limits(struct intel_connector *connector if (!is_branch) return; - if (drm_dp_dpcd_read_data(connector->dp.dsc_decompression_aux, - DP_DSC_BRANCH_OVERALL_THROUGHPUT_0, branch_caps, - sizeof(branch_caps)) != 0) + ret = drm_dp_dpcd_read_data(connector->dp.dsc_decompression_aux, + DP_DSC_BRANCH_OVERALL_THROUGHPUT_0, branch_caps, + sizeof(branch_caps)); + if (ret < 0) return; connector->dp.dsc_branch_caps.overall_throughput.rgb_yuv444 = @@ -4539,6 +4548,7 @@ void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, struct intel_connector *connector) { struct intel_display *display = to_intel_display(connector); + int ret; /* * Clear the cached register set to avoid using stale values @@ -4555,12 +4565,14 @@ void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, if (dpcd_rev < DP_DPCD_REV_14) return; - if (intel_dp_read_dsc_dpcd(connector->dp.dsc_decompression_aux, - connector->dp.dsc_dpcd) < 0) + ret = intel_dp_read_dsc_dpcd(connector->dp.dsc_decompression_aux, + connector->dp.dsc_dpcd); + if (ret < 0) return; - if (drm_dp_dpcd_readb(connector->dp.dsc_decompression_aux, DP_FEC_CAPABILITY, - &connector->dp.fec_capability) < 0) { + ret = drm_dp_dpcd_read_byte(connector->dp.dsc_decompression_aux, DP_FEC_CAPABILITY, + &connector->dp.fec_capability); + if (ret < 0) { drm_dbg_kms(display->drm, "Could not read FEC DPCD register\n"); return; } @@ -4670,12 +4682,14 @@ static void intel_edp_mso_init(struct intel_dp *intel_dp) struct intel_display *display = to_intel_display(intel_dp); struct intel_connector *connector = intel_dp->attached_connector; struct drm_display_info *info = &connector->base.display_info; + int ret; u8 mso; if (intel_dp->edp_dpcd[0] < DP_EDP_14) return; - if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_MSO_LINK_CAPABILITIES, &mso) != 1) { + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_EDP_MSO_LINK_CAPABILITIES, &mso); + if (ret < 0) { drm_err(display->drm, "Failed to read MSO cap\n"); return; } @@ -4853,9 +4867,9 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector * method). The display control registers should read zero if they're * not supported anyway. */ - if (drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_DPCD_REV, - intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd)) == - sizeof(intel_dp->edp_dpcd)) { + ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_EDP_DPCD_REV, + intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd)); + if (!ret) { drm_dbg_kms(display->drm, "eDP DPCD: %*ph\n", (int)sizeof(intel_dp->edp_dpcd), intel_dp->edp_dpcd); @@ -5084,6 +5098,7 @@ static bool intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *esi) { struct intel_display *display = to_intel_display(intel_dp); + int ret; /* * Display WA for HSD #13013007775: mtl/arl/lnl @@ -5092,24 +5107,30 @@ intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *esi) * inadvertently. */ if (IS_DISPLAY_VER(display, 14, 20) && !display->platform.battlemage) { - if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT_ESI, esi, 3) != 3) + ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_SINK_COUNT_ESI, esi, 3); + if (ret < 0) return false; /* DP_SINK_COUNT_ESI + 3 == DP_LINK_SERVICE_IRQ_VECTOR_ESI0 */ - return drm_dp_dpcd_readb(&intel_dp->aux, DP_LINK_SERVICE_IRQ_VECTOR_ESI0, - &esi[3]) == 1; + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_LINK_SERVICE_IRQ_VECTOR_ESI0, + &esi[3]); + return ret == 0; } - return drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT_ESI, esi, 4) == 4; + ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_SINK_COUNT_ESI, esi, 4); + + return ret == 0; } static bool intel_dp_ack_sink_irq_esi(struct intel_dp *intel_dp, u8 esi[4]) { int retry; + int ret; for (retry = 0; retry < 3; retry++) { - if (drm_dp_dpcd_write(&intel_dp->aux, DP_SINK_COUNT_ESI + 1, - &esi[1], 3) == 3) + ret = drm_dp_dpcd_write_data(&intel_dp->aux, DP_SINK_COUNT_ESI + 1, + &esi[1], 3); + if (!ret) return true; } @@ -5119,20 +5140,24 @@ static bool intel_dp_ack_sink_irq_esi(struct intel_dp *intel_dp, u8 esi[4]) /* Return %true if reading the ESI vector succeeded, %false otherwise. */ static bool intel_dp_get_sink_irq_esi_sst(struct intel_dp *intel_dp, u8 esi[4]) { + int ret; + memset(esi, 0, 4); /* * TODO: For DP_DPCD_REV >= 0x12 read * DP_SINK_COUNT_ESI and DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0. */ - if (drm_dp_dpcd_read_data(&intel_dp->aux, DP_SINK_COUNT, esi, 2) != 0) + ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_SINK_COUNT, esi, 2); + if (ret < 0) return false; if (intel_dp->dpcd[DP_DPCD_REV] < DP_DPCD_REV_12) return true; /* TODO: Read DP_DEVICE_SERVICE_IRQ_VECTOR_ESI1 as well */ - if (drm_dp_dpcd_read_byte(&intel_dp->aux, DP_LINK_SERVICE_IRQ_VECTOR_ESI0, &esi[3]) != 0) + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_LINK_SERVICE_IRQ_VECTOR_ESI0, &esi[3]); + if (ret < 0) return false; return true; @@ -5141,18 +5166,22 @@ static bool intel_dp_get_sink_irq_esi_sst(struct intel_dp *intel_dp, u8 esi[4]) /* Return %true if acking the ESI vector IRQ events succeeded, %false otherwise. */ static bool intel_dp_ack_sink_irq_esi_sst(struct intel_dp *intel_dp, u8 esi[4]) { + int ret; + /* * TODO: For DP_DPCD_REV >= 0x12 write * DP_DEVICE_SERVICE_IRQ_VECTOR_ESI0 */ - if (drm_dp_dpcd_write_byte(&intel_dp->aux, DP_DEVICE_SERVICE_IRQ_VECTOR, esi[1]) != 0) + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_DEVICE_SERVICE_IRQ_VECTOR, esi[1]); + if (ret < 0) return false; if (intel_dp->dpcd[DP_DPCD_REV] < DP_DPCD_REV_12) return true; /* TODO: Read DP_DEVICE_SERVICE_IRQ_VECTOR_ESI1 as well */ - if (drm_dp_dpcd_write_byte(&intel_dp->aux, DP_LINK_SERVICE_IRQ_VECTOR_ESI0, esi[3]) != 0) + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_LINK_SERVICE_IRQ_VECTOR_ESI0, esi[3]); + if (ret < 0) return false; return true; @@ -5750,14 +5779,17 @@ intel_dp_handle_hdmi_link_status_change(struct intel_dp *intel_dp) { bool is_active; u8 buf = 0; + int ret; is_active = drm_dp_pcon_hdmi_link_active(&intel_dp->aux); if (intel_dp->frl.is_trained && !is_active) { - if (drm_dp_dpcd_readb(&intel_dp->aux, DP_PCON_HDMI_LINK_CONFIG_1, &buf) < 0) + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_PCON_HDMI_LINK_CONFIG_1, &buf); + if (ret < 0) return; buf &= ~DP_PCON_ENABLE_HDMI_LINK; - if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_PCON_HDMI_LINK_CONFIG_1, buf) < 0) + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_PCON_HDMI_LINK_CONFIG_1, buf); + if (ret < 0) return; drm_dp_pcon_hdmi_frl_link_error_count(&intel_dp->aux, &intel_dp->attached_connector->base); @@ -6262,6 +6294,7 @@ static bool intel_dp_sink_supports_as_sdp_v2(struct intel_dp *intel_dp) { u8 rx_features; + int ret; /* * The DP spec does not explicitly provide the AS SDP v2 capability. @@ -6284,9 +6317,10 @@ intel_dp_sink_supports_as_sdp_v2(struct intel_dp *intel_dp) * support from Display ID. */ - if (drm_dp_dpcd_read_byte(&intel_dp->aux, - DP_DPRX_FEATURE_ENUMERATION_LIST_CONT_1, - &rx_features) == 1) { + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, + DP_DPRX_FEATURE_ENUMERATION_LIST_CONT_1, + &rx_features); + if (!ret) { if (rx_features & DP_AS_SDP_FAVT_PAYLOAD_FIELDS_PARSING_SUPPORTED) return true; } From 41de7a1888fe1aff94411162dc31fb48b0234619 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 21 Sep 2026 12:41:03 +0300 Subject: [PATCH 67/98] drm/i915/hdcp: switch to drm_dp_dpcd_{read_byte, read_data, write_data}() Switch to the modern DPCD access functions that return negative error codes on errors, -EIO for incomplete access, and 0 on success. This simplifies error handling all over the place. Convert the error logging to use %pe and ERR_PTR() while at it. Add comments to the read/write places that depend on the functions that return the number of bytes read/written for incomplete access. v2: return length from get_receiver_id_list_rx_info() (Sashiko) Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/20260921094103.701841-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 176 +++++++++---------- 1 file changed, 88 insertions(+), 88 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 14ed0ea22dd3..566a921d18a1 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -60,16 +60,15 @@ int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *dig_port, { struct intel_display *display = to_intel_display(dig_port); u8 aksv[DRM_HDCP_KSV_LEN] = {}; - ssize_t dpcd_ret; + int ret; /* Output An first, that's easy */ - dpcd_ret = drm_dp_dpcd_write(&dig_port->dp.aux, DP_AUX_HDCP_AN, + ret = drm_dp_dpcd_write_data(&dig_port->dp.aux, DP_AUX_HDCP_AN, an, DRM_HDCP_AN_LEN); - if (dpcd_ret != DRM_HDCP_AN_LEN) { + if (ret < 0) { drm_dbg_kms(display->drm, - "Failed to write An over DP/AUX (%zd)\n", - dpcd_ret); - return dpcd_ret >= 0 ? -EIO : dpcd_ret; + "Failed to write An over DP/AUX (%pe)\n", ERR_PTR(ret)); + return ret; } /* @@ -79,14 +78,14 @@ int intel_dp_hdcp_write_an_aksv(struct intel_digital_port *dig_port, * the destination address which will tickle the hardware to output the * Aksv on our behalf after the header is sent. */ - dpcd_ret = drm_dp_dpcd_write(&dig_port->dp.aux, DP_AUX_HDCP_AKSV, + ret = drm_dp_dpcd_write_data(&dig_port->dp.aux, DP_AUX_HDCP_AKSV, aksv, DRM_HDCP_KSV_LEN); - if (dpcd_ret != DRM_HDCP_KSV_LEN) { + if (ret < 0) { drm_dbg_kms(display->drm, - "Failed to write Aksv over DP/AUX (%zd)\n", - dpcd_ret); - return dpcd_ret >= 0 ? -EIO : dpcd_ret; + "Failed to write Aksv over DP/AUX (%pe)\n", ERR_PTR(ret)); + return ret; } + return 0; } @@ -94,15 +93,16 @@ static int intel_dp_hdcp_read_bksv(struct intel_digital_port *dig_port, u8 *bksv) { struct intel_display *display = to_intel_display(dig_port); - ssize_t ret; + int ret; - ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BKSV, bksv, - DRM_HDCP_KSV_LEN); - if (ret != DRM_HDCP_KSV_LEN) { + ret = drm_dp_dpcd_read_data(&dig_port->dp.aux, DP_AUX_HDCP_BKSV, bksv, + DRM_HDCP_KSV_LEN); + if (ret < 0) { drm_dbg_kms(display->drm, - "Read Bksv from DP/AUX failed (%zd)\n", ret); - return ret >= 0 ? -EIO : ret; + "Read Bksv from DP/AUX failed (%pe)\n", ERR_PTR(ret)); + return ret; } + return 0; } @@ -110,20 +110,21 @@ static int intel_dp_hdcp_read_bstatus(struct intel_digital_port *dig_port, u8 *bstatus) { struct intel_display *display = to_intel_display(dig_port); - ssize_t ret; + int ret; /* * For some reason the HDMI and DP HDCP specs call this register * definition by different names. In the HDMI spec, it's called BSTATUS, * but in DP it's called BINFO. */ - ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BINFO, - bstatus, DRM_HDCP_BSTATUS_LEN); - if (ret != DRM_HDCP_BSTATUS_LEN) { + ret = drm_dp_dpcd_read_data(&dig_port->dp.aux, DP_AUX_HDCP_BINFO, + bstatus, DRM_HDCP_BSTATUS_LEN); + if (ret < 0) { drm_dbg_kms(display->drm, - "Read bstatus from DP/AUX failed (%zd)\n", ret); - return ret >= 0 ? -EIO : ret; + "Read bstatus from DP/AUX failed (%pe)\n", ERR_PTR(ret)); + return ret; } + return 0; } @@ -132,14 +133,13 @@ int intel_dp_hdcp_read_bcaps(struct drm_dp_aux *aux, struct intel_display *display, u8 *bcaps) { - ssize_t ret; + int ret; - ret = drm_dp_dpcd_read(aux, DP_AUX_HDCP_BCAPS, - bcaps, 1); - if (ret != 1) { + ret = drm_dp_dpcd_read_byte(aux, DP_AUX_HDCP_BCAPS, bcaps); + if (ret < 0) { drm_dbg_kms(display->drm, - "Read bcaps from DP/AUX failed (%zd)\n", ret); - return ret >= 0 ? -EIO : ret; + "Read bcaps from DP/AUX failed (%pe)\n", ERR_PTR(ret)); + return ret; } return 0; @@ -166,16 +166,16 @@ int intel_dp_hdcp_read_ri_prime(struct intel_digital_port *dig_port, u8 *ri_prime) { struct intel_display *display = to_intel_display(dig_port); - ssize_t ret; + int ret; - ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_RI_PRIME, - ri_prime, DRM_HDCP_RI_LEN); - if (ret != DRM_HDCP_RI_LEN) { + ret = drm_dp_dpcd_read_data(&dig_port->dp.aux, DP_AUX_HDCP_RI_PRIME, + ri_prime, DRM_HDCP_RI_LEN); + if (ret < 0) { drm_dbg_kms(display->drm, - "Read Ri' from DP/AUX failed (%zd)\n", - ret); - return ret >= 0 ? -EIO : ret; + "Read Ri' from DP/AUX failed (%pe)\n", ERR_PTR(ret)); + return ret; } + return 0; } @@ -184,17 +184,18 @@ int intel_dp_hdcp_read_ksv_ready(struct intel_digital_port *dig_port, bool *ksv_ready) { struct intel_display *display = to_intel_display(dig_port); - ssize_t ret; u8 bstatus; + int ret; - ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BSTATUS, - &bstatus, 1); - if (ret != 1) { + ret = drm_dp_dpcd_read_byte(&dig_port->dp.aux, DP_AUX_HDCP_BSTATUS, + &bstatus); + if (ret < 0) { drm_dbg_kms(display->drm, - "Read bstatus from DP/AUX failed (%zd)\n", ret); - return ret >= 0 ? -EIO : ret; + "Read bstatus from DP/AUX failed (%pe)\n", ERR_PTR(ret)); + return ret; } *ksv_ready = bstatus & DP_BSTATUS_READY; + return 0; } @@ -203,23 +204,24 @@ int intel_dp_hdcp_read_ksv_fifo(struct intel_digital_port *dig_port, int num_downstream, u8 *ksv_fifo) { struct intel_display *display = to_intel_display(dig_port); - ssize_t ret; + int ret; int i; /* KSV list is read via 15 byte window (3 entries @ 5 bytes each) */ for (i = 0; i < num_downstream; i += 3) { size_t len = min(num_downstream - i, 3) * DRM_HDCP_KSV_LEN; - ret = drm_dp_dpcd_read(&dig_port->dp.aux, - DP_AUX_HDCP_KSV_FIFO, - ksv_fifo + i * DRM_HDCP_KSV_LEN, - len); - if (ret != len) { + ret = drm_dp_dpcd_read_data(&dig_port->dp.aux, + DP_AUX_HDCP_KSV_FIFO, + ksv_fifo + i * DRM_HDCP_KSV_LEN, + len); + if (ret < 0) { drm_dbg_kms(display->drm, - "Read ksv[%d] from DP/AUX failed (%zd)\n", - i, ret); - return ret >= 0 ? -EIO : ret; + "Read ksv[%d] from DP/AUX failed (%pe)\n", + i, ERR_PTR(ret)); + return ret; } } + return 0; } @@ -228,19 +230,19 @@ int intel_dp_hdcp_read_v_prime_part(struct intel_digital_port *dig_port, int i, u32 *part) { struct intel_display *display = to_intel_display(dig_port); - ssize_t ret; + int ret; if (i >= DRM_HDCP_V_PRIME_NUM_PARTS) return -EINVAL; - ret = drm_dp_dpcd_read(&dig_port->dp.aux, - DP_AUX_HDCP_V_PRIME(i), part, - DRM_HDCP_V_PRIME_PART_LEN); - if (ret != DRM_HDCP_V_PRIME_PART_LEN) { + ret = drm_dp_dpcd_read_data(&dig_port->dp.aux, DP_AUX_HDCP_V_PRIME(i), part, + DRM_HDCP_V_PRIME_PART_LEN); + if (ret < 0) { drm_dbg_kms(display->drm, - "Read v'[%d] from DP/AUX failed (%zd)\n", i, ret); - return ret >= 0 ? -EIO : ret; + "Read v'[%d] from DP/AUX failed (%pe)\n", i, ERR_PTR(ret)); + return ret; } + return 0; } @@ -258,14 +260,13 @@ bool intel_dp_hdcp_check_link(struct intel_digital_port *dig_port, struct intel_connector *connector) { struct intel_display *display = to_intel_display(dig_port); - ssize_t ret; u8 bstatus; + int ret; - ret = drm_dp_dpcd_read(&dig_port->dp.aux, DP_AUX_HDCP_BSTATUS, - &bstatus, 1); - if (ret != 1) { + ret = drm_dp_dpcd_read_byte(&dig_port->dp.aux, DP_AUX_HDCP_BSTATUS, &bstatus); + if (ret < 0) { drm_dbg_kms(display->drm, - "Read bstatus from DP/AUX failed (%zd)\n", ret); + "Read bstatus from DP/AUX failed (%pe)\n", ERR_PTR(ret)); return false; } @@ -346,15 +347,14 @@ intel_dp_hdcp2_read_rx_status(struct intel_connector *connector, struct intel_display *display = to_intel_display(connector); struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_dp_aux *aux = &dig_port->dp.aux; - ssize_t ret; + int ret; - ret = drm_dp_dpcd_read(aux, - DP_HDCP_2_2_REG_RXSTATUS_OFFSET, rx_status, - HDCP_2_2_DP_RXSTATUS_LEN); - if (ret != HDCP_2_2_DP_RXSTATUS_LEN) { + ret = drm_dp_dpcd_read_data(aux, DP_HDCP_2_2_REG_RXSTATUS_OFFSET, rx_status, + HDCP_2_2_DP_RXSTATUS_LEN); + if (ret < 0) { drm_dbg_kms(display->drm, - "Read bstatus from DP/AUX failed (%zd)\n", ret); - return ret >= 0 ? -EIO : ret; + "Read bstatus from DP/AUX failed (%pe)\n", ERR_PTR(ret)); + return ret; } return 0; @@ -474,8 +474,8 @@ int intel_dp_hdcp2_write_msg(struct intel_connector *connector, len = bytes_to_write > DP_AUX_MAX_PAYLOAD_BYTES ? DP_AUX_MAX_PAYLOAD_BYTES : bytes_to_write; - ret = drm_dp_dpcd_write(aux, - offset, (void *)byte, len); + /* Note: This may return < len for partial writes. */ + ret = drm_dp_dpcd_write(aux, offset, byte, len); if (ret < 0) return ret; @@ -487,20 +487,20 @@ int intel_dp_hdcp2_write_msg(struct intel_connector *connector, return size; } +/* return number of bytes read on success */ static ssize_t get_receiver_id_list_rx_info(struct intel_connector *connector, u32 *dev_cnt, u8 *byte) { struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_dp_aux *aux = &dig_port->dp.aux; - ssize_t ret; u8 *rx_info = byte; + int ret; - ret = drm_dp_dpcd_read(aux, - DP_HDCP_2_2_REG_RXINFO_OFFSET, - (void *)rx_info, HDCP_2_2_RXINFO_LEN); - if (ret != HDCP_2_2_RXINFO_LEN) - return ret >= 0 ? -EIO : ret; + ret = drm_dp_dpcd_read_data(aux, DP_HDCP_2_2_REG_RXINFO_OFFSET, + rx_info, HDCP_2_2_RXINFO_LEN); + if (ret < 0) + return ret; *dev_cnt = (HDCP_2_2_DEV_COUNT_HI(rx_info[0]) << 4 | HDCP_2_2_DEV_COUNT_LO(rx_info[1])); @@ -508,7 +508,7 @@ ssize_t get_receiver_id_list_rx_info(struct intel_connector *connector, if (*dev_cnt > HDCP_2_2_MAX_DEVICE_COUNT) *dev_cnt = HDCP_2_2_MAX_DEVICE_COUNT; - return ret; + return HDCP_2_2_RXINFO_LEN; } static @@ -566,11 +566,11 @@ int intel_dp_hdcp2_read_msg(struct intel_connector *connector, hdcp2_msg_data->msg_read_timeout); } - ret = drm_dp_dpcd_read(aux, offset, - (void *)byte, len); + /* Note: This may return < len for partial reads. */ + ret = drm_dp_dpcd_read(aux, offset, byte, len); if (ret < 0) { - drm_dbg_kms(display->drm, "msg_id %d, ret %zd\n", - msg_id, ret); + drm_dbg_kms(display->drm, "msg_id %d, ret %pe\n", + msg_id, ERR_PTR(ret)); return ret; } @@ -660,11 +660,11 @@ int _intel_dp_hdcp2_get_capability(struct drm_dp_aux *aux, * declare a monitor not capable of HDCP 2.2. */ for (i = 0; i < 3; i++) { - ret = drm_dp_dpcd_read(aux, - DP_HDCP_2_2_REG_RX_CAPS_OFFSET, - rx_caps, HDCP_2_2_RXCAPS_LEN); - if (ret != HDCP_2_2_RXCAPS_LEN) - return ret >= 0 ? -EIO : ret; + ret = drm_dp_dpcd_read_data(aux, + DP_HDCP_2_2_REG_RX_CAPS_OFFSET, + rx_caps, HDCP_2_2_RXCAPS_LEN); + if (ret < 0) + return ret; if (rx_caps[0] == HDCP_2_2_RX_CAPS_VERSION_VAL && HDCP_2_2_DP_HDCP_CAPABLE(rx_caps[2])) { From fc980a78c218a6f3f695827832dcd0cc5ff3ca37 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Sep 2026 11:29:39 +0300 Subject: [PATCH 68/98] drm/i915/dp: switch link training to drm_dp_dpcd_{read_byte, read_data, write_byte, write_data}() Switch to the modern DPCD access functions that return negative error codes on errors, -EIO for incomplete access, and 0 on success. Use local ret variables for the return value instead of checking inline, where sensible. Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/c88130676c7b8187a5e5954cdbd36c316950d89f.1789547331.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- .../drm/i915/display/intel_dp_link_training.c | 48 ++++++++++--------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index 9a692f4fdfee..b6e8b13ee4db 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -929,7 +929,7 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, { int reg = intel_dp_training_pattern_set_reg(intel_dp, dp_phy); u8 buf[sizeof(intel_dp->train_set) + 1]; - int len; + int ret, len; intel_dp_program_link_training_pattern(intel_dp, crtc_state, dp_phy, dp_train_pat); @@ -939,7 +939,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp, memcpy(buf + 1, intel_dp->train_set, crtc_state->lane_count); len = crtc_state->lane_count + 1; - return drm_dp_dpcd_write(&intel_dp->aux, reg, buf, len) == len; + ret = drm_dp_dpcd_write_data(&intel_dp->aux, reg, buf, len); + + return !ret; } static char dp_training_pattern_name(u8 train_pat) @@ -1046,10 +1048,10 @@ intel_dp_update_link_train(struct intel_dp *intel_dp, intel_dp_set_signal_levels(intel_dp, crtc_state, dp_phy); - ret = drm_dp_dpcd_write(&intel_dp->aux, reg, - intel_dp->train_set, crtc_state->lane_count); + ret = drm_dp_dpcd_write_data(&intel_dp->aux, reg, + intel_dp->train_set, crtc_state->lane_count); - return ret == crtc_state->lane_count; + return !ret; } /* 128b/132b */ @@ -1115,7 +1117,7 @@ void intel_dp_link_training_set_mode(struct intel_dp *intel_dp, int link_rate, link_config[0] |= pr_with_as_sdp_enable ? DP_FIXED_VTOTAL_AS_SDP_EN_IN_PR_ACTIVE : 0; link_config[1] = drm_dp_is_uhbr_rate(link_rate) ? DP_SET_ANSI_128B132B : DP_SET_ANSI_8B10B; - drm_dp_dpcd_write(&intel_dp->aux, DP_DOWNSPREAD_CTRL, link_config, 2); + drm_dp_dpcd_write_data(&intel_dp->aux, DP_DOWNSPREAD_CTRL, link_config, 2); } static bool @@ -1163,8 +1165,8 @@ void intel_dp_link_training_set_bw(struct intel_dp *intel_dp, /* DP and eDP v1.3 and earlier link bw set method. */ u8 link_config[] = { link_bw, lane_count }; - drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, - ARRAY_SIZE(link_config)); + drm_dp_dpcd_write_data(&intel_dp->aux, DP_LINK_BW_SET, link_config, + sizeof(link_config)); } else { /* * eDP v1.4 and later link rate set method. @@ -1175,8 +1177,8 @@ void intel_dp_link_training_set_bw(struct intel_dp *intel_dp, * eDP v1.5 sinks allow choosing either, and the last choice * shall be active. */ - drm_dp_dpcd_writeb(&intel_dp->aux, DP_LANE_COUNT_SET, lane_count); - drm_dp_dpcd_writeb(&intel_dp->aux, DP_LINK_RATE_SET, rate_select); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_LANE_COUNT_SET, lane_count); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_LINK_RATE_SET, rate_select); } } @@ -1286,8 +1288,8 @@ intel_dp_prepare_link_train(struct intel_dp *intel_dp, lt_dbg(intel_dp, DP_PHY_DPRX, "Reloading eDP link rates\n"); - drm_dp_dpcd_read(&intel_dp->aux, DP_SUPPORTED_LINK_RATES, - sink_rates, sizeof(sink_rates)); + drm_dp_dpcd_read_data(&intel_dp->aux, DP_SUPPORTED_LINK_RATES, + sink_rates, sizeof(sink_rates)); } if (link_bw) @@ -1612,7 +1614,7 @@ static void intel_dp_stop_post_lt_adj_req(struct intel_dp *intel_dp, if (crtc_state->enhanced_framing) lane_count |= DP_LANE_COUNT_ENHANCED_FRAME_EN; - drm_dp_dpcd_writeb(&intel_dp->aux, DP_LANE_COUNT_SET, lane_count); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_LANE_COUNT_SET, lane_count); } static bool intel_dp_disable_dpcd_training_pattern(struct intel_dp *intel_dp, @@ -1621,7 +1623,7 @@ static bool intel_dp_disable_dpcd_training_pattern(struct intel_dp *intel_dp, int reg = intel_dp_training_pattern_set_reg(intel_dp, dp_phy); u8 val = DP_TRAINING_PATTERN_DISABLE; - return drm_dp_dpcd_write(&intel_dp->aux, reg, &val, 1) == 1; + return drm_dp_dpcd_write_byte(&intel_dp->aux, reg, val) == 0; } static int @@ -1631,10 +1633,10 @@ intel_dp_128b132b_intra_hop(struct intel_dp *intel_dp, u8 sink_status; int ret; - ret = drm_dp_dpcd_readb(&intel_dp->aux, DP_SINK_STATUS, &sink_status); - if (ret != 1) { + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_SINK_STATUS, &sink_status); + if (ret < 0) { lt_dbg(intel_dp, DP_PHY_DPRX, "Failed to read sink status\n"); - return ret < 0 ? ret : -EIO; + return ret; } return sink_status & DP_INTRA_HOP_AUX_REPLY_INDICATION ? 1 : 0; @@ -2173,9 +2175,11 @@ intel_dp_128b132b_lane_cds(struct intel_dp *intel_dp, { u8 link_status[DP_LINK_STATUS_SIZE]; unsigned long deadline; + int ret; - if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TRAINING_PATTERN_SET, - DP_TRAINING_PATTERN_2_CDS) != 1) { + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_2_CDS); + if (ret < 0) { lt_err(intel_dp, DP_PHY_DPRX, "Failed to start 128b/132b TPS2 CDS\n"); return false; } @@ -2363,9 +2367,9 @@ void intel_dp_128b132b_sdp_crc16(struct intel_dp *intel_dp, return; /* DP v2.0 SCR on SDP CRC16 for 128b/132b Link Layer */ - drm_dp_dpcd_writeb(&intel_dp->aux, - DP_SDP_ERROR_DETECTION_CONFIGURATION, - DP_SDP_CRC16_128B132B_EN); + drm_dp_dpcd_write_byte(&intel_dp->aux, + DP_SDP_ERROR_DETECTION_CONFIGURATION, + DP_SDP_CRC16_128B132B_EN); lt_dbg(intel_dp, DP_PHY_DPRX, "DP2.0 SDP CRC16 for 128b/132b enabled\n"); } From 791a8519ff8407fd17a9ef04cf97771b5a37435b Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Sep 2026 11:29:40 +0300 Subject: [PATCH 69/98] drm/i915/dp-mst: switch to drm_dp_dpcd_read_byte() Switch to the modern DPCD access functions that return negative error codes on errors, -EIO for incomplete access, and 0 on success. Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/26dfbd4d99f86c19efbff89613728ab967ec4f67.1789547331.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp_mst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 0c362784afe4..7023619aaaba 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -2252,7 +2252,7 @@ bool intel_dp_mst_verify_dpcd_state(struct intel_dp *intel_dp) if (!intel_dp->is_mst) return true; - ret = drm_dp_dpcd_readb(intel_dp->mst.mgr.aux, DP_MSTM_CTRL, &val); + ret = drm_dp_dpcd_read_byte(intel_dp->mst.mgr.aux, DP_MSTM_CTRL, &val); /* Adjust the expected register value for SST + SideBand. */ if (ret < 0 || val != (DP_MST_EN | DP_UP_REQ_EN | DP_UPSTREAM_IS_SRC)) { From 3216d9cc254bb03c0bec1084d7bfccff2ecbcc7a Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Sep 2026 11:29:41 +0300 Subject: [PATCH 70/98] drm/i915/dp-test: switch to drm_dp_dpcd_{read_byte, read_data, write_byte, write_data}() Switch to the modern DPCD access functions that return negative error codes on errors, -EIO for incomplete access, and 0 on success. This flags incomplete reads, and simplifies error handling all over the place. Rename local int status to ret for clarity and consistency. Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/ddf90aeb0dae3779d92381f550d95111398e7e02.1789547331.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp_test.c | 57 ++++++++++---------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_test.c b/drivers/gpu/drm/i915/display/intel_dp_test.c index 0551a1ce60d3..424183a65155 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_test.c +++ b/drivers/gpu/drm/i915/display/intel_dp_test.c @@ -147,25 +147,24 @@ bool intel_dp_test_compute_config(struct intel_connector *connector, static u8 intel_dp_autotest_link_training(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); - int status = 0; + int ret; int test_link_rate; u8 test_lane_count, test_link_bw; /* (DP CTS 1.2) * 4.3.1.11 */ /* Read the TEST_LANE_COUNT and TEST_LINK_RTAE fields (DP CTS 3.1.4) */ - status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_LANE_COUNT, - &test_lane_count); - - if (status <= 0) { + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_TEST_LANE_COUNT, + &test_lane_count); + if (ret < 0) { drm_dbg_kms(display->drm, "Lane count read failed\n"); return DP_TEST_NAK; } test_lane_count &= DP_MAX_LANE_COUNT_MASK; - status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_LINK_RATE, - &test_link_bw); - if (status <= 0) { + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_TEST_LINK_RATE, + &test_link_bw); + if (ret < 0) { drm_dbg_kms(display->drm, "Link Rate read failed\n"); return DP_TEST_NAK; } @@ -188,35 +187,33 @@ static u8 intel_dp_autotest_video_pattern(struct intel_dp *intel_dp) u8 test_pattern; u8 test_misc; __be16 h_width, v_height; - int status = 0; + int ret; /* Read the TEST_PATTERN (DP CTS 3.1.5) */ - status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_PATTERN, - &test_pattern); - if (status <= 0) { + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_TEST_PATTERN, + &test_pattern); + if (ret < 0) { drm_dbg_kms(display->drm, "Test pattern read failed\n"); return DP_TEST_NAK; } if (test_pattern != DP_COLOR_RAMP) return DP_TEST_NAK; - status = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_H_WIDTH_HI, - &h_width, 2); - if (status <= 0) { + ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_TEST_H_WIDTH_HI, &h_width, 2); + if (ret < 0) { drm_dbg_kms(display->drm, "H Width read failed\n"); return DP_TEST_NAK; } - status = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_V_HEIGHT_HI, - &v_height, 2); - if (status <= 0) { + ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_TEST_V_HEIGHT_HI, + &v_height, 2); + if (ret < 0) { drm_dbg_kms(display->drm, "V Height read failed\n"); return DP_TEST_NAK; } - status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_MISC0, - &test_misc); - if (status <= 0) { + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_TEST_MISC0, &test_misc); + if (ret < 0) { drm_dbg_kms(display->drm, "TEST MISC read failed\n"); return DP_TEST_NAK; } @@ -274,8 +271,8 @@ static u8 intel_dp_autotest_edid(struct intel_dp *intel_dp) /* We have to write the checksum of the last block read */ block += block->extensions; - if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_EDID_CHECKSUM, - block->checksum) <= 0) + if (drm_dp_dpcd_write_byte(&intel_dp->aux, DP_TEST_EDID_CHECKSUM, + block->checksum) < 0) drm_dbg_kms(display->drm, "Failed to write EDID checksum\n"); @@ -397,8 +394,8 @@ static void intel_dp_process_phy_request(struct intel_dp *intel_dp, intel_dp_phy_pattern_update(intel_dp, crtc_state); - drm_dp_dpcd_write(&intel_dp->aux, DP_TRAINING_LANE0_SET, - intel_dp->train_set, crtc_state->lane_count); + drm_dp_dpcd_write_data(&intel_dp->aux, DP_TRAINING_LANE0_SET, + intel_dp->train_set, crtc_state->lane_count); drm_dp_set_phy_test_pattern(&intel_dp->aux, data, intel_dp->dpcd[DP_DPCD_REV]); @@ -427,10 +424,10 @@ void intel_dp_test_request(struct intel_dp *intel_dp) struct intel_display *display = to_intel_display(intel_dp); u8 response = DP_TEST_NAK; u8 request = 0; - int status; + int ret; - status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_REQUEST, &request); - if (status <= 0) { + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_TEST_REQUEST, &request); + if (ret < 0) { drm_dbg_kms(display->drm, "Could not read test request from sink\n"); goto update_status; @@ -463,8 +460,8 @@ void intel_dp_test_request(struct intel_dp *intel_dp) intel_dp->compliance.test_type = request; update_status: - status = drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_RESPONSE, response); - if (status <= 0) + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_TEST_RESPONSE, response); + if (ret < 0) drm_dbg_kms(display->drm, "Could not write test response to sink\n"); } From b6413a8f75e642bc4e75dcb3c25c7a8b5f451d33 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Sep 2026 11:29:42 +0300 Subject: [PATCH 71/98] drm/i915/psr: switch to drm_dp_dpcd_{read_byte, read_data, write_byte, write_data}() Switch to the modern DPCD access functions that return negative error codes on errors, -EIO for incomplete access, and 0 on success. This flags incomplete reads, and clarifies error handling all over the place. Use 1-byte accessors where sensible. Rename local int r to ret for clarity and consistency. Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/0a32cfdb64a37e586579a689bd8c3c4944596a31.1789547331.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_psr.c | 65 ++++++++++++------------ 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 872e253db178..f1d48b69a18f 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -471,9 +471,10 @@ static u8 intel_dp_get_sink_sync_latency(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); u8 val = 8; /* assume the worst if we can't read the value */ + int ret; - if (drm_dp_dpcd_readb(&intel_dp->aux, - DP_SYNCHRONIZATION_LATENCY_IN_SINK, &val) == 1) + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_SYNCHRONIZATION_LATENCY_IN_SINK, &val); + if (!ret) val &= DP_MAX_RESYNC_FRAME_COUNT_MASK; else drm_dbg_kms(display->drm, @@ -485,7 +486,7 @@ static void _psr_compute_su_granularity(struct intel_dp *intel_dp, struct intel_connector *connector) { struct intel_display *display = to_intel_display(intel_dp); - ssize_t r; + int ret; __le16 w; u8 y; @@ -500,19 +501,19 @@ static void _psr_compute_su_granularity(struct intel_dp *intel_dp, goto exit; } - r = drm_dp_dpcd_read(&intel_dp->aux, DP_PSR2_SU_X_GRANULARITY, &w, sizeof(w)); - if (r != sizeof(w)) + ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_PSR2_SU_X_GRANULARITY, &w, sizeof(w)); + if (ret < 0) drm_dbg_kms(display->drm, "Unable to read selective update x granularity\n"); /* * Spec says that if the value read is 0 the default granularity should * be used instead. */ - if (r != sizeof(w) || w == 0) + if (ret < 0 || w == 0) w = cpu_to_le16(4); - r = drm_dp_dpcd_read(&intel_dp->aux, DP_PSR2_SU_Y_GRANULARITY, &y, 1); - if (r != 1) { + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_PSR2_SU_Y_GRANULARITY, &y); + if (ret < 0) { drm_dbg_kms(display->drm, "Unable to read selective update y granularity\n"); y = 4; @@ -796,11 +797,11 @@ static void _panel_replay_enable_sink(struct intel_dp *intel_dp, panel_replay_config[1] |= DP_PANEL_REPLAY_SU_REGION_SCANLINE_CAPTURE; - drm_dp_dpcd_write(&intel_dp->aux, PANEL_REPLAY_CONFIG, - panel_replay_config, sizeof(panel_replay_config)); + drm_dp_dpcd_write_data(&intel_dp->aux, PANEL_REPLAY_CONFIG, + panel_replay_config, sizeof(panel_replay_config)); panel_replay_config_3 = intel_dp_as_sdp_transmission_time(); - drm_dp_dpcd_writeb(&intel_dp->aux, PANEL_REPLAY_CONFIG3, panel_replay_config_3); + drm_dp_dpcd_write_byte(&intel_dp->aux, PANEL_REPLAY_CONFIG3, panel_replay_config_3); } static void _psr_enable_sink(struct intel_dp *intel_dp, @@ -827,10 +828,10 @@ static void _psr_enable_sink(struct intel_dp *intel_dp, if (intel_dp->psr.entry_setup_frames > 0) val |= DP_PSR_FRAME_CAPTURE; - drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, val); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_PSR_EN_CFG, val); val |= DP_PSR_ENABLE; - drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, val); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_PSR_EN_CFG, val); } static void intel_psr_enable_sink(struct intel_dp *intel_dp, @@ -843,7 +844,7 @@ static void intel_psr_enable_sink(struct intel_dp *intel_dp, _psr_enable_sink(intel_dp, crtc_state); if (intel_dp_is_edp(intel_dp)) - drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); } void intel_psr_panel_replay_enable_sink(struct intel_dp *intel_dp) @@ -854,8 +855,8 @@ void intel_psr_panel_replay_enable_sink(struct intel_dp *intel_dp) * ensure this bit is cleared/set accordingly. */ if (CAN_PANEL_REPLAY(intel_dp) && panel_replay_global_enabled(intel_dp)) - drm_dp_dpcd_writeb(&intel_dp->aux, PANEL_REPLAY_CONFIG, - DP_PANEL_REPLAY_ENABLE); + drm_dp_dpcd_write_byte(&intel_dp->aux, PANEL_REPLAY_CONFIG, + DP_PANEL_REPLAY_ENABLE); } static u32 intel_psr1_get_tp_time(struct intel_dp *intel_dp) @@ -2373,11 +2374,11 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) /* Disable PSR on Sink */ if (!intel_dp->psr.panel_replay_enabled) { - drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_PSR_EN_CFG, 0); if (intel_dp->psr.sel_update_enabled) - drm_dp_dpcd_writeb(&intel_dp->aux, - DP_RECEIVER_ALPM_CONFIG, 0); + drm_dp_dpcd_write_byte(&intel_dp->aux, + DP_RECEIVER_ALPM_CONFIG, 0); } /* Wa_16025596647 */ @@ -3517,7 +3518,7 @@ static void intel_psr_handle_irq(struct intel_dp *intel_dp) intel_psr_disable_locked(intel_dp); psr->sink_not_reliable = true; /* let's make sure that sink is awaken */ - drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_SET_POWER, DP_SET_POWER_D0); } static void intel_psr_work(struct work_struct *work) @@ -3796,15 +3797,15 @@ static int psr_get_status_and_error_status(struct intel_dp *intel_dp, offset = intel_dp->psr.panel_replay_enabled ? DP_SINK_DEVICE_PR_AND_FRAME_LOCK_STATUS : DP_PSR_STATUS; - ret = drm_dp_dpcd_readb(aux, offset, status); - if (ret != 1) + ret = drm_dp_dpcd_read_byte(aux, offset, status); + if (ret < 0) return ret; offset = intel_dp->psr.panel_replay_enabled ? DP_PANEL_REPLAY_ERROR_STATUS : DP_PSR_ERROR_STATUS; - ret = drm_dp_dpcd_readb(aux, offset, error_status); - if (ret != 1) + ret = drm_dp_dpcd_read_byte(aux, offset, error_status); + if (ret < 0) return ret; *status = *status & DP_PSR_SINK_STATE_MASK; @@ -3829,11 +3830,11 @@ static void psr_capability_changed_check(struct intel_dp *intel_dp) { struct intel_display *display = to_intel_display(intel_dp); struct intel_psr *psr = &intel_dp->psr; + int ret; u8 val; - int r; - r = drm_dp_dpcd_readb(&intel_dp->aux, DP_PSR_ESI, &val); - if (r != 1) { + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_PSR_ESI, &val); + if (ret < 0) { drm_err(display->drm, "Error reading DP_PSR_ESI\n"); return; } @@ -3845,7 +3846,7 @@ static void psr_capability_changed_check(struct intel_dp *intel_dp) "Sink PSR capability changed, disabling PSR\n"); /* Clearing it */ - drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_ESI, val); + drm_dp_dpcd_write_byte(&intel_dp->aux, DP_PSR_ESI, val); } } @@ -3913,10 +3914,10 @@ void intel_psr_short_pulse(struct intel_dp *intel_dp) "PSR_ERROR_STATUS unhandled errors %x\n", error_status & ~errors); /* clear status register */ - drm_dp_dpcd_writeb(&intel_dp->aux, - panel_replay_enabled ? - DP_PANEL_REPLAY_ERROR_STATUS : DP_PSR_ERROR_STATUS, - error_status); + drm_dp_dpcd_write_byte(&intel_dp->aux, + panel_replay_enabled ? + DP_PANEL_REPLAY_ERROR_STATUS : DP_PSR_ERROR_STATUS, + error_status); if (!psr->panel_replay_enabled) { psr_alpm_check(intel_dp); From 9663c15d93e39fbad397e759669d21f96777697e Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 22 Sep 2026 18:17:21 +0300 Subject: [PATCH 72/98] drm/xe/display: reduce includes in xe_display.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit xe_display.c has a bunch of extra leftover includes. Remove and simplify. Reviewed-by: Michał Grzelak Link: https://patch.msgid.link/20260922151721.1483978-1-jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/xe/display/xe_display.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index 7b25c0814674..506f26e9c59a 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -6,31 +6,23 @@ #include "xe_display.h" #include "regs/xe_irq_regs.h" -#include +#include -#include -#include #include #include -#include #include #include -#include -#include "intel_acpi.h" #include "intel_display.h" #include "intel_display_core.h" #include "intel_display_device.h" #include "intel_display_driver.h" #include "intel_display_irq.h" -#include "intel_display_types.h" #include "intel_dmc.h" #include "intel_dmc_wl.h" -#include "intel_dp.h" #include "intel_fbdev.h" #include "intel_hotplug.h" #include "intel_opregion.h" -#include "skl_watermark.h" #include "xe_device.h" #include "xe_display_bo.h" #include "xe_display_pcode.h" From 17727f634433a4d1a7bc1764b90fa16eec860422 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Tue, 22 Sep 2026 17:43:16 +0530 Subject: [PATCH 73/98] drm/i915/lspcon: log DPCD access errors Now that the DPCD accessors return a proper error code, include it in the error messages using %pe and ERR_PTR(), instead of just stating that the access failed. While at it, fix the AVI IF control write error message, which incorrectly reported a failed read. Signed-off-by: Suraj Kandpal Reviewed-by: Nemesa Garg Link: https://patch.msgid.link/20260922121316.1768918-1-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_lspcon.c | 34 +++++++++++++-------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index 07b5a9d010ff..a61224523318 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -139,7 +139,8 @@ bool intel_lspcon_detect_hdr_capability(struct intel_digital_port *dig_port) ret = drm_dp_dpcd_read_byte(&intel_dp->aux, get_hdr_status_reg(lspcon), &hdr_caps); if (ret < 0) { - drm_dbg_kms(display->drm, "HDR capability detection failed\n"); + drm_dbg_kms(display->drm, "HDR capability detection failed (%pe)\n", + ERR_PTR(ret)); lspcon->hdr_supported = false; } else if (hdr_caps & 0x1) { drm_dbg_kms(display->drm, "LSPCON capable of HDR\n"); @@ -247,7 +248,7 @@ static bool lspcon_wake_native_aux_ch(struct intel_lspcon *lspcon) ret = drm_dp_dpcd_read_byte(&lspcon_to_intel_dp(lspcon)->aux, DP_DPCD_REV, &rev); if (ret < 0) { - drm_dbg_kms(display->drm, "Native AUX CH down\n"); + drm_dbg_kms(display->drm, "Native AUX CH down (%pe)\n", ERR_PTR(ret)); return false; } @@ -339,7 +340,8 @@ static bool lspcon_parade_fw_ready(struct drm_dp_aux *aux) ret = drm_dp_dpcd_read_byte(aux, LSPCON_PARADE_AVI_IF_CTRL, &avi_if_ctrl); if (ret < 0) { - drm_err(aux->drm_dev, "Failed to read AVI IF control\n"); + drm_err(aux->drm_dev, "Failed to read AVI IF control (%pe)\n", + ERR_PTR(ret)); return false; } @@ -371,8 +373,8 @@ static bool _lspcon_parade_write_infoframe_blocks(struct drm_dp_aux *aux, data = avi_buf + block_count * 8; ret = drm_dp_dpcd_write_data(aux, reg, data, 8); if (ret < 0) { - drm_err(aux->drm_dev, "Failed to write AVI IF block %d\n", - block_count); + drm_err(aux->drm_dev, "Failed to write AVI IF block %d (%pe)\n", + block_count, ERR_PTR(ret)); return false; } @@ -386,8 +388,8 @@ static bool _lspcon_parade_write_infoframe_blocks(struct drm_dp_aux *aux, avi_if_ctrl = LSPCON_PARADE_AVI_IF_KICKOFF | block_count; ret = drm_dp_dpcd_write_byte(aux, reg, avi_if_ctrl); if (ret < 0) { - drm_err(aux->drm_dev, "Failed to update (0x%x), block %d\n", - reg, block_count); + drm_err(aux->drm_dev, "Failed to update (0x%x), block %d (%pe)\n", + reg, block_count, ERR_PTR(ret)); return false; } @@ -450,7 +452,8 @@ static bool _lspcon_write_avi_infoframe_mca(struct drm_dp_aux *aux, mdelay(50); continue; } else { - drm_err(aux->drm_dev, "DPCD write failed at:0x%x\n", reg); + drm_err(aux->drm_dev, "DPCD write failed at:0x%x (%pe)\n", + reg, ERR_PTR(ret)); return false; } } @@ -462,7 +465,8 @@ static bool _lspcon_write_avi_infoframe_mca(struct drm_dp_aux *aux, reg = LSPCON_MCA_AVI_IF_CTRL; ret = drm_dp_dpcd_read_byte(aux, reg, &val); if (ret < 0) { - drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg); + drm_err(aux->drm_dev, "DPCD read failed, address 0x%x (%pe)\n", + reg, ERR_PTR(ret)); return false; } @@ -472,13 +476,15 @@ static bool _lspcon_write_avi_infoframe_mca(struct drm_dp_aux *aux, ret = drm_dp_dpcd_write_byte(aux, reg, val); if (ret < 0) { - drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg); + drm_err(aux->drm_dev, "DPCD write failed at:0x%x (%pe)\n", + reg, ERR_PTR(ret)); return false; } ret = drm_dp_dpcd_read_byte(aux, reg, &val); if (ret < 0) { - drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg); + drm_err(aux->drm_dev, "DPCD read failed, address 0x%x (%pe)\n", + reg, ERR_PTR(ret)); return false; } @@ -615,7 +621,8 @@ static bool _lspcon_read_avi_infoframe_enabled_mca(struct drm_dp_aux *aux) ret = drm_dp_dpcd_read_byte(aux, reg, &val); if (ret < 0) { - drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg); + drm_err(aux->drm_dev, "DPCD read failed, address 0x%x (%pe)\n", + reg, ERR_PTR(ret)); return false; } @@ -630,7 +637,8 @@ static bool _lspcon_read_avi_infoframe_enabled_parade(struct drm_dp_aux *aux) ret = drm_dp_dpcd_read_byte(aux, reg, &val); if (ret < 0) { - drm_err(aux->drm_dev, "DPCD read failed, address 0x%x\n", reg); + drm_err(aux->drm_dev, "DPCD read failed, address 0x%x (%pe)\n", + reg, ERR_PTR(ret)); return false; } From ebaa19c84f24f2fce51272d7f107ee704918f16b Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Mon, 21 Sep 2026 11:07:04 +0530 Subject: [PATCH 74/98] drm/i915/alpm: log DPCD access errors Now that the DPCD accessors return a proper error code, include it in the error messages using %pe and ERR_PTR(), instead of just stating that the access failed. Signed-off-by: Suraj Kandpal Reviewed-by: Nemesa Garg Link: https://patch.msgid.link/20260921053710.1586776-3-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_alpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_alpm.c b/drivers/gpu/drm/i915/display/intel_alpm.c index 9ef9d0e45258..f54b29e193ee 100644 --- a/drivers/gpu/drm/i915/display/intel_alpm.c +++ b/drivers/gpu/drm/i915/display/intel_alpm.c @@ -756,7 +756,7 @@ bool intel_alpm_get_error(struct intel_dp *intel_dp) ret = drm_dp_dpcd_read_byte(aux, DP_RECEIVER_ALPM_STATUS, &val); if (ret < 0) { - drm_err(display->drm, "Error reading ALPM status\n"); + drm_err(display->drm, "Error reading ALPM status (%pe)\n", ERR_PTR(ret)); return true; } From a27ef41465cb728931731e9f0bea568c198863f0 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Mon, 21 Sep 2026 11:07:05 +0530 Subject: [PATCH 75/98] drm/i915/ddi: log DPCD access errors Now that the DPCD accessors return a proper error code, include it in the error messages using %pe and ERR_PTR(), instead of just stating that the access failed. Store the FEC_STATUS write result in ret as well, so that it can be logged the same way. Signed-off-by: Suraj Kandpal Reviewed-by: Nemesa Garg Link: https://patch.msgid.link/20260921053710.1586776-4-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 7efd4c4d4994..a46ab5d3d70f 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2341,8 +2341,8 @@ static void intel_dp_sink_set_msa_timing_par_ignore_state(struct intel_dp *intel enable ? DP_MSA_TIMING_PAR_IGNORE_EN : 0); if (ret < 0) drm_dbg_kms(display->drm, - "Failed to %s MSA_TIMING_PAR_IGNORE in the sink\n", - str_enable_disable(enable)); + "Failed to %s MSA_TIMING_PAR_IGNORE in the sink (%pe)\n", + str_enable_disable(enable), ERR_PTR(ret)); } static void intel_dp_sink_set_fec_ready(struct intel_dp *intel_dp, @@ -2358,13 +2358,17 @@ static void intel_dp_sink_set_fec_ready(struct intel_dp *intel_dp, ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_FEC_CONFIGURATION, enable ? DP_FEC_READY : 0); if (ret < 0) - drm_dbg_kms(display->drm, "Failed to set FEC_READY to %s in the sink\n", - str_enabled_disabled(enable)); + drm_dbg_kms(display->drm, "Failed to set FEC_READY to %s in the sink (%pe)\n", + str_enabled_disabled(enable), ERR_PTR(ret)); - if (enable && - drm_dp_dpcd_write_byte(&intel_dp->aux, DP_FEC_STATUS, - DP_FEC_DECODE_EN_DETECTED | DP_FEC_DECODE_DIS_DETECTED) < 0) - drm_dbg_kms(display->drm, "Failed to clear FEC detected flags\n"); + if (enable) { + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_FEC_STATUS, + DP_FEC_DECODE_EN_DETECTED | + DP_FEC_DECODE_DIS_DETECTED); + if (ret < 0) + drm_dbg_kms(display->drm, "Failed to clear FEC detected flags (%pe)\n", + ERR_PTR(ret)); + } } static int wait_for_fec_detected(struct drm_dp_aux *aux, bool enabled) From 07d52ff1f649dea1298925021450ac000c3f52fc Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Mon, 21 Sep 2026 11:07:06 +0530 Subject: [PATCH 76/98] drm/i915/backlight: log DPCD access errors Now that the DPCD accessors return a proper error code, include it in the error messages using %pe and ERR_PTR(), instead of just stating that the access failed. Store the brightness control write result in ret as well, so that it can be logged the same way. Signed-off-by: Suraj Kandpal Reviewed-by: Nemesa Garg Link: https://patch.msgid.link/20260921053710.1586776-5-suraj.kandpal@intel.com --- .../drm/i915/display/intel_dp_aux_backlight.c | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index f30da5f7e3d2..36aebc32971b 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -183,8 +183,8 @@ intel_dp_aux_hdr_get_backlight(struct intel_connector *connector, enum pipe pipe ret = drm_dp_dpcd_read_byte(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, &tmp); if (ret < 0) { drm_err(display->drm, - "[CONNECTOR:%d:%s] Failed to read current backlight mode from DPCD\n", - connector->base.base.id, connector->base.name); + "[CONNECTOR:%d:%s] Failed to read current backlight mode from DPCD (%pe)\n", + connector->base.base.id, connector->base.name, ERR_PTR(ret)); return 0; } @@ -203,8 +203,8 @@ intel_dp_aux_hdr_get_backlight(struct intel_connector *connector, enum pipe pipe sizeof(buf)); if (ret < 0) { drm_err(display->drm, - "[CONNECTOR:%d:%s] Failed to read brightness from DPCD\n", - connector->base.base.id, connector->base.name); + "[CONNECTOR:%d:%s] Failed to read brightness from DPCD (%pe)\n", + connector->base.base.id, connector->base.name, ERR_PTR(ret)); return 0; } @@ -226,8 +226,8 @@ intel_dp_aux_hdr_set_aux_backlight(const struct drm_connector_state *conn_state, ret = drm_dp_dpcd_write_data(&intel_dp->aux, INTEL_EDP_BRIGHTNESS_NITS_LSB, buf, sizeof(buf)); if (ret < 0) - drm_err(dev, "[CONNECTOR:%d:%s] Failed to write brightness level to DPCD\n", - connector->base.base.id, connector->base.name); + drm_err(dev, "[CONNECTOR:%d:%s] Failed to write brightness level to DPCD (%pe)\n", + connector->base.base.id, connector->base.name, ERR_PTR(ret)); } static void @@ -341,11 +341,14 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state, intel_dp_aux_fill_hdr_tcon_params(conn_state, &ctrl); - if (ctrl != old_ctrl && - drm_dp_dpcd_write_byte(&intel_dp->aux, INTEL_EDP_HDR_GETSET_CTRL_PARAMS, ctrl) < 0) - drm_err(display->drm, - "[CONNECTOR:%d:%s] Failed to configure DPCD brightness controls\n", - connector->base.base.id, connector->base.name); + if (ctrl != old_ctrl) { + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, + INTEL_EDP_HDR_GETSET_CTRL_PARAMS, ctrl); + if (ret < 0) + drm_err(display->drm, + "[CONNECTOR:%d:%s] Failed to configure DPCD brightness controls (%pe)\n", + connector->base.base.id, connector->base.name, ERR_PTR(ret)); + } if (intel_dp_in_hdr_mode(conn_state)) { hdr_metadata = conn_state->hdr_output_metadata->data; @@ -463,8 +466,8 @@ static u32 intel_dp_aux_vesa_get_backlight(struct intel_connector *connector, en sizeof(buf)); if (ret < 0) { drm_err(intel_dp->aux.drm_dev, - "[CONNECTOR:%d:%s] Failed to read Luminance from DPCD\n", - connector->base.base.id, connector->base.name); + "[CONNECTOR:%d:%s] Failed to read Luminance from DPCD (%pe)\n", + connector->base.base.id, connector->base.name, ERR_PTR(ret)); return 0; } From 6591a9bf2586f3351fafd0d3a412fc0d480a9f81 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Mon, 21 Sep 2026 11:07:07 +0530 Subject: [PATCH 77/98] drm/i915/dp: log DPCD access errors Now that the DPCD accessors return a proper error code, include it in the error messages using %pe and ERR_PTR(), instead of just stating that the access failed. Signed-off-by: Suraj Kandpal Reviewed-by: Nemesa Garg Link: https://patch.msgid.link/20260921053710.1586776-6-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 31 ++++++++++++++----------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index ffddf4b33728..d8c0d9381471 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -3925,7 +3925,7 @@ intel_dp_init_source_oui(struct intel_dp *intel_dp) */ ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_SOURCE_OUI, buf, sizeof(buf)); if (ret < 0) - drm_dbg_kms(display->drm, "Failed to read source OUI\n"); + drm_dbg_kms(display->drm, "Failed to read source OUI (%pe)\n", ERR_PTR(ret)); if (memcmp(oui, buf, sizeof(oui)) == 0) { /* Assume the OUI was written now. */ @@ -3935,7 +3935,7 @@ intel_dp_init_source_oui(struct intel_dp *intel_dp) ret = drm_dp_dpcd_write_data(&intel_dp->aux, DP_SOURCE_OUI, oui, sizeof(oui)); if (ret < 0) { - drm_dbg_kms(display->drm, "Failed to write source OUI\n"); + drm_dbg_kms(display->drm, "Failed to write source OUI (%pe)\n", ERR_PTR(ret)); WRITE_ONCE(intel_dp->oui_valid, false); } @@ -4002,9 +4002,9 @@ void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode) if (ret < 0) drm_dbg_kms(display->drm, - "[ENCODER:%d:%s] Set power to %s failed\n", + "[ENCODER:%d:%s] Set power to %s failed (%pe)\n", encoder->base.base.id, encoder->base.name, - mode == DP_SET_POWER_D0 ? "D0" : "D3"); + mode == DP_SET_POWER_D0 ? "D0" : "D3", ERR_PTR(ret)); } static bool @@ -4104,8 +4104,8 @@ static void intel_dp_get_pcon_dsc_cap(struct intel_dp *intel_dp) intel_dp->pcon_dsc_dpcd, sizeof(intel_dp->pcon_dsc_dpcd)); if (ret < 0) - drm_err(display->drm, "Failed to read DPCD register 0x%x\n", - DP_PCON_DSC_ENCODER); + drm_err(display->drm, "Failed to read DPCD register 0x%x (%pe)\n", + DP_PCON_DSC_ENCODER, ERR_PTR(ret)); drm_dbg_kms(display->drm, "PCON ENCODER DSC DPCD: %*ph\n", (int)sizeof(intel_dp->pcon_dsc_dpcd), intel_dp->pcon_dsc_dpcd); @@ -4428,8 +4428,9 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp, DP_PROTOCOL_CONVERTER_CONTROL_0, tmp); if (ret < 0) drm_dbg_kms(display->drm, - "Failed to %s protocol converter HDMI mode\n", - str_enable_disable(intel_dp_has_hdmi_sink(intel_dp))); + "Failed to %s protocol converter HDMI mode (%pe)\n", + str_enable_disable(intel_dp_has_hdmi_sink(intel_dp)), + ERR_PTR(ret)); if (crtc_state->sink_format == INTEL_OUTPUT_FORMAT_YCBCR420) { switch (crtc_state->output_format) { @@ -4465,16 +4466,17 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp, DP_PROTOCOL_CONVERTER_CONTROL_1, tmp); if (ret < 0) drm_dbg_kms(display->drm, - "Failed to %s protocol converter YCbCr 4:2:0 conversion mode\n", - str_enable_disable(intel_dp->dfp.ycbcr_444_to_420)); + "Failed to %s protocol converter YCbCr 4:2:0 conversion mode (%pe)\n", + str_enable_disable(intel_dp->dfp.ycbcr_444_to_420), + ERR_PTR(ret)); tmp = rgb_to_ycbcr ? DP_CONVERSION_BT709_RGB_YCBCR_ENABLE : 0; ret = drm_dp_pcon_convert_rgb_to_ycbcr(&intel_dp->aux, tmp); if (ret < 0) drm_dbg_kms(display->drm, - "Failed to %s protocol converter RGB->YCbCr conversion mode\n", - str_enable_disable(tmp)); + "Failed to %s protocol converter RGB->YCbCr conversion mode (%pe)\n", + str_enable_disable(tmp), ERR_PTR(ret)); } static u8 intel_dp_read_dprx_feature_enum(struct intel_dp *intel_dp) @@ -4573,7 +4575,8 @@ void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, ret = drm_dp_dpcd_read_byte(connector->dp.dsc_decompression_aux, DP_FEC_CAPABILITY, &connector->dp.fec_capability); if (ret < 0) { - drm_dbg_kms(display->drm, "Could not read FEC DPCD register\n"); + drm_dbg_kms(display->drm, "Could not read FEC DPCD register (%pe)\n", + ERR_PTR(ret)); return; } @@ -4690,7 +4693,7 @@ static void intel_edp_mso_init(struct intel_dp *intel_dp) ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_EDP_MSO_LINK_CAPABILITIES, &mso); if (ret < 0) { - drm_err(display->drm, "Failed to read MSO cap\n"); + drm_err(display->drm, "Failed to read MSO cap (%pe)\n", ERR_PTR(ret)); return; } From 1d9d3bc0dad332361e1363df50b058634dcd232d Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Mon, 21 Sep 2026 11:07:08 +0530 Subject: [PATCH 78/98] drm/i915/linktraining: log link training DPCD access errors Now that the DPCD accessors return a proper error code, include it in the error messages using %pe and ERR_PTR(), instead of just stating that the access failed. Signed-off-by: Suraj Kandpal Reviewed-by: Nemesa Garg Link: https://patch.msgid.link/20260921053710.1586776-7-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_dp_link_training.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index b6e8b13ee4db..ac1aff6edf05 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -1635,7 +1635,8 @@ intel_dp_128b132b_intra_hop(struct intel_dp *intel_dp, ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_SINK_STATUS, &sink_status); if (ret < 0) { - lt_dbg(intel_dp, DP_PHY_DPRX, "Failed to read sink status\n"); + lt_dbg(intel_dp, DP_PHY_DPRX, "Failed to read sink status (%pe)\n", + ERR_PTR(ret)); return ret; } @@ -2180,7 +2181,8 @@ intel_dp_128b132b_lane_cds(struct intel_dp *intel_dp, ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_2_CDS); if (ret < 0) { - lt_err(intel_dp, DP_PHY_DPRX, "Failed to start 128b/132b TPS2 CDS\n"); + lt_err(intel_dp, DP_PHY_DPRX, "Failed to start 128b/132b TPS2 CDS (%pe)\n", + ERR_PTR(ret)); return false; } From 0cddb1e03381532727bddd3bc18818af98c4c7d1 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Mon, 21 Sep 2026 11:07:09 +0530 Subject: [PATCH 79/98] drm/i915/dptest: log DPCD access errors Now that the DPCD accessors return a proper error code, include it in the error messages using %pe and ERR_PTR(), instead of just stating that the access failed. Store the EDID checksum write result in ret as well, so that it can be logged the same way. Signed-off-by: Suraj Kandpal Reviewed-by: Nemesa Garg Link: https://patch.msgid.link/20260921053710.1586776-8-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_dp_test.c | 24 +++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_test.c b/drivers/gpu/drm/i915/display/intel_dp_test.c index 424183a65155..17cf27273124 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_test.c +++ b/drivers/gpu/drm/i915/display/intel_dp_test.c @@ -157,7 +157,7 @@ static u8 intel_dp_autotest_link_training(struct intel_dp *intel_dp) ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_TEST_LANE_COUNT, &test_lane_count); if (ret < 0) { - drm_dbg_kms(display->drm, "Lane count read failed\n"); + drm_dbg_kms(display->drm, "Lane count read failed (%pe)\n", ERR_PTR(ret)); return DP_TEST_NAK; } test_lane_count &= DP_MAX_LANE_COUNT_MASK; @@ -165,7 +165,7 @@ static u8 intel_dp_autotest_link_training(struct intel_dp *intel_dp) ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_TEST_LINK_RATE, &test_link_bw); if (ret < 0) { - drm_dbg_kms(display->drm, "Link Rate read failed\n"); + drm_dbg_kms(display->drm, "Link Rate read failed (%pe)\n", ERR_PTR(ret)); return DP_TEST_NAK; } test_link_rate = drm_dp_bw_code_to_link_rate(test_link_bw); @@ -193,7 +193,7 @@ static u8 intel_dp_autotest_video_pattern(struct intel_dp *intel_dp) ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_TEST_PATTERN, &test_pattern); if (ret < 0) { - drm_dbg_kms(display->drm, "Test pattern read failed\n"); + drm_dbg_kms(display->drm, "Test pattern read failed (%pe)\n", ERR_PTR(ret)); return DP_TEST_NAK; } if (test_pattern != DP_COLOR_RAMP) @@ -201,20 +201,20 @@ static u8 intel_dp_autotest_video_pattern(struct intel_dp *intel_dp) ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_TEST_H_WIDTH_HI, &h_width, 2); if (ret < 0) { - drm_dbg_kms(display->drm, "H Width read failed\n"); + drm_dbg_kms(display->drm, "H Width read failed (%pe)\n", ERR_PTR(ret)); return DP_TEST_NAK; } ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_TEST_V_HEIGHT_HI, &v_height, 2); if (ret < 0) { - drm_dbg_kms(display->drm, "V Height read failed\n"); + drm_dbg_kms(display->drm, "V Height read failed (%pe)\n", ERR_PTR(ret)); return DP_TEST_NAK; } ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_TEST_MISC0, &test_misc); if (ret < 0) { - drm_dbg_kms(display->drm, "TEST MISC read failed\n"); + drm_dbg_kms(display->drm, "TEST MISC read failed (%pe)\n", ERR_PTR(ret)); return DP_TEST_NAK; } if ((test_misc & DP_TEST_COLOR_FORMAT_MASK) != DP_COLOR_FORMAT_RGB) @@ -247,6 +247,7 @@ static u8 intel_dp_autotest_edid(struct intel_dp *intel_dp) u8 test_result = DP_TEST_ACK; struct intel_connector *intel_connector = intel_dp->attached_connector; struct drm_connector *connector = &intel_connector->base; + int ret; if (!intel_connector->detect_edid || connector->edid_corrupt || intel_dp->aux.i2c_defer_count > 6) { @@ -271,10 +272,11 @@ static u8 intel_dp_autotest_edid(struct intel_dp *intel_dp) /* We have to write the checksum of the last block read */ block += block->extensions; - if (drm_dp_dpcd_write_byte(&intel_dp->aux, DP_TEST_EDID_CHECKSUM, - block->checksum) < 0) + ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_TEST_EDID_CHECKSUM, + block->checksum); + if (ret < 0) drm_dbg_kms(display->drm, - "Failed to write EDID checksum\n"); + "Failed to write EDID checksum (%pe)\n", ERR_PTR(ret)); test_result = DP_TEST_ACK | DP_TEST_EDID_CHECKSUM_WRITE; intel_dp->compliance.test_data.edid = INTEL_DP_RESOLUTION_PREFERRED; @@ -429,7 +431,7 @@ void intel_dp_test_request(struct intel_dp *intel_dp) ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_TEST_REQUEST, &request); if (ret < 0) { drm_dbg_kms(display->drm, - "Could not read test request from sink\n"); + "Could not read test request from sink (%pe)\n", ERR_PTR(ret)); goto update_status; } @@ -463,7 +465,7 @@ void intel_dp_test_request(struct intel_dp *intel_dp) ret = drm_dp_dpcd_write_byte(&intel_dp->aux, DP_TEST_RESPONSE, response); if (ret < 0) drm_dbg_kms(display->drm, - "Could not write test response to sink\n"); + "Could not write test response to sink (%pe)\n", ERR_PTR(ret)); } /* phy test */ From a24f49a328477ef8520ec1d803c99adece6c6fb2 Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Mon, 21 Sep 2026 11:07:10 +0530 Subject: [PATCH 80/98] drm/i915/psr: log DPCD access errors Now that the DPCD accessors return a proper error code, include it in the error messages using %pe and ERR_PTR(), instead of just stating that the access failed. Signed-off-by: Suraj Kandpal Reviewed-by: Nemesa Garg Link: https://patch.msgid.link/20260921053710.1586776-9-suraj.kandpal@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index f1d48b69a18f..00d0146b2600 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -478,7 +478,8 @@ static u8 intel_dp_get_sink_sync_latency(struct intel_dp *intel_dp) val &= DP_MAX_RESYNC_FRAME_COUNT_MASK; else drm_dbg_kms(display->drm, - "Unable to get sink synchronization latency, assuming 8 frames\n"); + "Unable to get sink synchronization latency, assuming 8 frames (%pe)\n", + ERR_PTR(ret)); return val; } @@ -504,7 +505,8 @@ static void _psr_compute_su_granularity(struct intel_dp *intel_dp, ret = drm_dp_dpcd_read_data(&intel_dp->aux, DP_PSR2_SU_X_GRANULARITY, &w, sizeof(w)); if (ret < 0) drm_dbg_kms(display->drm, - "Unable to read selective update x granularity\n"); + "Unable to read selective update x granularity (%pe)\n", + ERR_PTR(ret)); /* * Spec says that if the value read is 0 the default granularity should * be used instead. @@ -515,7 +517,8 @@ static void _psr_compute_su_granularity(struct intel_dp *intel_dp, ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_PSR2_SU_Y_GRANULARITY, &y); if (ret < 0) { drm_dbg_kms(display->drm, - "Unable to read selective update y granularity\n"); + "Unable to read selective update y granularity (%pe)\n", + ERR_PTR(ret)); y = 4; } if (y == 0) @@ -3835,7 +3838,7 @@ static void psr_capability_changed_check(struct intel_dp *intel_dp) ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_PSR_ESI, &val); if (ret < 0) { - drm_err(display->drm, "Error reading DP_PSR_ESI\n"); + drm_err(display->drm, "Error reading DP_PSR_ESI (%pe)\n", ERR_PTR(ret)); return; } From f23399dbf2d131fac6824e6ae503c2a80eaff908 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 23 Sep 2026 13:15:20 +0200 Subject: [PATCH 81/98] drm/i915/gt: Use spin_lock_irq() instead of local_irq_disable() + spin_lock() execlists_dequeue() is invoked from a function which uses local_irq_disable() to disable interrupts so the spin_lock() behaves like spin_lock_irq(). This breaks PREEMPT_RT because local_irq_disable() + spin_lock() is not the same as spin_lock_irq(). execlists_dequeue_irq() and execlists_dequeue() has each one caller only. If intel_engine_cs::active::lock is acquired and released with the _irq suffix then it behaves almost as if execlists_dequeue() would be invoked with disabled interrupts. The difference is the last part of the function which is then invoked with enabled interrupts. I can't tell if this makes a difference. From looking at it, it might work to move the last unlock at the end of the function as I didn't find anything that would acquire the lock again. Reported-by: Clark Williams Signed-off-by: Sebastian Andrzej Siewior Reviewed-by: Maarten Lankhorst Link: https://patch.msgid.link/20260923111518.310430-9-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- .../drm/i915/gt/intel_execlists_submission.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index e693b0c9d2a3..841f71932675 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -1300,7 +1300,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) * and context switches) submission. */ - spin_lock(&sched_engine->lock); + spin_lock_irq(&sched_engine->lock); /* * If the queue is higher priority than the last @@ -1400,7 +1400,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) * Even if ELSP[1] is occupied and not worthy * of timeslices, our queue might be. */ - spin_unlock(&sched_engine->lock); + spin_unlock_irq(&sched_engine->lock); return; } } @@ -1426,7 +1426,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) if (last && !can_merge_rq(last, rq)) { spin_unlock(&ve->base.sched_engine->lock); - spin_unlock(&engine->sched_engine->lock); + spin_unlock_irq(&engine->sched_engine->lock); return; /* leave this for another sibling */ } @@ -1588,7 +1588,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) */ sched_engine->queue_priority_hint = queue_prio(sched_engine); i915_sched_engine_reset_on_empty(sched_engine); - spin_unlock(&sched_engine->lock); + spin_unlock_irq(&sched_engine->lock); /* * We can skip poking the HW if we ended up with exactly the same set @@ -1614,13 +1614,6 @@ static void execlists_dequeue(struct intel_engine_cs *engine) } } -static void execlists_dequeue_irq(struct intel_engine_cs *engine) -{ - local_irq_disable(); /* Suspend interrupts across request submission */ - execlists_dequeue(engine); - local_irq_enable(); /* flush irq_work (e.g. breadcrumb enabling) */ -} - static void clear_ports(struct i915_request **ports, int count) { memset_p((void **)ports, NULL, count); @@ -2475,7 +2468,7 @@ static void execlists_submission_tasklet(struct tasklet_struct *t) } if (!engine->execlists.pending[0]) { - execlists_dequeue_irq(engine); + execlists_dequeue(engine); start_timeslice(engine); } From a0cd18290718c770cd635b7f6b6516f13c442be4 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 23 Sep 2026 13:15:21 +0200 Subject: [PATCH 82/98] drm/i915: Drop the irqs_disabled() check The !irqs_disabled() check triggers on PREEMPT_RT even with i915_sched_engine::lock acquired. The reason is the lock is transformed into a sleeping lock on PREEMPT_RT and does not disable interrupts. There is no need to check for disabled interrupts. The lockdep annotation below already check if the lock has been acquired by the caller and will yell if the interrupts are not disabled. Remove the !irqs_disabled() check. Reported-by: Maarten Lankhorst Acked-by: Tvrtko Ursulin Signed-off-by: Sebastian Andrzej Siewior Reviewed-by: Rodrigo Vivi Link: https://patch.msgid.link/20260923111518.310430-10-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/i915/i915_request.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index d2c7b1090df0..f66f8efc7062 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -610,7 +610,6 @@ bool __i915_request_submit(struct i915_request *request) RQ_TRACE(request, "\n"); - GEM_BUG_ON(!irqs_disabled()); lockdep_assert_held(&engine->sched_engine->lock); /* @@ -719,7 +718,6 @@ void __i915_request_unsubmit(struct i915_request *request) */ RQ_TRACE(request, "\n"); - GEM_BUG_ON(!irqs_disabled()); lockdep_assert_held(&engine->sched_engine->lock); /* From 7890c29092c8ed55a58f84f9f0cd71ac730db1af Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 23 Sep 2026 13:15:22 +0200 Subject: [PATCH 83/98] drm/i915/guc: Consider also RCU depth in busy loop. intel_guc_send_busy_loop() looks at in_atomic() and irqs_disabled() to decide if it should busy-spin while waiting or if it may sleep. Both checks will report false on PREEMPT_RT if sleeping spinlocks are acquired leading to RCU splats while the function sleeps. Check also if RCU has been disabled. Reported-by: "John B. Wyatt IV" Reviewed-by: Rodrigo Vivi Signed-off-by: Sebastian Andrzej Siewior Link: https://patch.msgid.link/20260923111518.310430-11-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/i915/gt/uc/intel_guc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 053780f562c1..b25fa8f4dc4b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -362,7 +362,7 @@ static inline int intel_guc_send_busy_loop(struct intel_guc *guc, { int err; unsigned int sleep_period_ms = 1; - bool not_atomic = !in_atomic() && !irqs_disabled(); + bool not_atomic = !in_atomic() && !irqs_disabled() && !rcu_preempt_depth(); /* * FIXME: Have caller pass in if we are in an atomic context to avoid From 70e3cf8a64413d7a4f617c2f95d369e7e501376a Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 23 Sep 2026 13:15:23 +0200 Subject: [PATCH 84/98] drm/i915/gt: Fix selftests on PREEMPT_RT The engine->busyness() callbacks called from the selftests are on PREEMPT_RT not safe with preemption disabled, because all spinlock_t locks becomes sleeping locks on PREEMPT_RT and must not be acquired with disabled preemption. This is also a problem for perf events, where we disable the busyness events on PREEMPT_RT, as they're run from hardirq context. Previous attempts to fix this failed, so convert the selftest code to read engine->busyness() with migrate_disable() instead of preempt_disable() to prevent selftest failures on PREEMPT_RT. By disabling migration, we prevent moving the selftests between cores, and should decrease the jitter in both the idle cases and busy cases, compared to no prevention at all. Since interrupts were not disabled, some jitter may still occur, but it should hopefully be less with migration disabled. Reviewed-by: Sebastian Andrzej Siewior Link: https://patch.msgid.link/20260923111518.310430-12-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/i915/gt/selftest_engine_pm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_pm.c b/drivers/gpu/drm/i915/gt/selftest_engine_pm.c index 10e556a7eac4..c1eff9edd8a5 100644 --- a/drivers/gpu/drm/i915/gt/selftest_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/selftest_engine_pm.c @@ -277,11 +277,11 @@ static int live_engine_busy_stats(void *arg) st_engine_heartbeat_disable(engine); ENGINE_TRACE(engine, "measuring idle time\n"); - preempt_disable(); + migrate_disable(); de = intel_engine_get_busy_time(engine, &t[0]); udelay(100); de = ktime_sub(intel_engine_get_busy_time(engine, &t[1]), de); - preempt_enable(); + migrate_enable(); dt = ktime_sub(t[1], t[0]); if (de < 0 || de > 10) { pr_err("%s: reported %lldns [%d%%] busyness while sleeping [for %lldns]\n", @@ -316,11 +316,11 @@ static int live_engine_busy_stats(void *arg) } ENGINE_TRACE(engine, "measuring busy time\n"); - preempt_disable(); + migrate_disable(); de = intel_engine_get_busy_time(engine, &t[0]); mdelay(100); de = ktime_sub(intel_engine_get_busy_time(engine, &t[1]), de); - preempt_enable(); + migrate_enable(); dt = ktime_sub(t[1], t[0]); if (100 * de < 95 * dt || 95 * de > 100 * dt) { pr_err("%s: reported %lldns [%d%%] busyness while spinning [for %lldns]\n", From 031f0cde234dc0ee4a1b8360a407551fe30020e1 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 23 Sep 2026 13:15:24 +0200 Subject: [PATCH 85/98] drm/i915/gt: Set stop_timeout() correctly on PREEMPT-RT Also check if RCU is disabled for PREEMPT-RT, which is the case when local_bh_disable() is called. Reviewed-by: Rodrigo Vivi Reviewed-by: Sebastian Andrzej Siewior Link: https://patch.msgid.link/20260923111518.310430-13-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index c0fd349a4600..9dd9665128ca 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -1607,7 +1607,7 @@ u64 intel_engine_get_last_batch_head(const struct intel_engine_cs *engine) static unsigned long stop_timeout(const struct intel_engine_cs *engine) { - if (in_atomic() || irqs_disabled()) /* inside atomic preempt-reset? */ + if (in_atomic() || irqs_disabled() || rcu_preempt_depth()) /* inside atomic preempt-reset? */ return 0; /* From a8c17ccf9eb85c2b60376bb6ab98d75f897073b9 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 23 Sep 2026 13:15:25 +0200 Subject: [PATCH 86/98] drm/i915: Use sleeping selftests for igt_atomic on PREEMPT_RT This makes the i915 selftests slightly happier, especially related to GPU reset. All of the i915 code that used to run in BH's, IRQ's, etc is converted to preemptible code when compiled with PREEMPT_RT, so adding coverage for those situations would require. This is a better approach than trying to convert all locks in i915 from spinlock_t to raw_spinlock_t just to increase test coverage for situations that no longer happen. Reviewed-by: Sebastian Andrzej Siewior Link: https://patch.msgid.link/20260923111518.310430-14-dev@lankhorst.se Signed-off-by: Maarten Lankhorst --- drivers/gpu/drm/i915/selftests/igt_atomic.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/selftests/igt_atomic.c b/drivers/gpu/drm/i915/selftests/igt_atomic.c index fb506b699095..8ae39cf570b7 100644 --- a/drivers/gpu/drm/i915/selftests/igt_atomic.c +++ b/drivers/gpu/drm/i915/selftests/igt_atomic.c @@ -39,7 +39,14 @@ static void __hardirq_end(void) local_irq_enable(); } +static void __maybe_unused __nop(void) +{} + const struct igt_atomic_section igt_atomic_phases[] = { +#if IS_ENABLED(CONFIG_PREEMPT_RT) + { "sleeping", __nop, __nop }, + { }, +#endif { "preempt", __preempt_begin, __preempt_end }, { "softirq", __softirq_begin, __softirq_end }, { "hardirq", __hardirq_begin, __hardirq_end }, From c9e608d1247cd4c286a54d7f26188c41e8f0a6c2 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Thu, 24 Sep 2026 07:49:50 +0530 Subject: [PATCH 87/98] drm/i915/display: Update the CMN_SDP_TL in fastset path Commit bfa597238073 ("drm/i915/dip: Enable Common SDP Transmission line") enabled the CMN_SDP_TL for the modeset path, but missed to add it to the fastset path. Since dip.cmn_sdp_tl is already skipped from the strict pipe-config comparison during fastsets, it was always intended to get updated without full modeset, but the update to the register was missed. During a fastset, if CMN_SDP_TL changes, update the register similar to the EMP_AS_SDP_TL, which gets updated in intel_vrr_set_transcoder_timings(). v2: Update cmn_sdp_changed() to also compare gmp_sdp_tl, pps_sdp_tl and vsc_ext_sdp_tl, not just cmn_sdp_tl. (Sashiko) Fixes: bfa597238073 ("drm/i915/dip: Enable Common SDP Transmission line") Cc: Suraj Kandpal Signed-off-by: Ankit Nautiyal Reviewed-by: Suraj Kandpal Link: https://patch.msgid.link/20260924021950.350207-1-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e3e0d2f8faef..d5d4453f283b 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -69,6 +69,7 @@ #include "intel_cx0_phy.h" #include "intel_ddi.h" #include "intel_de.h" +#include "intel_dip.h" #include "intel_display_driver.h" #include "intel_display_power.h" #include "intel_display_regs.h" @@ -999,6 +1000,15 @@ static bool cmrr_params_changed(const struct intel_crtc_state *old_crtc_state, old_crtc_state->vrr.cmrr.cmrr_n != new_crtc_state->vrr.cmrr.cmrr_n; } +static bool cmn_sdp_changed(const struct intel_crtc_state *old_crtc_state, + const struct intel_crtc_state *new_crtc_state) +{ + return old_crtc_state->dip.cmn_sdp_tl != new_crtc_state->dip.cmn_sdp_tl || + old_crtc_state->dip.gmp_sdp_tl != new_crtc_state->dip.gmp_sdp_tl || + old_crtc_state->dip.pps_sdp_tl != new_crtc_state->dip.pps_sdp_tl || + old_crtc_state->dip.vsc_ext_sdp_tl != new_crtc_state->dip.vsc_ext_sdp_tl; +} + static bool intel_crtc_vrr_enabling(struct intel_atomic_state *state, struct intel_crtc *crtc) { @@ -6924,6 +6934,9 @@ static void intel_pre_update_crtc(struct intel_atomic_state *state, if (vrr_params_changed(old_crtc_state, new_crtc_state) || cmrr_params_changed(old_crtc_state, new_crtc_state)) intel_vrr_set_transcoder_timings(new_crtc_state); + + if (cmn_sdp_changed(old_crtc_state, new_crtc_state)) + intel_dip_cmn_sdp_transmission_line_enable(new_crtc_state); } intel_fbc_update(state, crtc); From 4e8bc6b5bbe6305e530e2f024cf983506d72f657 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 18 Sep 2026 12:37:25 +0200 Subject: [PATCH 88/98] drm/i915: Use %p for pointer formatting Commit 2563a4524febe ("drm/i915: restrict kernel address leak in debugfs") introduced the %pK modifier in order not to leak kernel pointer. Since commit ad67b74d2469d ("printk: hash addresses printed with %p") pointers are hashed by default and the behaviour can be controller by `hash_pointers' boot argument. The policy on %p is to not introduce new ones. Keeping the %p allows to assign an id to the object. Removing %pK makes it possible to remove its handling from the library. Use %p instead %pK to allow debugging if needed. Signed-off-by: Sebastian Andrzej Siewior Reviewed-by: Andi Shyti Signed-off-by: Andi Shyti Link: https://patch.msgid.link/20260918103725.cfYzL1Wt@linutronix.de --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index a3e27f9e4f47..93ba7369ba6e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -179,7 +179,7 @@ i915_debugfs_describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) struct i915_vma *vma; int pin_count = 0; - seq_printf(m, "%pK: %c%c%c %8zdKiB %02x %02x %s%s%s", + seq_printf(m, "%p: %c%c%c %8zdKiB %02x %02x %s%s%s", &obj->base, get_tiling_flag(obj), get_global_flag(obj), From 042b855e19f336c8526c4cf2a107c5279735a4a0 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 30 Sep 2026 17:59:57 +0300 Subject: [PATCH 89/98] drm/intel: move i915_gtt_view_types.h to include/drm/intel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The i915 and xe drivers share i915_gtt_view_types.h from i915 source. Move it to include/drm/intel/gtt_view_types.h. Remove the i915 compat header. v2: Keep comment for header guard #endif (Ville) Reviewed-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/174f7e26be755b29a1286bf8b8ef0342dcc083a6.1790780340.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_types.h | 2 +- drivers/gpu/drm/i915/i915_vma_types.h | 3 +-- .../gpu/drm/xe/compat-i915-headers/i915_gtt_view_types.h | 7 ------- drivers/gpu/drm/xe/display/xe_fb_pin.c | 4 +--- .../drm/intel/gtt_view_types.h | 6 +++--- 5 files changed, 6 insertions(+), 16 deletions(-) delete mode 100644 drivers/gpu/drm/xe/compat-i915-headers/i915_gtt_view_types.h rename drivers/gpu/drm/i915/i915_gtt_view_types.h => include/drm/intel/gtt_view_types.h (92%) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 79f30660c2b6..fe3b6bec4817 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -41,10 +41,10 @@ #include #include #include +#include #include #include -#include "i915_gtt_view_types.h" #include "intel_bios.h" #include "intel_display.h" #include "intel_display_conversion.h" diff --git a/drivers/gpu/drm/i915/i915_vma_types.h b/drivers/gpu/drm/i915/i915_vma_types.h index a499a3bea874..83fe02833b5e 100644 --- a/drivers/gpu/drm/i915/i915_vma_types.h +++ b/drivers/gpu/drm/i915/i915_vma_types.h @@ -29,11 +29,10 @@ #include #include +#include #include "gem/i915_gem_object_types.h" -#include "i915_gtt_view_types.h" - /** * DOC: Global GTT views * diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_gtt_view_types.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_gtt_view_types.h deleted file mode 100644 index b261910cd6f9..000000000000 --- a/drivers/gpu/drm/xe/compat-i915-headers/i915_gtt_view_types.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* Copyright © 2025 Intel Corporation */ - -#include "../../i915/i915_gtt_view_types.h" - -/* Partial view not supported in xe, fail build if used. */ -#define I915_GTT_VIEW_PARTIAL diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index 73469ea5f333..ce2601069e7d 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -4,11 +4,9 @@ */ #include +#include #include -/* FIXME move the types to parent interface? */ -#include "i915_gtt_view_types.h" - /* FIXME move intel_remapped_info_size() & co. to parent interface? */ #include "intel_fb.h" diff --git a/drivers/gpu/drm/i915/i915_gtt_view_types.h b/include/drm/intel/gtt_view_types.h similarity index 92% rename from drivers/gpu/drm/i915/i915_gtt_view_types.h rename to include/drm/intel/gtt_view_types.h index 9c4f38db32ff..5770fc53b823 100644 --- a/drivers/gpu/drm/i915/i915_gtt_view_types.h +++ b/include/drm/intel/gtt_view_types.h @@ -1,8 +1,8 @@ /* SPDX-License-Identifier: MIT */ /* Copyright © 2025 Intel Corporation */ -#ifndef __I915_GTT_VIEW_TYPES_H__ -#define __I915_GTT_VIEW_TYPES_H__ +#ifndef __DRM_INTEL_GTT_VIEW_TYPES_H__ +#define __DRM_INTEL_GTT_VIEW_TYPES_H__ #include @@ -71,4 +71,4 @@ static inline bool i915_gtt_view_is_rotated(const struct i915_gtt_view *view) return view->type == I915_GTT_VIEW_ROTATED; } -#endif /* __I915_GTT_VIEW_TYPES_H__ */ +#endif /* __DRM_INTEL_GTT_VIEW_TYPES_H__ */ From fe05df7a540aaf940d294cad137b0ae8bb578387 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 30 Sep 2026 17:59:58 +0300 Subject: [PATCH 90/98] drm/intel: rename i915_gtt_view_is_*() helpers to intel_gtt_view_is_*() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the i915_gtt_view_is_*() helpers less i915 specific, and rename them intel_gtt_view_is_*(). $ sed -i 's/i915_gtt_view_is_/intel_gtt_view_is_/g' -- $(git grep -l i915_gtt_view_is_) Reviewed-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/8230339be1738a1f7c87047f2516dfa66b03d9aa.1790780340.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fb.c | 8 ++++---- include/drm/intel/gtt_view_types.h | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index c3e4c3f6d8cf..63b7644c5659 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -1289,7 +1289,7 @@ bool intel_plane_uses_fence(const struct intel_plane_state *plane_state) return intel_plane_needs_fence(display) || (plane->fbc && !plane_state->no_fbc_reason && - i915_gtt_view_is_normal(&plane_state->view.gtt)); + intel_gtt_view_is_normal(&plane_state->view.gtt)); } static int intel_fb_pitch(const struct intel_framebuffer *fb, int color_plane, unsigned int rotation) @@ -1511,7 +1511,7 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p plane_view_height_tiles(fb, color_plane, dims, y)); } - if (i915_gtt_view_is_rotated(&view->gtt)) { + if (intel_gtt_view_is_rotated(&view->gtt)) { drm_WARN_ON(display->drm, remap_info->linear); check_array_bounds(display, view->gtt.rotated.plane, color_plane); @@ -1536,7 +1536,7 @@ static u32 calc_plane_remap_info(const struct intel_framebuffer *fb, int color_p /* rotate the tile dimensions to match the GTT view */ swap(tile_width, tile_height); } else { - drm_WARN_ON(display->drm, !i915_gtt_view_is_remapped(&view->gtt)); + drm_WARN_ON(display->drm, !intel_gtt_view_is_remapped(&view->gtt)); check_array_bounds(display, view->gtt.remapped.plane, color_plane); @@ -1638,7 +1638,7 @@ static void intel_fb_view_init(struct intel_display *display, memset(view, 0, sizeof(*view)); view->gtt.type = view_type; - if (i915_gtt_view_is_remapped(&view->gtt) && + if (intel_gtt_view_is_remapped(&view->gtt) && intel_fb_needs_pot_stride_remap(fb)) view->gtt.remapped.plane_alignment = SZ_2M / PAGE_SIZE; } diff --git a/include/drm/intel/gtt_view_types.h b/include/drm/intel/gtt_view_types.h index 5770fc53b823..61d2289a8921 100644 --- a/include/drm/intel/gtt_view_types.h +++ b/include/drm/intel/gtt_view_types.h @@ -56,17 +56,17 @@ struct i915_gtt_view { }; }; -static inline bool i915_gtt_view_is_normal(const struct i915_gtt_view *view) +static inline bool intel_gtt_view_is_normal(const struct i915_gtt_view *view) { return view->type == I915_GTT_VIEW_NORMAL; } -static inline bool i915_gtt_view_is_remapped(const struct i915_gtt_view *view) +static inline bool intel_gtt_view_is_remapped(const struct i915_gtt_view *view) { return view->type == I915_GTT_VIEW_REMAPPED; } -static inline bool i915_gtt_view_is_rotated(const struct i915_gtt_view *view) +static inline bool intel_gtt_view_is_rotated(const struct i915_gtt_view *view) { return view->type == I915_GTT_VIEW_ROTATED; } From 468a755f203ea2f364452f7f1e009ffe8484a6a3 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 30 Sep 2026 17:59:59 +0300 Subject: [PATCH 91/98] drm/intel: rename i915_gtt_view* struct/enum to intel_gtt_view* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make enum i915_gtt_view_type and struct i915_gtt_view less i915 specific, and rename them enum intel_gtt_view_type and struct intel_gtt_view, respectively. $ sed -i 's/i915_gtt_view/intel_gtt_view/g' -- $(git grep -l i915_gtt_view) Reviewed-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/4ca4ad3d11b0f8167a54d69d6eef0c8a78218c53.1790780340.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- .../gpu/drm/i915/display/intel_display_types.h | 2 +- drivers/gpu/drm/i915/display/intel_fb.c | 2 +- drivers/gpu/drm/i915/display/intel_parent.c | 4 ++-- drivers/gpu/drm/i915/display/intel_parent.h | 6 +++--- drivers/gpu/drm/i915/gem/i915_gem_domain.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_mman.c | 6 +++--- drivers/gpu/drm/i915/gem/i915_gem_object.h | 2 +- .../gpu/drm/i915/gem/selftests/i915_gem_mman.c | 4 ++-- drivers/gpu/drm/i915/i915_gem.c | 4 ++-- drivers/gpu/drm/i915/i915_gem.h | 6 +++--- drivers/gpu/drm/i915/i915_vma.c | 8 ++++---- drivers/gpu/drm/i915/i915_vma.h | 4 ++-- drivers/gpu/drm/i915/i915_vma_types.h | 16 ++++++++-------- drivers/gpu/drm/i915/selftests/i915_vma.c | 16 ++++++++-------- drivers/gpu/drm/xe/display/xe_fb_pin.c | 10 +++++----- include/drm/intel/display_parent_interface.h | 8 ++++---- include/drm/intel/gtt_view_types.h | 12 ++++++------ 17 files changed, 56 insertions(+), 56 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index fe3b6bec4817..0e3083e852d5 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -111,7 +111,7 @@ struct intel_fb_view { * In the normal view the FB object's backing store sg list is used * directly and hence the remap information here is not used. */ - struct i915_gtt_view gtt; + struct intel_gtt_view gtt; /* * The GTT view (gtt.type) specific information for each FB color diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 63b7644c5659..d1b4efa08bcc 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -1632,7 +1632,7 @@ calc_plane_normal_size(const struct intel_framebuffer *fb, int color_plane, static void intel_fb_view_init(struct intel_display *display, struct intel_fb_view *view, - enum i915_gtt_view_type view_type, + enum intel_gtt_view_type view_type, const struct intel_framebuffer *fb) { memset(view, 0, sizeof(*view)); diff --git a/drivers/gpu/drm/i915/display/intel_parent.c b/drivers/gpu/drm/i915/display/intel_parent.c index 99cebb17763a..ed3e21b0a927 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.c +++ b/drivers/gpu/drm/i915/display/intel_parent.c @@ -94,9 +94,9 @@ void intel_parent_fb_pin_dpt_unpin(struct intel_display *display, struct i915_vma *intel_parent_fb_pin_reuse_vma(struct intel_display *display, struct i915_vma *old_ggtt_vma, struct drm_gem_object *old_obj, - const struct i915_gtt_view *old_view, + const struct intel_gtt_view *old_view, struct drm_gem_object *new_obj, - const struct i915_gtt_view *new_view, + const struct intel_gtt_view *new_view, u32 *out_offset) { if (!display->parent->fb_pin->reuse_vma) diff --git a/drivers/gpu/drm/i915/display/intel_parent.h b/drivers/gpu/drm/i915/display/intel_parent.h index cc4a58f63166..923cb6464a98 100644 --- a/drivers/gpu/drm/i915/display/intel_parent.h +++ b/drivers/gpu/drm/i915/display/intel_parent.h @@ -11,12 +11,12 @@ struct dma_fence; struct drm_file; struct drm_gem_object; struct drm_scanout_buffer; -struct i915_gtt_view; struct i915_vma; struct intel_display; struct intel_dpt; struct intel_fb_pin_params; struct intel_frontbuffer; +struct intel_gtt_view; struct intel_hdcp_gsc_context; struct intel_panic; struct intel_stolen_node; @@ -53,9 +53,9 @@ void intel_parent_fb_pin_dpt_unpin(struct intel_display *display, struct i915_vma *intel_parent_fb_pin_reuse_vma(struct intel_display *display, struct i915_vma *old_ggtt_vma, struct drm_gem_object *old_obj, - const struct i915_gtt_view *old_view, + const struct intel_gtt_view *old_view, struct drm_gem_object *new_obj, - const struct i915_gtt_view *new_view, + const struct intel_gtt_view *new_view, u32 *out_offset); void intel_parent_fb_pin_get_map(struct intel_display *display, struct i915_vma *vma, struct iosys_map *map); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index b7297c0a3a48..0cb41704e54e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -421,7 +421,7 @@ struct i915_vma * i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, struct i915_gem_ww_ctx *ww, u32 alignment, unsigned int guard, - const struct i915_gtt_view *view, + const struct intel_gtt_view *view, unsigned int flags) { struct drm_i915_private *i915 = to_i915(obj->base.dev); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index 9ca90c1bb5b4..ee8fbbcbb5fe 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -196,12 +196,12 @@ int i915_gem_mmap_gtt_version(void) return 5; } -static inline struct i915_gtt_view +static inline struct intel_gtt_view compute_partial_view(const struct drm_i915_gem_object *obj, pgoff_t page_offset, unsigned int chunk) { - struct i915_gtt_view view; + struct intel_gtt_view view; if (i915_gem_object_is_tiled(obj)) chunk = roundup(chunk, tile_row_pages(obj) ?: 1); @@ -391,7 +391,7 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf) PIN_NOEVICT); if (IS_ERR(vma) && vma != ERR_PTR(-EDEADLK)) { /* Use a partial view if it is bigger than available space */ - struct i915_gtt_view view = + struct intel_gtt_view view = compute_partial_view(obj, page_offset, MIN_CHUNK_PAGES); unsigned int flags; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index 2c5d20e4dbaf..a2f4b6758a65 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -776,7 +776,7 @@ struct i915_vma * __must_check i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, struct i915_gem_ww_ctx *ww, u32 alignment, unsigned int guard, - const struct i915_gtt_view *view, + const struct intel_gtt_view *view, unsigned int flags); void i915_gem_object_make_unshrinkable(struct drm_i915_gem_object *obj); diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c index d01acfb7d93d..4d49fd6c15e3 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c @@ -97,7 +97,7 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj, { const unsigned long npages = obj->base.size / PAGE_SIZE; struct drm_i915_private *i915 = to_i915(obj->base.dev); - struct i915_gtt_view view; + struct intel_gtt_view view; struct i915_vma *vma; unsigned long offset; unsigned long page; @@ -214,7 +214,7 @@ static int check_partial_mappings(struct drm_i915_gem_object *obj, } for_each_prime_number_from(page, 1, npages) { - struct i915_gtt_view view = + struct intel_gtt_view view = compute_partial_view(obj, page, MIN_CHUNK_PAGES); unsigned long offset; u32 __iomem *io; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a432daf8038a..62987ae59a50 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -902,7 +902,7 @@ static void discard_ggtt_vma(struct i915_vma *vma) struct i915_vma * i915_gem_object_ggtt_pin_ww(struct drm_i915_gem_object *obj, struct i915_gem_ww_ctx *ww, - const struct i915_gtt_view *view, + const struct intel_gtt_view *view, u64 size, u64 alignment, u64 flags) { struct drm_i915_private *i915 = to_i915(obj->base.dev); @@ -1004,7 +1004,7 @@ i915_gem_object_ggtt_pin_ww(struct drm_i915_gem_object *obj, struct i915_vma * __must_check i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, - const struct i915_gtt_view *view, + const struct intel_gtt_view *view, u64 size, u64 alignment, u64 flags) { struct i915_gem_ww_ctx ww; diff --git a/drivers/gpu/drm/i915/i915_gem.h b/drivers/gpu/drm/i915/i915_gem.h index 20b3cb29cfff..80d9758fe684 100644 --- a/drivers/gpu/drm/i915/i915_gem.h +++ b/drivers/gpu/drm/i915/i915_gem.h @@ -36,8 +36,8 @@ struct drm_file; struct drm_i915_gem_object; struct drm_i915_private; struct i915_gem_ww_ctx; -struct i915_gtt_view; struct i915_vma; +struct intel_gtt_view; #define I915_GEM_GPU_DOMAINS \ (I915_GEM_DOMAIN_RENDER | \ @@ -55,12 +55,12 @@ void i915_gem_drain_workqueue(struct drm_i915_private *i915); struct i915_vma * __must_check i915_gem_object_ggtt_pin_ww(struct drm_i915_gem_object *obj, struct i915_gem_ww_ctx *ww, - const struct i915_gtt_view *view, + const struct intel_gtt_view *view, u64 size, u64 alignment, u64 flags); struct i915_vma * __must_check i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, - const struct i915_gtt_view *view, + const struct intel_gtt_view *view, u64 size, u64 alignment, u64 flags); int i915_gem_object_unbind(struct drm_i915_gem_object *obj, diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index afc192d9931b..61ddfa5d2895 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -147,7 +147,7 @@ static void __i915_vma_retire(struct i915_active *ref) static struct i915_vma * vma_create(struct drm_i915_gem_object *obj, struct i915_address_space *vm, - const struct i915_gtt_view *view) + const struct intel_gtt_view *view) { struct i915_vma *pos = ERR_PTR(-E2BIG); struct i915_vma *vma; @@ -286,7 +286,7 @@ vma_create(struct drm_i915_gem_object *obj, static struct i915_vma * i915_vma_lookup(struct drm_i915_gem_object *obj, struct i915_address_space *vm, - const struct i915_gtt_view *view) + const struct intel_gtt_view *view) { struct rb_node *rb; @@ -324,7 +324,7 @@ i915_vma_lookup(struct drm_i915_gem_object *obj, struct i915_vma * i915_vma_instance(struct drm_i915_gem_object *obj, struct i915_address_space *vm, - const struct i915_gtt_view *view) + const struct intel_gtt_view *view) { struct i915_vma *vma; @@ -1267,7 +1267,7 @@ intel_remap_pages(struct intel_remapped_info *rem_info, } static noinline struct sg_table * -intel_partial_pages(const struct i915_gtt_view *view, +intel_partial_pages(const struct intel_gtt_view *view, struct drm_i915_gem_object *obj) { struct sg_table *st; diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h index 892306ab935d..a8a89bb0270c 100644 --- a/drivers/gpu/drm/i915/i915_vma.h +++ b/drivers/gpu/drm/i915/i915_vma.h @@ -43,7 +43,7 @@ struct i915_vma * i915_vma_instance(struct drm_i915_gem_object *obj, struct i915_address_space *vm, - const struct i915_gtt_view *view); + const struct intel_gtt_view *view); void i915_vma_unpin_and_release(struct i915_vma **p_vma, unsigned int flags); #define I915_VMA_RELEASE_MAP BIT(0) @@ -207,7 +207,7 @@ static inline void i915_vma_put(struct i915_vma *vma) static inline long i915_vma_compare(struct i915_vma *vma, struct i915_address_space *vm, - const struct i915_gtt_view *view) + const struct intel_gtt_view *view) { ptrdiff_t cmp; diff --git a/drivers/gpu/drm/i915/i915_vma_types.h b/drivers/gpu/drm/i915/i915_vma_types.h index 83fe02833b5e..8815421eaefb 100644 --- a/drivers/gpu/drm/i915/i915_vma_types.h +++ b/drivers/gpu/drm/i915/i915_vma_types.h @@ -66,22 +66,22 @@ * Implementation and usage * * GGTT views are implemented using VMAs and are distinguished via enum - * i915_gtt_view_type and struct i915_gtt_view. + * intel_gtt_view_type and struct intel_gtt_view. * * A new flavour of core GEM functions which work with GGTT bound objects were * added with the _ggtt_ infix, and sometimes with _view postfix to avoid - * renaming in large amounts of code. They take the struct i915_gtt_view + * renaming in large amounts of code. They take the struct intel_gtt_view * parameter encapsulating all metadata required to implement a view. * * As a helper for callers which are only interested in the normal view, - * globally const i915_gtt_view_normal singleton instance exists. All old core + * globally const intel_gtt_view_normal singleton instance exists. All old core * GEM API functions, the ones not taking the view parameter, are operating on, * or with the normal GGTT view. * * Code wanting to add or use a new GGTT view needs to: * * 1. Add a new enum with a suitable name. - * 2. Extend the metadata in the i915_gtt_view structure if required. + * 2. Extend the metadata in the intel_gtt_view structure if required. * 3. Add support to i915_get_vma_pages(). * * New views are required to build a scatter-gather table from within the @@ -89,7 +89,7 @@ * exists for the lifetime of an VMA. * * Core API is designed to have copy semantics which means that passed in - * struct i915_gtt_view does not need to be persistent (left around after + * struct intel_gtt_view does not need to be persistent (left around after * calling the core API functions). * */ @@ -111,7 +111,7 @@ static inline void assert_i915_gem_gtt_types(void) /* As we encode the size of each branch inside the union into its type, * we have to be careful that each branch has a unique size. */ - switch ((enum i915_gtt_view_type)0) { + switch ((enum intel_gtt_view_type)0) { case I915_GTT_VIEW_NORMAL: case I915_GTT_VIEW_PARTIAL: case I915_GTT_VIEW_ROTATED: @@ -230,11 +230,11 @@ struct i915_vma { /** * Support different GGTT views into the same object. * This means there can be multiple VMA mappings per object and per VM. - * i915_gtt_view_type is used to distinguish between those entries. + * intel_gtt_view_type is used to distinguish between those entries. * The default one of zero (I915_GTT_VIEW_NORMAL) is default and also * assumed in GEM functions which take no ggtt view parameter. */ - struct i915_gtt_view gtt_view; + struct intel_gtt_view gtt_view; /** This object's place on the active/inactive lists */ struct list_head vm_link; diff --git a/drivers/gpu/drm/i915/selftests/i915_vma.c b/drivers/gpu/drm/i915/selftests/i915_vma.c index 7c4111e60f2e..b16297a6a4e8 100644 --- a/drivers/gpu/drm/i915/selftests/i915_vma.c +++ b/drivers/gpu/drm/i915/selftests/i915_vma.c @@ -63,7 +63,7 @@ static bool assert_vma(struct i915_vma *vma, static struct i915_vma * checked_vma_instance(struct drm_i915_gem_object *obj, struct i915_address_space *vm, - const struct i915_gtt_view *view) + const struct intel_gtt_view *view) { struct i915_vma *vma; bool ok = true; @@ -533,7 +533,7 @@ assert_remapped(struct drm_i915_gem_object *obj, return sg; } -static unsigned int remapped_size(enum i915_gtt_view_type view_type, +static unsigned int remapped_size(enum intel_gtt_view_type view_type, const struct intel_remapped_plane_info *a, const struct intel_remapped_plane_info *b) { @@ -572,7 +572,7 @@ static int igt_vma_rotate_remap(void *arg) { } }, *a, *b; - enum i915_gtt_view_type types[] = { + enum intel_gtt_view_type types[] = { I915_GTT_VIEW_ROTATED, I915_GTT_VIEW_REMAPPED, 0, @@ -592,7 +592,7 @@ static int igt_vma_rotate_remap(void *arg) for (t = types; *t; t++) { for (a = planes; a->width; a++) { for (b = planes + ARRAY_SIZE(planes); b-- != planes; ) { - struct i915_gtt_view view = { + struct intel_gtt_view view = { .type = *t, .remapped.plane[0] = *a, .remapped.plane[1] = *b, @@ -745,7 +745,7 @@ static bool assert_partial(struct drm_i915_gem_object *obj, } static bool assert_pin(struct i915_vma *vma, - struct i915_gtt_view *view, + struct intel_gtt_view *view, u64 size, const char *name) { @@ -823,7 +823,7 @@ static int igt_vma_partial(void *arg) nvma = 0; for_each_prime_number_from(sz, 1, npages) { for_each_prime_number_from(offset, 0, npages - sz) { - struct i915_gtt_view view; + struct intel_gtt_view view; view.type = I915_GTT_VIEW_PARTIAL; view.partial.offset = offset; @@ -981,7 +981,7 @@ static int igt_vma_remapped_gtt(void *arg) { } }, *p; - enum i915_gtt_view_type types[] = { + enum intel_gtt_view_type types[] = { I915_GTT_VIEW_ROTATED, I915_GTT_VIEW_REMAPPED, 0, @@ -1001,7 +1001,7 @@ static int igt_vma_remapped_gtt(void *arg) for (t = types; *t; t++) { for (p = planes; p->width; p++) { - struct i915_gtt_view view = { + struct intel_gtt_view view = { .type = *t, .rotated.plane[0] = *p, }; diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index ce2601069e7d..1ba2dfc2f574 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -148,7 +148,7 @@ static int __xe_pin_fb_vma_dpt(struct drm_gem_object *obj, struct xe_device *xe = to_xe_device(obj->dev); struct xe_tile *tile0 = xe_device_get_root_tile(xe); struct xe_ggtt *ggtt = tile0->mem.ggtt; - const struct i915_gtt_view *view = pin_params->view; + const struct intel_gtt_view *view = pin_params->view; struct xe_bo *bo = gem_to_xe_bo(obj), *dpt; u32 dpt_size, size = bo->ttm.base.size; @@ -231,7 +231,7 @@ write_ggtt_rotated(struct xe_ggtt *ggtt, u32 *ggtt_ofs, } struct fb_rotate_args { - const struct i915_gtt_view *view; + const struct intel_gtt_view *view; struct xe_bo *bo; }; @@ -256,7 +256,7 @@ static int __xe_pin_fb_vma_ggtt(struct drm_gem_object *obj, const struct intel_fb_pin_params *pin_params, struct i915_vma *vma) { - const struct i915_gtt_view *view = pin_params->view; + const struct intel_gtt_view *view = pin_params->view; struct xe_bo *bo = gem_to_xe_bo(obj); struct xe_device *xe = to_xe_device(obj->dev); struct xe_tile *tile0 = xe_device_get_root_tile(xe); @@ -457,9 +457,9 @@ static void xe_fb_pin_dpt_unpin(struct intel_dpt *dpt, static struct i915_vma * xe_fb_pin_reuse_vma(struct i915_vma *old_ggtt_vma, struct drm_gem_object *old_obj, - const struct i915_gtt_view *old_view, + const struct intel_gtt_view *old_view, struct drm_gem_object *new_obj, - const struct i915_gtt_view *new_view, + const struct intel_gtt_view *new_view, u32 *out_offset) { if (old_ggtt_vma && old_obj == new_obj && diff --git a/include/drm/intel/display_parent_interface.h b/include/drm/intel/display_parent_interface.h index f36134e89cb6..464fb588cb60 100644 --- a/include/drm/intel/display_parent_interface.h +++ b/include/drm/intel/display_parent_interface.h @@ -16,11 +16,11 @@ struct drm_mode_fb_cmd2; struct drm_plane_state; struct drm_scanout_buffer; struct fb_info; -struct i915_gtt_view; struct i915_vma; struct intel_dpt; struct intel_dsb_buffer; struct intel_frontbuffer; +struct intel_gtt_view; struct intel_hdcp_gsc_context; struct intel_initial_plane_config; struct intel_panic; @@ -31,7 +31,7 @@ struct seq_file; struct vm_area_struct; struct intel_fb_pin_params { - const struct i915_gtt_view *view; + const struct intel_gtt_view *view; unsigned int alignment; unsigned int phys_alignment; unsigned int vtd_guard; @@ -101,9 +101,9 @@ struct intel_display_fb_pin_interface { struct i915_vma *ggtt_vma); struct i915_vma *(*reuse_vma)(struct i915_vma *old_ggtt_vma, struct drm_gem_object *old_obj, - const struct i915_gtt_view *old_view, + const struct intel_gtt_view *old_view, struct drm_gem_object *new_obj, - const struct i915_gtt_view *new_view, + const struct intel_gtt_view *new_view, u32 *out_offset); void (*get_map)(struct i915_vma *vma, struct iosys_map *map); }; diff --git a/include/drm/intel/gtt_view_types.h b/include/drm/intel/gtt_view_types.h index 61d2289a8921..3ad2a1026db1 100644 --- a/include/drm/intel/gtt_view_types.h +++ b/include/drm/intel/gtt_view_types.h @@ -39,15 +39,15 @@ struct intel_remapped_info { u32 plane_alignment; } __packed; -enum i915_gtt_view_type { +enum intel_gtt_view_type { I915_GTT_VIEW_NORMAL = 0, I915_GTT_VIEW_ROTATED = sizeof(struct intel_rotation_info), I915_GTT_VIEW_PARTIAL = sizeof(struct intel_partial_info), I915_GTT_VIEW_REMAPPED = sizeof(struct intel_remapped_info), }; -struct i915_gtt_view { - enum i915_gtt_view_type type; +struct intel_gtt_view { + enum intel_gtt_view_type type; union { /* Members need to contain no holes/padding */ struct intel_partial_info partial; @@ -56,17 +56,17 @@ struct i915_gtt_view { }; }; -static inline bool intel_gtt_view_is_normal(const struct i915_gtt_view *view) +static inline bool intel_gtt_view_is_normal(const struct intel_gtt_view *view) { return view->type == I915_GTT_VIEW_NORMAL; } -static inline bool intel_gtt_view_is_remapped(const struct i915_gtt_view *view) +static inline bool intel_gtt_view_is_remapped(const struct intel_gtt_view *view) { return view->type == I915_GTT_VIEW_REMAPPED; } -static inline bool intel_gtt_view_is_rotated(const struct i915_gtt_view *view) +static inline bool intel_gtt_view_is_rotated(const struct intel_gtt_view *view) { return view->type == I915_GTT_VIEW_ROTATED; } From 4a197e47221236f39abe072df065dcab2ce31b69 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 30 Sep 2026 18:00:00 +0300 Subject: [PATCH 92/98] drm/intel: add intel_gtt_view_is_partial() for completeness MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's a helper for all other view types, add one for intel_gtt_view_is_partial() too. Reviewed-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/be522421df45be071ec8f298f4d5b7a49fa6bab8.1790780340.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- include/drm/intel/gtt_view_types.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/drm/intel/gtt_view_types.h b/include/drm/intel/gtt_view_types.h index 3ad2a1026db1..d77292897d64 100644 --- a/include/drm/intel/gtt_view_types.h +++ b/include/drm/intel/gtt_view_types.h @@ -71,4 +71,9 @@ static inline bool intel_gtt_view_is_rotated(const struct intel_gtt_view *view) return view->type == I915_GTT_VIEW_ROTATED; } +static inline bool intel_gtt_view_is_partial(const struct intel_gtt_view *view) +{ + return view->type == I915_GTT_VIEW_PARTIAL; +} + #endif /* __DRM_INTEL_GTT_VIEW_TYPES_H__ */ From 0586e5f135513c4fc7656769b9c15974ca2be59c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 30 Sep 2026 18:00:01 +0300 Subject: [PATCH 93/98] drm/xe/display: use intel_gtt_view_is_*() helpers more MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prefer using the intel_gtt_view_is_*() helpers instead of comparing the view type directly. Reviewed-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/e05bf916d46007f8e655beb6c31748a8f69e09f3.1790780340.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/xe/display/xe_fb_pin.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_fb_pin.c b/drivers/gpu/drm/xe/display/xe_fb_pin.c index 1ba2dfc2f574..ab2be62a7fb4 100644 --- a/drivers/gpu/drm/xe/display/xe_fb_pin.c +++ b/drivers/gpu/drm/xe/display/xe_fb_pin.c @@ -152,9 +152,9 @@ static int __xe_pin_fb_vma_dpt(struct drm_gem_object *obj, struct xe_bo *bo = gem_to_xe_bo(obj), *dpt; u32 dpt_size, size = bo->ttm.base.size; - if (view->type == I915_GTT_VIEW_NORMAL) + if (intel_gtt_view_is_normal(view)) dpt_size = ALIGN(size / XE_PAGE_SIZE * 8, XE_PAGE_SIZE); - else if (view->type == I915_GTT_VIEW_REMAPPED) + else if (intel_gtt_view_is_remapped(view)) dpt_size = ALIGN(intel_remapped_info_size(&view->remapped) * 8, XE_PAGE_SIZE); else @@ -173,7 +173,7 @@ static int __xe_pin_fb_vma_dpt(struct drm_gem_object *obj, if (IS_ERR(dpt)) return PTR_ERR(dpt); - if (view->type == I915_GTT_VIEW_NORMAL) { + if (intel_gtt_view_is_normal(view)) { u64 pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe_cache_pat_idx(xe, XE_CACHE_NONE)); u32 x; @@ -182,7 +182,7 @@ static int __xe_pin_fb_vma_dpt(struct drm_gem_object *obj, iosys_map_wr(&dpt->vmap, x * 8, u64, pte | addr); } - } else if (view->type == I915_GTT_VIEW_REMAPPED) { + } else if (intel_gtt_view_is_remapped(view)) { write_dpt_remapped(bo, &view->remapped, &dpt->vmap); } else { const struct intel_rotation_info *rot_info = &view->rotated; @@ -275,7 +275,7 @@ static int __xe_pin_fb_vma_ggtt(struct drm_gem_object *obj, align = max(align, SZ_64K); /* Fast case, preallocated GGTT view? */ - if (bo->ggtt_node[tile0->id] && view->type == I915_GTT_VIEW_NORMAL) { + if (bo->ggtt_node[tile0->id] && intel_gtt_view_is_normal(view)) { vma->node = bo->ggtt_node[tile0->id]; return 0; } @@ -283,7 +283,7 @@ static int __xe_pin_fb_vma_ggtt(struct drm_gem_object *obj, /* TODO: Consider sharing framebuffer mapping? * embed i915_vma inside intel_framebuffer */ - if (view->type == I915_GTT_VIEW_NORMAL) + if (intel_gtt_view_is_normal(view)) size = xe_bo_size(bo); else /* display uses tiles instead of bytes here, so convert it back.. */ @@ -292,7 +292,7 @@ static int __xe_pin_fb_vma_ggtt(struct drm_gem_object *obj, pte = xe_ggtt_encode_pte_flags(ggtt, bo, xe_cache_pat_idx(xe, XE_CACHE_NONE)); vma->node = xe_ggtt_insert_node_transform(ggtt, bo, pte, ALIGN(size, align), align, - view->type == I915_GTT_VIEW_NORMAL ? + intel_gtt_view_is_normal(view) ? NULL : write_ggtt_rotated_node, &(struct fb_rotate_args){view, bo}); if (IS_ERR(vma->node)) From 1a4aab52c6ea890d0cef2dfc21900715c086da83 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 30 Sep 2026 18:00:02 +0300 Subject: [PATCH 94/98] drm/i915/gem: use intel_gtt_view_is_*() helpers more MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prefer using the intel_gtt_view_is_*() helpers instead of comparing the view type directly. Reviewed-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/1b7f309d0c5c5891caa2ec84c04ce8a4438f1207.1790780340.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/gem/i915_gem_domain.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_mman.c | 2 +- drivers/gpu/drm/i915/i915_gem.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index 0cb41704e54e..9a82ed77ccaf 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -462,7 +462,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, */ vma = ERR_PTR(-ENOSPC); if ((flags & PIN_MAPPABLE) == 0 && - (!view || view->type == I915_GTT_VIEW_NORMAL)) + (!view || intel_gtt_view_is_normal(view))) vma = i915_gem_object_ggtt_pin_ww(obj, ww, view, 0, alignment, flags | PIN_MAPPABLE | PIN_NONBLOCK); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index ee8fbbcbb5fe..055f8d3161da 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -396,7 +396,7 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf) unsigned int flags; flags = PIN_MAPPABLE | PIN_NOSEARCH; - if (view.type == I915_GTT_VIEW_NORMAL) + if (intel_gtt_view_is_normal(&view)) flags |= PIN_NONBLOCK; /* avoid warnings for pinned */ /* diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 62987ae59a50..1209d5f1fc8d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -913,7 +913,7 @@ i915_gem_object_ggtt_pin_ww(struct drm_i915_gem_object *obj, GEM_WARN_ON(!ww); if (flags & PIN_MAPPABLE && - (!view || view->type == I915_GTT_VIEW_NORMAL)) { + (!view || intel_gtt_view_is_normal(view))) { /* * If the required space is larger than the available * aperture, we will not able to find a slot for the From d37667551cfe2828b2530740ebaccce70cec3377 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 30 Sep 2026 18:00:03 +0300 Subject: [PATCH 95/98] drm/i915/vma: use intel_gtt_view_is_*() helpers more MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prefer using the intel_gtt_view_is_*() helpers instead of comparing the view type directly. Reviewed-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/5bc8331cab1d15855b378bd01c76fb0fc4be5c7f.1790780340.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_vma.c | 36 +++++++++++---------------------- 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 61ddfa5d2895..16782d8579a8 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -179,9 +179,9 @@ vma_create(struct drm_i915_gem_object *obj, INIT_LIST_HEAD(&vma->obj_link); RB_CLEAR_NODE(&vma->obj_node); - if (view && view->type != I915_GTT_VIEW_NORMAL) { + if (view && !intel_gtt_view_is_normal(view)) { vma->gtt_view = *view; - if (view->type == I915_GTT_VIEW_PARTIAL) { + if (intel_gtt_view_is_partial(view)) { GEM_BUG_ON(range_overflows_t(u64, view->partial.offset, view->partial.size, @@ -189,10 +189,10 @@ vma_create(struct drm_i915_gem_object *obj, vma->size = view->partial.size; vma->size <<= PAGE_SHIFT; GEM_BUG_ON(vma->size > obj->base.size); - } else if (view->type == I915_GTT_VIEW_ROTATED) { + } else if (intel_gtt_view_is_rotated(view)) { vma->size = intel_rotation_info_size(&view->rotated); vma->size <<= PAGE_SHIFT; - } else if (view->type == I915_GTT_VIEW_REMAPPED) { + } else if (intel_gtt_view_is_remapped(view)) { vma->size = intel_remapped_info_size(&view->remapped); vma->size <<= PAGE_SHIFT; } @@ -1311,27 +1311,15 @@ __i915_vma_get_pages(struct i915_vma *vma) */ GEM_BUG_ON(!i915_gem_object_has_pinned_pages(vma->obj)); - switch (vma->gtt_view.type) { - default: - GEM_BUG_ON(vma->gtt_view.type); - fallthrough; - case I915_GTT_VIEW_NORMAL: - pages = vma->obj->mm.pages; - break; - - case I915_GTT_VIEW_ROTATED: - pages = - intel_rotate_pages(&vma->gtt_view.rotated, vma->obj); - break; - - case I915_GTT_VIEW_REMAPPED: - pages = - intel_remap_pages(&vma->gtt_view.remapped, vma->obj); - break; - - case I915_GTT_VIEW_PARTIAL: + if (intel_gtt_view_is_rotated(&vma->gtt_view)) { + pages = intel_rotate_pages(&vma->gtt_view.rotated, vma->obj); + } else if (intel_gtt_view_is_remapped(&vma->gtt_view)) { + pages = intel_remap_pages(&vma->gtt_view.remapped, vma->obj); + } else if (intel_gtt_view_is_partial(&vma->gtt_view)) { pages = intel_partial_pages(&vma->gtt_view, vma->obj); - break; + } else { + GEM_BUG_ON(!intel_gtt_view_is_normal(&vma->gtt_view)); + pages = vma->obj->mm.pages; } if (IS_ERR(pages)) { From 88d9d2bab07325c6649f1e227466c8974af64fb7 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 30 Sep 2026 18:00:04 +0300 Subject: [PATCH 96/98] drm/i915/selftests: use intel_gtt_view_is_*() helpers more MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prefer using the intel_gtt_view_is_*() helpers instead of comparing the view type directly. v3: Use view, not vma->gtt_view even more (Ville) v2: Use view, not vma->gtt_view at the end (Sashiko) Reviewed-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/350f0be2c56ae4ac7b7bb97186f4d501faa7bb4e.1790780340.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/selftests/i915_vma.c | 34 +++++++++++------------ 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/selftests/i915_vma.c b/drivers/gpu/drm/i915/selftests/i915_vma.c index b16297a6a4e8..182c9f860628 100644 --- a/drivers/gpu/drm/i915/selftests/i915_vma.c +++ b/drivers/gpu/drm/i915/selftests/i915_vma.c @@ -51,7 +51,7 @@ static bool assert_vma(struct i915_vma *vma, ok = false; } - if (vma->gtt_view.type != I915_GTT_VIEW_NORMAL) { + if (!intel_gtt_view_is_normal(&vma->gtt_view)) { pr_err("VMA created with wrong type [%d]\n", vma->gtt_view.type); ok = false; @@ -533,12 +533,12 @@ assert_remapped(struct drm_i915_gem_object *obj, return sg; } -static unsigned int remapped_size(enum intel_gtt_view_type view_type, +static unsigned int remapped_size(const struct intel_gtt_view *view, const struct intel_remapped_plane_info *a, const struct intel_remapped_plane_info *b) { - if (view_type == I915_GTT_VIEW_ROTATED) + if (intel_gtt_view_is_rotated(view)) return a->dst_stride * a->width + b->dst_stride * b->width; else return a->dst_stride * a->height + b->dst_stride * b->height; @@ -606,11 +606,11 @@ static int igt_vma_rotate_remap(void *arg) max_offset = max_pages - max_offset; if (!plane_info[0].dst_stride) - plane_info[0].dst_stride = view.type == I915_GTT_VIEW_ROTATED ? + plane_info[0].dst_stride = intel_gtt_view_is_rotated(&view) ? plane_info[0].height : plane_info[0].width; if (!plane_info[1].dst_stride) - plane_info[1].dst_stride = view.type == I915_GTT_VIEW_ROTATED ? + plane_info[1].dst_stride = intel_gtt_view_is_rotated(&view) ? plane_info[1].height : plane_info[1].width; @@ -632,9 +632,9 @@ static int igt_vma_rotate_remap(void *arg) goto out_object; } - expected_pages = remapped_size(view.type, &plane_info[0], &plane_info[1]); + expected_pages = remapped_size(&view, &plane_info[0], &plane_info[1]); - if (view.type == I915_GTT_VIEW_ROTATED && + if (intel_gtt_view_is_rotated(&view) && vma->size != expected_pages * PAGE_SIZE) { pr_err("VMA is wrong size, expected %lu, found %llu\n", PAGE_SIZE * expected_pages, vma->size); @@ -642,7 +642,7 @@ static int igt_vma_rotate_remap(void *arg) goto out_object; } - if (view.type == I915_GTT_VIEW_REMAPPED && + if (intel_gtt_view_is_remapped(&view) && vma->size > expected_pages * PAGE_SIZE) { pr_err("VMA is wrong size, expected %lu, found %llu\n", PAGE_SIZE * expected_pages, vma->size); @@ -672,13 +672,13 @@ static int igt_vma_rotate_remap(void *arg) sg = vma->pages->sgl; for (n = 0; n < ARRAY_SIZE(view.rotated.plane); n++) { - if (view.type == I915_GTT_VIEW_ROTATED) + if (intel_gtt_view_is_rotated(&view)) sg = assert_rotated(obj, &view.rotated, n, sg); else sg = assert_remapped(obj, &view.remapped, n, sg); if (IS_ERR(sg)) { pr_err("Inconsistent %s VMA pages for plane %d: [(%d, %d, %d, %d, %d), (%d, %d, %d, %d, %d)]\n", - view.type == I915_GTT_VIEW_ROTATED ? + intel_gtt_view_is_rotated(&view) ? "rotated" : "remapped", n, plane_info[0].width, plane_info[0].height, @@ -763,7 +763,7 @@ static bool assert_pin(struct i915_vma *vma, ok = false; } - if (view && view->type != I915_GTT_VIEW_NORMAL) { + if (view && !intel_gtt_view_is_normal(view)) { if (memcmp(&vma->gtt_view, view, sizeof(*view))) { pr_err("(%s) VMA mismatch upon creation!\n", name); @@ -776,7 +776,7 @@ static bool assert_pin(struct i915_vma *vma, ok = false; } } else { - if (vma->gtt_view.type != I915_GTT_VIEW_NORMAL) { + if (!intel_gtt_view_is_normal(&vma->gtt_view)) { pr_err("Not the normal ggtt view! Found %d\n", vma->gtt_view.type); ok = false; @@ -1017,7 +1017,7 @@ static int igt_vma_remapped_gtt(void *arg) goto out; if (!plane_info[0].dst_stride) - plane_info[0].dst_stride = *t == I915_GTT_VIEW_ROTATED ? + plane_info[0].dst_stride = intel_gtt_view_is_rotated(&view) ? p->height : p->width; vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, PIN_MAPPABLE); @@ -1040,7 +1040,7 @@ static int igt_vma_remapped_gtt(void *arg) unsigned int offset; u32 val = y << 16 | x; - if (*t == I915_GTT_VIEW_ROTATED) + if (intel_gtt_view_is_rotated(&view)) offset = (x * plane_info[0].dst_stride + y) * PAGE_SIZE; else offset = (y * plane_info[0].dst_stride + x) * PAGE_SIZE; @@ -1057,7 +1057,7 @@ static int igt_vma_remapped_gtt(void *arg) goto out; } - GEM_BUG_ON(vma->gtt_view.type != I915_GTT_VIEW_NORMAL); + GEM_BUG_ON(!intel_gtt_view_is_normal(&vma->gtt_view)); map = i915_vma_pin_iomap(vma); i915_vma_unpin(vma); @@ -1072,7 +1072,7 @@ static int igt_vma_remapped_gtt(void *arg) u32 exp = y << 16 | x; u32 val; - if (*t == I915_GTT_VIEW_ROTATED) + if (intel_gtt_view_is_rotated(&view)) src_idx = rotated_index(&view.rotated, 0, x, y); else src_idx = remapped_index(&view.remapped, 0, x, y); @@ -1081,7 +1081,7 @@ static int igt_vma_remapped_gtt(void *arg) val = ioread32(&map[offset / sizeof(*map)]); if (val != exp) { pr_err("%s VMA write test failed, expected 0x%x, found 0x%x\n", - *t == I915_GTT_VIEW_ROTATED ? "Rotated" : "Remapped", + intel_gtt_view_is_rotated(&view) ? "Rotated" : "Remapped", exp, val); i915_vma_unpin_iomap(vma); err = -EINVAL; From 105852cba40e500775207144e22c72e4ca2347a7 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 30 Sep 2026 18:00:05 +0300 Subject: [PATCH 97/98] drm/i915/debugfs: use the intel_gtt_view_is_*() helpers more MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prefer using the intel_gtt_view_is_*() helpers instead of comparing the view type directly. Reviewed-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/6d9279ce0522f6768f55fb6c760862fdb92ffc03.1790780340.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_debugfs.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 93ba7369ba6e..04bc3d27b836 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -209,18 +209,13 @@ i915_debugfs_describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) stringify_page_sizes(vma->resource->page_sizes_gtt, NULL, 0)); if (i915_vma_is_ggtt(vma) || i915_vma_is_dpt(vma)) { - switch (vma->gtt_view.type) { - case I915_GTT_VIEW_NORMAL: + if (intel_gtt_view_is_normal(&vma->gtt_view)) { seq_puts(m, ", normal"); - break; - - case I915_GTT_VIEW_PARTIAL: + } else if (intel_gtt_view_is_partial(&vma->gtt_view)) { seq_printf(m, ", partial [%08llx+%x]", vma->gtt_view.partial.offset << PAGE_SHIFT, vma->gtt_view.partial.size << PAGE_SHIFT); - break; - - case I915_GTT_VIEW_ROTATED: + } else if (intel_gtt_view_is_rotated(&vma->gtt_view)) { seq_printf(m, ", rotated [(%ux%u, src_stride=%u, dst_stride=%u, offset=%u), (%ux%u, src_stride=%u, dst_stride=%u, offset=%u)]", vma->gtt_view.rotated.plane[0].width, vma->gtt_view.rotated.plane[0].height, @@ -232,9 +227,7 @@ i915_debugfs_describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) vma->gtt_view.rotated.plane[1].src_stride, vma->gtt_view.rotated.plane[1].dst_stride, vma->gtt_view.rotated.plane[1].offset); - break; - - case I915_GTT_VIEW_REMAPPED: + } else if (intel_gtt_view_is_remapped(&vma->gtt_view)) { seq_printf(m, ", remapped [(%ux%u, src_stride=%u, dst_stride=%u, offset=%u), (%ux%u, src_stride=%u, dst_stride=%u, offset=%u)]", vma->gtt_view.remapped.plane[0].width, vma->gtt_view.remapped.plane[0].height, @@ -246,11 +239,8 @@ i915_debugfs_describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) vma->gtt_view.remapped.plane[1].src_stride, vma->gtt_view.remapped.plane[1].dst_stride, vma->gtt_view.remapped.plane[1].offset); - break; - - default: + } else { MISSING_CASE(vma->gtt_view.type); - break; } } if (vma->fence) From 2c1bb96681bea17c2ffbd134816961615292a159 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 30 Sep 2026 18:00:06 +0300 Subject: [PATCH 98/98] drm/intel: rename I915_GTT_VIEW_* enumerations to INTEL_GTT_VIEW_* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the I915_GTT_VIEW_* enumerators less i915 specific, and rename them INTEL_GTT_VIEW_*. $ sed -i 's/I915_GTT_VIEW_/INTEL_GTT_VIEW_/g' -- $(git grep -l I915_GTT_VIEW_) Reviewed-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä Link: https://patch.msgid.link/6e66fd6b61e361ffde316e5399baf9432383ced5.1790780340.git.jani.nikula@intel.com Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_fb.c | 8 ++++---- drivers/gpu/drm/i915/gem/i915_gem_mman.c | 6 +++--- drivers/gpu/drm/i915/i915_vma.h | 8 ++++---- drivers/gpu/drm/i915/i915_vma_types.h | 10 +++++----- drivers/gpu/drm/i915/selftests/i915_vma.c | 12 ++++++------ include/drm/intel/gtt_view_types.h | 16 ++++++++-------- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index d1b4efa08bcc..9d71f594537f 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -1706,7 +1706,7 @@ int intel_fill_fb_info(struct intel_display *display, struct intel_framebuffer * unsigned int tile_size = intel_tile_size(display); intel_fb_view_init(display, &fb->normal_view, - I915_GTT_VIEW_NORMAL, fb); + INTEL_GTT_VIEW_NORMAL, fb); drm_WARN_ON(display->drm, intel_fb_supports_90_270_rotation(fb) && @@ -1714,10 +1714,10 @@ int intel_fill_fb_info(struct intel_display *display, struct intel_framebuffer * if (intel_fb_supports_90_270_rotation(fb)) intel_fb_view_init(display, &fb->rotated_view, - I915_GTT_VIEW_ROTATED, fb); + INTEL_GTT_VIEW_ROTATED, fb); if (intel_fb_needs_pot_stride_remap(fb)) intel_fb_view_init(display, &fb->remapped_view, - I915_GTT_VIEW_REMAPPED, fb); + INTEL_GTT_VIEW_REMAPPED, fb); for (i = 0; i < num_planes; i++) { struct fb_plane_view_dims view_dims; @@ -1845,7 +1845,7 @@ static void intel_plane_remap_gtt(struct intel_plane_state *plane_state) intel_fb_view_init(display, &plane_state->view, drm_rotation_90_or_270(rotation) ? - I915_GTT_VIEW_ROTATED : I915_GTT_VIEW_REMAPPED, + INTEL_GTT_VIEW_ROTATED : INTEL_GTT_VIEW_REMAPPED, intel_fb); src_x = plane_state->uapi.src.x1 >> 16; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index 055f8d3161da..6b337684dbfe 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -206,7 +206,7 @@ compute_partial_view(const struct drm_i915_gem_object *obj, if (i915_gem_object_is_tiled(obj)) chunk = roundup(chunk, tile_row_pages(obj) ?: 1); - view.type = I915_GTT_VIEW_PARTIAL; + view.type = INTEL_GTT_VIEW_PARTIAL; view.partial.offset = rounddown(page_offset, chunk); view.partial.size = min_t(unsigned int, chunk, @@ -214,7 +214,7 @@ compute_partial_view(const struct drm_i915_gem_object *obj, /* If the partial covers the entire object, just create a normal VMA. */ if (chunk >= obj->base.size >> PAGE_SHIFT) - view.type = I915_GTT_VIEW_NORMAL; + view.type = INTEL_GTT_VIEW_NORMAL; return view; } @@ -407,7 +407,7 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf) vma = i915_gem_object_ggtt_pin_ww(obj, &ww, &view, 0, 0, flags); if (IS_ERR(vma) && vma != ERR_PTR(-EDEADLK)) { flags = PIN_MAPPABLE; - view.type = I915_GTT_VIEW_PARTIAL; + view.type = INTEL_GTT_VIEW_PARTIAL; vma = i915_gem_object_ggtt_pin_ww(obj, &ww, &view, 0, 0, flags); } diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h index a8a89bb0270c..b0aca10bf8e7 100644 --- a/drivers/gpu/drm/i915/i915_vma.h +++ b/drivers/gpu/drm/i915/i915_vma.h @@ -217,7 +217,7 @@ i915_vma_compare(struct i915_vma *vma, if (cmp) return cmp; - BUILD_BUG_ON(I915_GTT_VIEW_NORMAL != 0); + BUILD_BUG_ON(INTEL_GTT_VIEW_NORMAL != 0); cmp = vma->gtt_view.type; if (!view) return cmp; @@ -238,9 +238,9 @@ i915_vma_compare(struct i915_vma *vma, * we assert above that all branches have the same address, and that * each branch has a unique type/size. */ - BUILD_BUG_ON(I915_GTT_VIEW_NORMAL >= I915_GTT_VIEW_PARTIAL); - BUILD_BUG_ON(I915_GTT_VIEW_PARTIAL >= I915_GTT_VIEW_ROTATED); - BUILD_BUG_ON(I915_GTT_VIEW_ROTATED >= I915_GTT_VIEW_REMAPPED); + BUILD_BUG_ON(INTEL_GTT_VIEW_NORMAL >= INTEL_GTT_VIEW_PARTIAL); + BUILD_BUG_ON(INTEL_GTT_VIEW_PARTIAL >= INTEL_GTT_VIEW_ROTATED); + BUILD_BUG_ON(INTEL_GTT_VIEW_ROTATED >= INTEL_GTT_VIEW_REMAPPED); BUILD_BUG_ON(offsetof(typeof(*view), rotated) != offsetof(typeof(*view), partial)); BUILD_BUG_ON(offsetof(typeof(*view), rotated) != diff --git a/drivers/gpu/drm/i915/i915_vma_types.h b/drivers/gpu/drm/i915/i915_vma_types.h index 8815421eaefb..95eaf68fdfae 100644 --- a/drivers/gpu/drm/i915/i915_vma_types.h +++ b/drivers/gpu/drm/i915/i915_vma_types.h @@ -112,10 +112,10 @@ static inline void assert_i915_gem_gtt_types(void) * we have to be careful that each branch has a unique size. */ switch ((enum intel_gtt_view_type)0) { - case I915_GTT_VIEW_NORMAL: - case I915_GTT_VIEW_PARTIAL: - case I915_GTT_VIEW_ROTATED: - case I915_GTT_VIEW_REMAPPED: + case INTEL_GTT_VIEW_NORMAL: + case INTEL_GTT_VIEW_PARTIAL: + case INTEL_GTT_VIEW_ROTATED: + case INTEL_GTT_VIEW_REMAPPED: /* gcc complains if these are identical cases */ break; } @@ -231,7 +231,7 @@ struct i915_vma { * Support different GGTT views into the same object. * This means there can be multiple VMA mappings per object and per VM. * intel_gtt_view_type is used to distinguish between those entries. - * The default one of zero (I915_GTT_VIEW_NORMAL) is default and also + * The default one of zero (INTEL_GTT_VIEW_NORMAL) is default and also * assumed in GEM functions which take no ggtt view parameter. */ struct intel_gtt_view gtt_view; diff --git a/drivers/gpu/drm/i915/selftests/i915_vma.c b/drivers/gpu/drm/i915/selftests/i915_vma.c index 182c9f860628..fc068dab27f4 100644 --- a/drivers/gpu/drm/i915/selftests/i915_vma.c +++ b/drivers/gpu/drm/i915/selftests/i915_vma.c @@ -573,8 +573,8 @@ static int igt_vma_rotate_remap(void *arg) { } }, *a, *b; enum intel_gtt_view_type types[] = { - I915_GTT_VIEW_ROTATED, - I915_GTT_VIEW_REMAPPED, + INTEL_GTT_VIEW_ROTATED, + INTEL_GTT_VIEW_REMAPPED, 0, }, *t; const unsigned int max_pages = 64; @@ -825,12 +825,12 @@ static int igt_vma_partial(void *arg) for_each_prime_number_from(offset, 0, npages - sz) { struct intel_gtt_view view; - view.type = I915_GTT_VIEW_PARTIAL; + view.type = INTEL_GTT_VIEW_PARTIAL; view.partial.offset = offset; view.partial.size = sz; if (sz == npages) - view.type = I915_GTT_VIEW_NORMAL; + view.type = INTEL_GTT_VIEW_NORMAL; vma = checked_vma_instance(obj, vm, &view); if (IS_ERR(vma)) { @@ -982,8 +982,8 @@ static int igt_vma_remapped_gtt(void *arg) { } }, *p; enum intel_gtt_view_type types[] = { - I915_GTT_VIEW_ROTATED, - I915_GTT_VIEW_REMAPPED, + INTEL_GTT_VIEW_ROTATED, + INTEL_GTT_VIEW_REMAPPED, 0, }, *t; struct drm_i915_gem_object *obj; diff --git a/include/drm/intel/gtt_view_types.h b/include/drm/intel/gtt_view_types.h index d77292897d64..128392d98f3a 100644 --- a/include/drm/intel/gtt_view_types.h +++ b/include/drm/intel/gtt_view_types.h @@ -40,10 +40,10 @@ struct intel_remapped_info { } __packed; enum intel_gtt_view_type { - I915_GTT_VIEW_NORMAL = 0, - I915_GTT_VIEW_ROTATED = sizeof(struct intel_rotation_info), - I915_GTT_VIEW_PARTIAL = sizeof(struct intel_partial_info), - I915_GTT_VIEW_REMAPPED = sizeof(struct intel_remapped_info), + INTEL_GTT_VIEW_NORMAL = 0, + INTEL_GTT_VIEW_ROTATED = sizeof(struct intel_rotation_info), + INTEL_GTT_VIEW_PARTIAL = sizeof(struct intel_partial_info), + INTEL_GTT_VIEW_REMAPPED = sizeof(struct intel_remapped_info), }; struct intel_gtt_view { @@ -58,22 +58,22 @@ struct intel_gtt_view { static inline bool intel_gtt_view_is_normal(const struct intel_gtt_view *view) { - return view->type == I915_GTT_VIEW_NORMAL; + return view->type == INTEL_GTT_VIEW_NORMAL; } static inline bool intel_gtt_view_is_remapped(const struct intel_gtt_view *view) { - return view->type == I915_GTT_VIEW_REMAPPED; + return view->type == INTEL_GTT_VIEW_REMAPPED; } static inline bool intel_gtt_view_is_rotated(const struct intel_gtt_view *view) { - return view->type == I915_GTT_VIEW_ROTATED; + return view->type == INTEL_GTT_VIEW_ROTATED; } static inline bool intel_gtt_view_is_partial(const struct intel_gtt_view *view) { - return view->type == I915_GTT_VIEW_PARTIAL; + return view->type == INTEL_GTT_VIEW_PARTIAL; } #endif /* __DRM_INTEL_GTT_VIEW_TYPES_H__ */