* [PATCH 0/2] drm: detect panel type from DisplayID 2.x
@ 2026-05-14 6:54 Chenyu Chen
2026-05-14 6:54 ` [PATCH 1/2] drm/edid: parse panel type from DisplayID 2.x Display Parameters block Chenyu Chen
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Chenyu Chen @ 2026-05-14 6:54 UTC (permalink / raw)
To: amd-gfx, dri-devel
Cc: Harry Wentland, Leo Li, Ray Wu, Limonciello Mario, Jani Nikula,
Chenyu Chen
Parse the Display Device Technology field from the DisplayID v2.x
Display Parameters Data Block to identify LCD and OLED panels, and
wire it into amdgpu_dm as a fallback for panel type detection.
Chenyu Chen (2):
drm/edid: parse panel type from DisplayID 2.x Display Parameters block
drm/amd/display: use DisplayID panel type in dm_set_panel_type
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 ++--
drivers/gpu/drm/drm_displayid_internal.h | 25 ++++++++
drivers/gpu/drm/drm_edid.c | 61 +++++++++++++++----
include/drm/drm_connector.h | 6 ++
include/uapi/drm/drm_mode.h | 1 +
5 files changed, 89 insertions(+), 16 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 1/2] drm/edid: parse panel type from DisplayID 2.x Display Parameters block 2026-05-14 6:54 [PATCH 0/2] drm: detect panel type from DisplayID 2.x Chenyu Chen @ 2026-05-14 6:54 ` Chenyu Chen 2026-05-15 8:23 ` Jani Nikula 2026-05-16 1:17 ` Claude review: " Claude Code Review Bot 2026-05-14 6:54 ` [PATCH 2/2] drm/amd/display: use DisplayID panel type in dm_set_panel_type Chenyu Chen 2026-05-16 1:17 ` Claude review: drm: detect panel type from DisplayID 2.x Claude Code Review Bot 2 siblings, 2 replies; 8+ messages in thread From: Chenyu Chen @ 2026-05-14 6:54 UTC (permalink / raw) To: amd-gfx, dri-devel Cc: Harry Wentland, Leo Li, Ray Wu, Limonciello Mario, Jani Nikula, Chenyu Chen, Mario Limonciello Parse the Display Parameters Data Block (tag 0x21) defined in DisplayID v2.1a Section 4.2.6. Extract the Display Device Technology field from payload byte 27, bits [6:4], which indicates whether the panel is LCD (001b) or OLED (010b). Store the result in drm_display_info.did_panel_type so that downstream drivers can use it for panel-type-dependent behavior. Assisted-by: Copilot:Claude-Opus-4.6 Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com> --- drivers/gpu/drm/drm_displayid_internal.h | 25 ++++++++++ drivers/gpu/drm/drm_edid.c | 61 +++++++++++++++++++----- include/drm/drm_connector.h | 6 +++ include/uapi/drm/drm_mode.h | 1 + 4 files changed, 82 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/drm_displayid_internal.h b/drivers/gpu/drm/drm_displayid_internal.h index 5b1b32f73516..e0f7c54d2987 100644 --- a/drivers/gpu/drm/drm_displayid_internal.h +++ b/drivers/gpu/drm/drm_displayid_internal.h @@ -142,6 +142,31 @@ struct displayid_formula_timing_block { struct displayid_formula_timings_9 timings[]; } __packed; +/* + * DisplayID v2.x Display Parameters Data Block (tag 0x21). + * + * Per VESA DisplayID v2.1a, Section 4.2.6, Table 4-14: + * Offset 0x1E (payload byte 27) contains Native Color Depth and + * Display Device Technology fields. + * bits [2:0] = Native Color Depth + * bit [3] = RESERVED + * bits [6:4] = Display Device Technology + * 000b = not specified, 001b = LCD, 010b = OLED, others reserved + * bit [7] = Display Device Theme Preference + */ +#define DISPLAYID_DISPLAY_PARAMS_DEVICE_TECH GENMASK(6, 4) + +struct displayid_display_params_block { + struct displayid_block base; + u8 payload[27]; + u8 device_tech_byte; /* bits [6:4] = Display Device Technology */ + u8 reserved; +} __packed; + +#define DISPLAYID_DISPLAY_PARAMS_MIN_LEN \ + (sizeof(struct displayid_display_params_block) - \ + sizeof(struct displayid_block)) + #define DISPLAYID_VESA_MSO_OVERLAP GENMASK(3, 0) #define DISPLAYID_VESA_MSO_MODE GENMASK(6, 5) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 8031f021d4d0..9b160a878df4 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -6713,6 +6713,8 @@ static void drm_reset_display_info(struct drm_connector *connector) info->source_physical_address = CEC_PHYS_ADDR_INVALID; memset(&info->amd_vsdb, 0, sizeof(info->amd_vsdb)); + + info->did_panel_type = DRM_MODE_PANEL_TYPE_UNKNOWN; } static void update_displayid_info(struct drm_connector *connector, @@ -6721,24 +6723,61 @@ static void update_displayid_info(struct drm_connector *connector, struct drm_display_info *info = &connector->display_info; const struct displayid_block *block; struct displayid_iter iter; + const u8 *section = NULL; displayid_iter_edid_begin(drm_edid, &iter); displayid_iter_for_each(block, &iter) { + if (section != iter.section) { + drm_dbg_kms(connector->dev, + "[CONNECTOR:%d:%s] DisplayID extension version 0x%02x, primary use 0x%02x\n", + connector->base.id, connector->name, + displayid_version(&iter), + displayid_primary_use(&iter)); + if (displayid_version(&iter) == DISPLAY_ID_STRUCTURE_VER_20 && + (displayid_primary_use(&iter) == PRIMARY_USE_HEAD_MOUNTED_VR || + displayid_primary_use(&iter) == PRIMARY_USE_HEAD_MOUNTED_AR)) + info->non_desktop = true; + section = iter.section; + } + drm_dbg_kms(connector->dev, - "[CONNECTOR:%d:%s] DisplayID extension version 0x%02x, primary use 0x%02x\n", + "[CONNECTOR:%d:%s] DisplayID block tag 0x%02x, rev 0x%02x, size %u\n", connector->base.id, connector->name, - displayid_version(&iter), - displayid_primary_use(&iter)); + block->tag, block->rev, block->num_bytes); + if (displayid_version(&iter) == DISPLAY_ID_STRUCTURE_VER_20 && - (displayid_primary_use(&iter) == PRIMARY_USE_HEAD_MOUNTED_VR || - displayid_primary_use(&iter) == PRIMARY_USE_HEAD_MOUNTED_AR)) - info->non_desktop = true; + block->tag == DATA_BLOCK_2_DISPLAY_PARAMETERS) { + const struct displayid_display_params_block *params = + (const struct displayid_display_params_block *)block; + u8 tech; + + if (block->num_bytes < DISPLAYID_DISPLAY_PARAMS_MIN_LEN) { + drm_dbg_kms(connector->dev, + "[CONNECTOR:%d:%s] DisplayID Display Parameters block too short (%u < %zu)\n", + connector->base.id, connector->name, + block->num_bytes, + DISPLAYID_DISPLAY_PARAMS_MIN_LEN); + continue; + } - /* - * We're only interested in the base section here, no need to - * iterate further. - */ - break; + tech = FIELD_GET(DISPLAYID_DISPLAY_PARAMS_DEVICE_TECH, + params->device_tech_byte); + + drm_dbg_kms(connector->dev, + "[CONNECTOR:%d:%s] DisplayID Display Parameters: device technology %u\n", + connector->base.id, connector->name, tech); + + switch (tech) { + case 1: /* LCD */ + info->did_panel_type = DRM_MODE_PANEL_TYPE_LCD; + break; + case 2: /* OLED */ + info->did_panel_type = DRM_MODE_PANEL_TYPE_OLED; + break; + default: + break; + } + } } displayid_iter_end(&iter); } diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index c398dbc68bbc..b95aec34ddb7 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -899,6 +899,12 @@ struct drm_display_info { * @amd_vsdb: AMD-specific VSDB information. */ struct drm_amd_vsdb_info amd_vsdb; + + /** + * @did_panel_type: Panel type from DisplayID Display Parameters + * Data Block (tag 0x21). Uses DRM_MODE_PANEL_TYPE_* constants. + */ + u8 did_panel_type; }; int drm_display_info_set_bus_formats(struct drm_display_info *info, diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index 3693d82b5279..d7ca1040b92e 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -169,6 +169,7 @@ extern "C" { /* Panel type property */ #define DRM_MODE_PANEL_TYPE_UNKNOWN 0 #define DRM_MODE_PANEL_TYPE_OLED 1 +#define DRM_MODE_PANEL_TYPE_LCD 2 /* * DRM_MODE_ROTATE_<degrees> -- 2.43.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] drm/edid: parse panel type from DisplayID 2.x Display Parameters block 2026-05-14 6:54 ` [PATCH 1/2] drm/edid: parse panel type from DisplayID 2.x Display Parameters block Chenyu Chen @ 2026-05-15 8:23 ` Jani Nikula 2026-05-15 23:47 ` Leo Li 2026-05-16 1:17 ` Claude review: " Claude Code Review Bot 1 sibling, 1 reply; 8+ messages in thread From: Jani Nikula @ 2026-05-15 8:23 UTC (permalink / raw) To: Chenyu Chen, amd-gfx, dri-devel Cc: Harry Wentland, Leo Li, Ray Wu, Limonciello Mario, Chenyu Chen, Mario Limonciello On Thu, 14 May 2026, Chenyu Chen <chen-yu.chen@amd.com> wrote: > Parse the Display Parameters Data Block (tag 0x21) defined in > DisplayID v2.1a Section 4.2.6. Extract the Display Device Technology > field from payload byte 27, bits [6:4], which indicates whether the > panel is LCD (001b) or OLED (010b). > > Store the result in drm_display_info.did_panel_type so that downstream > drivers can use it for panel-type-dependent behavior. > > Assisted-by: Copilot:Claude-Opus-4.6 > Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com> > Reviewed-by: Mario Limonciello <mario.limonciello@amd.com> > --- > drivers/gpu/drm/drm_displayid_internal.h | 25 ++++++++++ > drivers/gpu/drm/drm_edid.c | 61 +++++++++++++++++++----- > include/drm/drm_connector.h | 6 +++ > include/uapi/drm/drm_mode.h | 1 + > 4 files changed, 82 insertions(+), 11 deletions(-) > > diff --git a/drivers/gpu/drm/drm_displayid_internal.h b/drivers/gpu/drm/drm_displayid_internal.h > index 5b1b32f73516..e0f7c54d2987 100644 > --- a/drivers/gpu/drm/drm_displayid_internal.h > +++ b/drivers/gpu/drm/drm_displayid_internal.h > @@ -142,6 +142,31 @@ struct displayid_formula_timing_block { > struct displayid_formula_timings_9 timings[]; > } __packed; > > +/* > + * DisplayID v2.x Display Parameters Data Block (tag 0x21). > + * > + * Per VESA DisplayID v2.1a, Section 4.2.6, Table 4-14: > + * Offset 0x1E (payload byte 27) contains Native Color Depth and > + * Display Device Technology fields. > + * bits [2:0] = Native Color Depth > + * bit [3] = RESERVED > + * bits [6:4] = Display Device Technology > + * 000b = not specified, 001b = LCD, 010b = OLED, others reserved > + * bit [7] = Display Device Theme Preference > + */ > +#define DISPLAYID_DISPLAY_PARAMS_DEVICE_TECH GENMASK(6, 4) > + > +struct displayid_display_params_block { > + struct displayid_block base; > + u8 payload[27]; > + u8 device_tech_byte; /* bits [6:4] = Display Device Technology */ > + u8 reserved; > +} __packed; > + > +#define DISPLAYID_DISPLAY_PARAMS_MIN_LEN \ > + (sizeof(struct displayid_display_params_block) - \ > + sizeof(struct displayid_block)) > + > #define DISPLAYID_VESA_MSO_OVERLAP GENMASK(3, 0) > #define DISPLAYID_VESA_MSO_MODE GENMASK(6, 5) > > diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c > index 8031f021d4d0..9b160a878df4 100644 > --- a/drivers/gpu/drm/drm_edid.c > +++ b/drivers/gpu/drm/drm_edid.c > @@ -6713,6 +6713,8 @@ static void drm_reset_display_info(struct drm_connector *connector) > > info->source_physical_address = CEC_PHYS_ADDR_INVALID; > memset(&info->amd_vsdb, 0, sizeof(info->amd_vsdb)); > + > + info->did_panel_type = DRM_MODE_PANEL_TYPE_UNKNOWN; > } > > static void update_displayid_info(struct drm_connector *connector, > @@ -6721,24 +6723,61 @@ static void update_displayid_info(struct drm_connector *connector, > struct drm_display_info *info = &connector->display_info; > const struct displayid_block *block; > struct displayid_iter iter; > + const u8 *section = NULL; > > displayid_iter_edid_begin(drm_edid, &iter); > displayid_iter_for_each(block, &iter) { > + if (section != iter.section) { > + drm_dbg_kms(connector->dev, > + "[CONNECTOR:%d:%s] DisplayID extension version 0x%02x, primary use 0x%02x\n", > + connector->base.id, connector->name, > + displayid_version(&iter), > + displayid_primary_use(&iter)); > + if (displayid_version(&iter) == DISPLAY_ID_STRUCTURE_VER_20 && > + (displayid_primary_use(&iter) == PRIMARY_USE_HEAD_MOUNTED_VR || > + displayid_primary_use(&iter) == PRIMARY_USE_HEAD_MOUNTED_AR)) > + info->non_desktop = true; > + section = iter.section; > + } What is this even supposed to do? > + > drm_dbg_kms(connector->dev, > - "[CONNECTOR:%d:%s] DisplayID extension version 0x%02x, primary use 0x%02x\n", > + "[CONNECTOR:%d:%s] DisplayID block tag 0x%02x, rev 0x%02x, size %u\n", > connector->base.id, connector->name, > - displayid_version(&iter), > - displayid_primary_use(&iter)); > + block->tag, block->rev, block->num_bytes); > + > if (displayid_version(&iter) == DISPLAY_ID_STRUCTURE_VER_20 && > - (displayid_primary_use(&iter) == PRIMARY_USE_HEAD_MOUNTED_VR || > - displayid_primary_use(&iter) == PRIMARY_USE_HEAD_MOUNTED_AR)) > - info->non_desktop = true; > + block->tag == DATA_BLOCK_2_DISPLAY_PARAMETERS) { > + const struct displayid_display_params_block *params = > + (const struct displayid_display_params_block *)block; > + u8 tech; > + > + if (block->num_bytes < DISPLAYID_DISPLAY_PARAMS_MIN_LEN) { > + drm_dbg_kms(connector->dev, > + "[CONNECTOR:%d:%s] DisplayID Display Parameters block too short (%u < %zu)\n", > + connector->base.id, connector->name, > + block->num_bytes, > + DISPLAYID_DISPLAY_PARAMS_MIN_LEN); > + continue; > + } > > - /* > - * We're only interested in the base section here, no need to > - * iterate further. > - */ > - break; > + tech = FIELD_GET(DISPLAYID_DISPLAY_PARAMS_DEVICE_TECH, > + params->device_tech_byte); > + > + drm_dbg_kms(connector->dev, > + "[CONNECTOR:%d:%s] DisplayID Display Parameters: device technology %u\n", > + connector->base.id, connector->name, tech); > + > + switch (tech) { > + case 1: /* LCD */ > + info->did_panel_type = DRM_MODE_PANEL_TYPE_LCD; > + break; > + case 2: /* OLED */ > + info->did_panel_type = DRM_MODE_PANEL_TYPE_OLED; > + break; > + default: > + break; > + } > + } Please tell copilot to not add so much crap in the iterator block. Add functions. Add the first function as a refactor for non_desktop, add more stuff on top, i.e. split this into multiple patches. BR, Jani. > } > displayid_iter_end(&iter); > } > diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h > index c398dbc68bbc..b95aec34ddb7 100644 > --- a/include/drm/drm_connector.h > +++ b/include/drm/drm_connector.h > @@ -899,6 +899,12 @@ struct drm_display_info { > * @amd_vsdb: AMD-specific VSDB information. > */ > struct drm_amd_vsdb_info amd_vsdb; > + > + /** > + * @did_panel_type: Panel type from DisplayID Display Parameters > + * Data Block (tag 0x21). Uses DRM_MODE_PANEL_TYPE_* constants. > + */ > + u8 did_panel_type; > }; > > int drm_display_info_set_bus_formats(struct drm_display_info *info, > diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h > index 3693d82b5279..d7ca1040b92e 100644 > --- a/include/uapi/drm/drm_mode.h > +++ b/include/uapi/drm/drm_mode.h > @@ -169,6 +169,7 @@ extern "C" { > /* Panel type property */ > #define DRM_MODE_PANEL_TYPE_UNKNOWN 0 > #define DRM_MODE_PANEL_TYPE_OLED 1 > +#define DRM_MODE_PANEL_TYPE_LCD 2 > > /* > * DRM_MODE_ROTATE_<degrees> -- Jani Nikula, Intel ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] drm/edid: parse panel type from DisplayID 2.x Display Parameters block 2026-05-15 8:23 ` Jani Nikula @ 2026-05-15 23:47 ` Leo Li 0 siblings, 0 replies; 8+ messages in thread From: Leo Li @ 2026-05-15 23:47 UTC (permalink / raw) To: Jani Nikula, Chenyu Chen, amd-gfx, dri-devel Cc: Harry Wentland, Ray Wu, Limonciello Mario On 2026-05-15 04:23, Jani Nikula wrote: > On Thu, 14 May 2026, Chenyu Chen <chen-yu.chen@amd.com> wrote: >> Parse the Display Parameters Data Block (tag 0x21) defined in >> DisplayID v2.1a Section 4.2.6. Extract the Display Device Technology >> field from payload byte 27, bits [6:4], which indicates whether the >> panel is LCD (001b) or OLED (010b). >> >> Store the result in drm_display_info.did_panel_type so that downstream >> drivers can use it for panel-type-dependent behavior. >> >> Assisted-by: Copilot:Claude-Opus-4.6 >> Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com> >> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com> >> --- >> drivers/gpu/drm/drm_displayid_internal.h | 25 ++++++++++ >> drivers/gpu/drm/drm_edid.c | 61 +++++++++++++++++++----- >> include/drm/drm_connector.h | 6 +++ >> include/uapi/drm/drm_mode.h | 1 + >> 4 files changed, 82 insertions(+), 11 deletions(-) >> >> diff --git a/drivers/gpu/drm/drm_displayid_internal.h b/drivers/gpu/drm/drm_displayid_internal.h >> index 5b1b32f73516..e0f7c54d2987 100644 >> --- a/drivers/gpu/drm/drm_displayid_internal.h >> +++ b/drivers/gpu/drm/drm_displayid_internal.h >> @@ -142,6 +142,31 @@ struct displayid_formula_timing_block { >> struct displayid_formula_timings_9 timings[]; >> } __packed; >> >> +/* >> + * DisplayID v2.x Display Parameters Data Block (tag 0x21). >> + * >> + * Per VESA DisplayID v2.1a, Section 4.2.6, Table 4-14: >> + * Offset 0x1E (payload byte 27) contains Native Color Depth and >> + * Display Device Technology fields. >> + * bits [2:0] = Native Color Depth >> + * bit [3] = RESERVED >> + * bits [6:4] = Display Device Technology >> + * 000b = not specified, 001b = LCD, 010b = OLED, others reserved >> + * bit [7] = Display Device Theme Preference >> + */ >> +#define DISPLAYID_DISPLAY_PARAMS_DEVICE_TECH GENMASK(6, 4) >> + >> +struct displayid_display_params_block { >> + struct displayid_block base; >> + u8 payload[27]; >> + u8 device_tech_byte; /* bits [6:4] = Display Device Technology */ >> + u8 reserved; >> +} __packed; >> + >> +#define DISPLAYID_DISPLAY_PARAMS_MIN_LEN \ >> + (sizeof(struct displayid_display_params_block) - \ >> + sizeof(struct displayid_block)) >> + >> #define DISPLAYID_VESA_MSO_OVERLAP GENMASK(3, 0) >> #define DISPLAYID_VESA_MSO_MODE GENMASK(6, 5) >> >> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c >> index 8031f021d4d0..9b160a878df4 100644 >> --- a/drivers/gpu/drm/drm_edid.c >> +++ b/drivers/gpu/drm/drm_edid.c >> @@ -6713,6 +6713,8 @@ static void drm_reset_display_info(struct drm_connector *connector) >> >> info->source_physical_address = CEC_PHYS_ADDR_INVALID; >> memset(&info->amd_vsdb, 0, sizeof(info->amd_vsdb)); >> + >> + info->did_panel_type = DRM_MODE_PANEL_TYPE_UNKNOWN; >> } >> >> static void update_displayid_info(struct drm_connector *connector, >> @@ -6721,24 +6723,61 @@ static void update_displayid_info(struct drm_connector *connector, >> struct drm_display_info *info = &connector->display_info; >> const struct displayid_block *block; >> struct displayid_iter iter; >> + const u8 *section = NULL; >> >> displayid_iter_edid_begin(drm_edid, &iter); >> displayid_iter_for_each(block, &iter) { >> + if (section != iter.section) { >> + drm_dbg_kms(connector->dev, >> + "[CONNECTOR:%d:%s] DisplayID extension version 0x%02x, primary use 0x%02x\n", >> + connector->base.id, connector->name, >> + displayid_version(&iter), >> + displayid_primary_use(&iter)); >> + if (displayid_version(&iter) == DISPLAY_ID_STRUCTURE_VER_20 && >> + (displayid_primary_use(&iter) == PRIMARY_USE_HEAD_MOUNTED_VR || >> + displayid_primary_use(&iter) == PRIMARY_USE_HEAD_MOUNTED_AR)) >> + info->non_desktop = true; >> + section = iter.section; >> + } > > What is this even supposed to do? > I think the intention is to log and process the DisplayID base section header only once instead on every iteration. Maybe a `bool header_processed` works better? - Leo >> + >> drm_dbg_kms(connector->dev, >> - "[CONNECTOR:%d:%s] DisplayID extension version 0x%02x, primary use 0x%02x\n", >> + "[CONNECTOR:%d:%s] DisplayID block tag 0x%02x, rev 0x%02x, size %u\n", >> connector->base.id, connector->name, >> - displayid_version(&iter), >> - displayid_primary_use(&iter)); >> + block->tag, block->rev, block->num_bytes); >> + >> if (displayid_version(&iter) == DISPLAY_ID_STRUCTURE_VER_20 && >> - (displayid_primary_use(&iter) == PRIMARY_USE_HEAD_MOUNTED_VR || >> - displayid_primary_use(&iter) == PRIMARY_USE_HEAD_MOUNTED_AR)) >> - info->non_desktop = true; >> + block->tag == DATA_BLOCK_2_DISPLAY_PARAMETERS) { >> + const struct displayid_display_params_block *params = >> + (const struct displayid_display_params_block *)block; >> + u8 tech; >> + >> + if (block->num_bytes < DISPLAYID_DISPLAY_PARAMS_MIN_LEN) { >> + drm_dbg_kms(connector->dev, >> + "[CONNECTOR:%d:%s] DisplayID Display Parameters block too short (%u < %zu)\n", >> + connector->base.id, connector->name, >> + block->num_bytes, >> + DISPLAYID_DISPLAY_PARAMS_MIN_LEN); >> + continue; >> + } >> >> - /* >> - * We're only interested in the base section here, no need to >> - * iterate further. >> - */ >> - break; >> + tech = FIELD_GET(DISPLAYID_DISPLAY_PARAMS_DEVICE_TECH, >> + params->device_tech_byte); >> + >> + drm_dbg_kms(connector->dev, >> + "[CONNECTOR:%d:%s] DisplayID Display Parameters: device technology %u\n", >> + connector->base.id, connector->name, tech); >> + >> + switch (tech) { >> + case 1: /* LCD */ >> + info->did_panel_type = DRM_MODE_PANEL_TYPE_LCD; >> + break; >> + case 2: /* OLED */ >> + info->did_panel_type = DRM_MODE_PANEL_TYPE_OLED; >> + break; >> + default: >> + break; >> + } >> + } > > Please tell copilot to not add so much crap in the iterator block. Add > functions. Add the first function as a refactor for non_desktop, add > more stuff on top, i.e. split this into multiple patches. > > BR, > Jani. > > >> } >> displayid_iter_end(&iter); >> } >> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h >> index c398dbc68bbc..b95aec34ddb7 100644 >> --- a/include/drm/drm_connector.h >> +++ b/include/drm/drm_connector.h >> @@ -899,6 +899,12 @@ struct drm_display_info { >> * @amd_vsdb: AMD-specific VSDB information. >> */ >> struct drm_amd_vsdb_info amd_vsdb; >> + >> + /** >> + * @did_panel_type: Panel type from DisplayID Display Parameters >> + * Data Block (tag 0x21). Uses DRM_MODE_PANEL_TYPE_* constants. >> + */ >> + u8 did_panel_type; >> }; >> >> int drm_display_info_set_bus_formats(struct drm_display_info *info, >> diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h >> index 3693d82b5279..d7ca1040b92e 100644 >> --- a/include/uapi/drm/drm_mode.h >> +++ b/include/uapi/drm/drm_mode.h >> @@ -169,6 +169,7 @@ extern "C" { >> /* Panel type property */ >> #define DRM_MODE_PANEL_TYPE_UNKNOWN 0 >> #define DRM_MODE_PANEL_TYPE_OLED 1 >> +#define DRM_MODE_PANEL_TYPE_LCD 2 >> >> /* >> * DRM_MODE_ROTATE_<degrees> > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Claude review: drm/edid: parse panel type from DisplayID 2.x Display Parameters block 2026-05-14 6:54 ` [PATCH 1/2] drm/edid: parse panel type from DisplayID 2.x Display Parameters block Chenyu Chen 2026-05-15 8:23 ` Jani Nikula @ 2026-05-16 1:17 ` Claude Code Review Bot 1 sibling, 0 replies; 8+ messages in thread From: Claude Code Review Bot @ 2026-05-16 1:17 UTC (permalink / raw) To: dri-devel-reviews Patch Review **Struct layout and minimum length check — looks correct.** The `displayid_display_params_block` struct places `device_tech_byte` at payload offset 27 (absolute block offset 0x1E), matching the spec reference. The `DISPLAYID_DISPLAY_PARAMS_MIN_LEN` correctly computes 29 (the struct payload excluding the `displayid_block` header), ensuring `device_tech_byte` is accessible before it's read: ```c if (block->num_bytes < DISPLAYID_DISPLAY_PARAMS_MIN_LEN) { ... continue; } ``` **Private field access in `displayid_iter`.** The patch accesses `iter.section` directly: ```c const u8 *section = NULL; ... if (section != iter.section) { ... section = iter.section; } ``` The `displayid_iter` struct is annotated with `Do not access directly, this is private.` While `drm_edid.c` is core DRM code and uses the internal header, this still violates the stated API contract. Consider adding an accessor like `displayid_section()` alongside the existing `displayid_version()` and `displayid_primary_use()`. Alternatively, a boolean `displayid_is_v2_headmount()` helper that encapsulates the VR/AR check might be cleaner, so the section-tracking remains internal to the iterator implementation. **Behavior change from removing the `break` — intentional but worth noting in the commit message.** The old code: ```c displayid_iter_for_each(block, &iter) { // log + VR/AR check break; // only first block of first section } ``` The new code iterates **all blocks across all sections**. This is required to find the Display Parameters block, and the VR/AR detection is correctly refactored to fire once per section via the `section` pointer guard. However, the commit message doesn't mention this change in iteration scope. It would be helpful to note that the function now processes all DisplayID sections/blocks, not just the first. **Minor: magic numbers in the switch.** ```c case 1: /* LCD */ info->did_panel_type = DRM_MODE_PANEL_TYPE_LCD; break; case 2: /* OLED */ info->did_panel_type = DRM_MODE_PANEL_TYPE_OLED; break; ``` These match the spec (Display Device Technology: 001b = LCD, 010b = OLED). The comments are sufficient, but named constants in the header (e.g. `DISPLAYID_DEVICE_TECH_LCD = 1`, `DISPLAYID_DEVICE_TECH_OLED = 2`) would be slightly more self-documenting and consistent with the kernel style for spec-derived values. **Missing update to `drm_panel_type_enum_list`.** The new `DRM_MODE_PANEL_TYPE_LCD` value is added to `drm_mode.h` but the enum registration in `drm_connector.c` is not updated: ```c static const struct drm_prop_enum_list drm_panel_type_enum_list[] = { { DRM_MODE_PANEL_TYPE_UNKNOWN, "unknown" }, { DRM_MODE_PANEL_TYPE_OLED, "OLED" }, // missing: { DRM_MODE_PANEL_TYPE_LCD, "LCD" }, }; ``` Without this, `DRM_MODE_PANEL_TYPE_LCD` cannot actually be used as a property value. This should be part of this patch (since this is where the UAPI constant is introduced). **Overall:** Structurally solid parsing code, but needs the enum list update and preferably an accessor for `iter.section`. --- --- Generated by Claude Code Patch Reviewer ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/2] drm/amd/display: use DisplayID panel type in dm_set_panel_type 2026-05-14 6:54 [PATCH 0/2] drm: detect panel type from DisplayID 2.x Chenyu Chen 2026-05-14 6:54 ` [PATCH 1/2] drm/edid: parse panel type from DisplayID 2.x Display Parameters block Chenyu Chen @ 2026-05-14 6:54 ` Chenyu Chen 2026-05-16 1:17 ` Claude review: " Claude Code Review Bot 2026-05-16 1:17 ` Claude review: drm: detect panel type from DisplayID 2.x Claude Code Review Bot 2 siblings, 1 reply; 8+ messages in thread From: Chenyu Chen @ 2026-05-14 6:54 UTC (permalink / raw) To: amd-gfx, dri-devel Cc: Harry Wentland, Leo Li, Ray Wu, Limonciello Mario, Jani Nikula, Chenyu Chen, Mario Limonciello Wire up the newly parsed did_panel_type from drm_display_info into amdgpu_dm's panel type detection path. When neither the AMD VSDB nor DPCD determines the panel type, fall back to the DisplayID Display Device Technology field to set PANEL_TYPE_LCD or PANEL_TYPE_OLED accordingly. Assisted-by: Copilot:Claude-Opus-4.6 Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com> --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index e42a5eecdf46..353a4982333d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3944,11 +3944,13 @@ static void dm_set_panel_type(struct amdgpu_dm_connector *aconnector) link->panel_type = PANEL_TYPE_OLED; } - /* - * TODO: get panel type from DID2 that has device technology field - * to specify if it's OLED or not. But we need to wait for DID2 - * support in DC and EDID parser to be able to use it here. - */ + /* If VSDB and DPCD didn't determine panel type, check DID */ + if (link->panel_type == PANEL_TYPE_NONE) { + if (display_info->did_panel_type == DRM_MODE_PANEL_TYPE_LCD) + link->panel_type = PANEL_TYPE_LCD; + else if (display_info->did_panel_type == DRM_MODE_PANEL_TYPE_OLED) + link->panel_type = PANEL_TYPE_OLED; + } if (link->panel_type == PANEL_TYPE_NONE) { struct drm_amd_vsdb_info *vsdb = &display_info->amd_vsdb; -- 2.43.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Claude review: drm/amd/display: use DisplayID panel type in dm_set_panel_type 2026-05-14 6:54 ` [PATCH 2/2] drm/amd/display: use DisplayID panel type in dm_set_panel_type Chenyu Chen @ 2026-05-16 1:17 ` Claude Code Review Bot 0 siblings, 0 replies; 8+ messages in thread From: Claude Code Review Bot @ 2026-05-16 1:17 UTC (permalink / raw) To: dri-devel-reviews Patch Review **Placement of the DID2 fallback — correct.** The new check is inserted after VSDB + DPCD and before the Samsung heuristic, which matches the priority the TODO comment described: ```c /* If VSDB and DPCD didn't determine panel type, check DID */ if (link->panel_type == PANEL_TYPE_NONE) { if (display_info->did_panel_type == DRM_MODE_PANEL_TYPE_LCD) link->panel_type = PANEL_TYPE_LCD; else if (display_info->did_panel_type == DRM_MODE_PANEL_TYPE_OLED) link->panel_type = PANEL_TYPE_OLED; } ``` This correctly gates on `PANEL_TYPE_NONE`, so higher-priority detection (VSDB, DPCD) is not overridden. **Bug: property-setting code not updated for LCD.** The existing code at the end of `dm_set_panel_type()` (untouched by this patch) is: ```c if (link->panel_type == PANEL_TYPE_OLED) drm_object_property_set_value(&connector->base, adev_to_drm(adev)->mode_config.panel_type_property, DRM_MODE_PANEL_TYPE_OLED); else drm_object_property_set_value(&connector->base, adev_to_drm(adev)->mode_config.panel_type_property, DRM_MODE_PANEL_TYPE_UNKNOWN); ``` If DID2 detects LCD, `link->panel_type` becomes `PANEL_TYPE_LCD` (value 1 from `dc_types.h`). This falls into the `else` branch, and the userspace-visible property is set to `DRM_MODE_PANEL_TYPE_UNKNOWN`. The LCD detection works internally within the driver but is invisible to userspace. This should be updated to also handle `PANEL_TYPE_LCD`: ```c if (link->panel_type == PANEL_TYPE_OLED) ...DRM_MODE_PANEL_TYPE_OLED; else if (link->panel_type == PANEL_TYPE_LCD) ...DRM_MODE_PANEL_TYPE_LCD; else ...DRM_MODE_PANEL_TYPE_UNKNOWN; ``` **Style nit: mixing UAPI and internal constants in the comparison.** ```c if (display_info->did_panel_type == DRM_MODE_PANEL_TYPE_LCD) link->panel_type = PANEL_TYPE_LCD; ``` This compares a `DRM_MODE_PANEL_TYPE_*` (UAPI) value against the same namespace and assigns a `PANEL_TYPE_*` (DC internal) value. It works because the values happen to map correctly, but it couples the driver to the UAPI constants. The `did_panel_type` field in `drm_display_info` uses UAPI constants by design (it's DRM core), so this cross-namespace mapping is unavoidable here. Just be aware that if either namespace is reordered independently, this breaks silently. **Overall:** The fallback logic is correct and well-placed. The missing property-setting update for LCD is the main issue that should be fixed before merging. --- Generated by Claude Code Patch Reviewer ^ permalink raw reply [flat|nested] 8+ messages in thread
* Claude review: drm: detect panel type from DisplayID 2.x 2026-05-14 6:54 [PATCH 0/2] drm: detect panel type from DisplayID 2.x Chenyu Chen 2026-05-14 6:54 ` [PATCH 1/2] drm/edid: parse panel type from DisplayID 2.x Display Parameters block Chenyu Chen 2026-05-14 6:54 ` [PATCH 2/2] drm/amd/display: use DisplayID panel type in dm_set_panel_type Chenyu Chen @ 2026-05-16 1:17 ` Claude Code Review Bot 2 siblings, 0 replies; 8+ messages in thread From: Claude Code Review Bot @ 2026-05-16 1:17 UTC (permalink / raw) To: dri-devel-reviews Overall Series Review Subject: drm: detect panel type from DisplayID 2.x Author: Chenyu Chen <chen-yu.chen@amd.com> Patches: 5 Reviewed: 2026-05-16T11:17:30.013253 --- This 2-patch series adds DisplayID v2.x Display Parameters Data Block parsing to detect LCD vs OLED panels, and wires it into amdgpu_dm as a fallback panel type detection path. The general approach is sound: it fills a longstanding TODO in the amdgpu_dm code. **However, there is a significant gap across the series:** `DRM_MODE_PANEL_TYPE_LCD` is added to the UAPI header (`drm_mode.h`) but: 1. The `drm_panel_type_enum_list` in `drm_connector.c` is not updated to include LCD, so the `panel_type` property enum doesn't recognize value 2. 2. The property-setting code at the end of `dm_set_panel_type()` is not updated to expose LCD — it only maps `PANEL_TYPE_OLED` → `DRM_MODE_PANEL_TYPE_OLED` and everything else → `DRM_MODE_PANEL_TYPE_UNKNOWN`. This means a DID2-detected LCD panel will correctly set `link->panel_type = PANEL_TYPE_LCD` internally, but userspace will see `DRM_MODE_PANEL_TYPE_UNKNOWN` from the property, and the enum property likely cannot even accept value 2. The new UAPI constant is effectively dead code. --- --- Generated by Claude Code Patch Reviewer ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-05-16 1:17 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-05-14 6:54 [PATCH 0/2] drm: detect panel type from DisplayID 2.x Chenyu Chen 2026-05-14 6:54 ` [PATCH 1/2] drm/edid: parse panel type from DisplayID 2.x Display Parameters block Chenyu Chen 2026-05-15 8:23 ` Jani Nikula 2026-05-15 23:47 ` Leo Li 2026-05-16 1:17 ` Claude review: " Claude Code Review Bot 2026-05-14 6:54 ` [PATCH 2/2] drm/amd/display: use DisplayID panel type in dm_set_panel_type Chenyu Chen 2026-05-16 1:17 ` Claude review: " Claude Code Review Bot 2026-05-16 1:17 ` Claude review: drm: detect panel type from DisplayID 2.x Claude Code Review Bot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox