Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/edid: Parse AMD Vendor-Specific Data Block

Parse the AMD VSDB v3 from CTA extension blocks and store the result
in struct drm_amd_vsdb_info, a new field of drm_display_info. This
includes replay mode, panel type, and luminance ranges.

Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>

authored by

Chenyu Chen and committed by
Alex Deucher
118362a9 57ce498f

+110
+72
drivers/gpu/drm/drm_edid.c
··· 99 99 }; 100 100 101 101 #define MICROSOFT_IEEE_OUI 0xca125c 102 + #define AMD_IEEE_OUI 0x00001A 103 + 104 + #define AMD_VSDB_V3_PAYLOAD_MIN_LEN 15 105 + #define AMD_VSDB_V3_PAYLOAD_MAX_LEN 20 106 + 107 + struct amd_vsdb_v3_payload { 108 + u8 oui[3]; 109 + u8 version; 110 + u8 feature_caps; 111 + u8 rsvd0[3]; 112 + u8 cs_eotf_support; 113 + u8 lum1_max; 114 + u8 lum1_min; 115 + u8 lum2_max; 116 + u8 lum2_min; 117 + u8 rsvd1[2]; 118 + /* 119 + * Bytes beyond AMD_VSDB_V3_PAYLOAD_MIN_LEN are optional; a 120 + * monitor may provide a payload as short as 15 bytes. Always 121 + * check cea_db_payload_len() before accessing extra[]. 122 + */ 123 + u8 extra[AMD_VSDB_V3_PAYLOAD_MAX_LEN - AMD_VSDB_V3_PAYLOAD_MIN_LEN]; 124 + } __packed; 102 125 103 126 struct detailed_mode_closure { 104 127 struct drm_connector *connector; ··· 5228 5205 cea_db_payload_len(db) == 21; 5229 5206 } 5230 5207 5208 + static bool cea_db_is_amd_vsdb(const struct cea_db *db) 5209 + { 5210 + return cea_db_is_vendor(db, AMD_IEEE_OUI) && 5211 + cea_db_payload_len(db) >= AMD_VSDB_V3_PAYLOAD_MIN_LEN && 5212 + cea_db_payload_len(db) <= AMD_VSDB_V3_PAYLOAD_MAX_LEN; 5213 + } 5214 + 5231 5215 static bool cea_db_is_vcdb(const struct cea_db *db) 5232 5216 { 5233 5217 return cea_db_is_extended_tag(db, CTA_EXT_DB_VIDEO_CAP) && ··· 6431 6401 connector->base.id, connector->name, version, db[5]); 6432 6402 } 6433 6403 6404 + static void drm_parse_amd_vsdb(struct drm_connector *connector, 6405 + const struct cea_db *db) 6406 + { 6407 + struct drm_display_info *info = &connector->display_info; 6408 + const u8 *data = cea_db_data(db); 6409 + const struct amd_vsdb_v3_payload *p; 6410 + 6411 + p = (const struct amd_vsdb_v3_payload *)data; 6412 + 6413 + if (p->version != 0x03) { 6414 + drm_dbg_kms(connector->dev, 6415 + "[CONNECTOR:%d:%s] Unsupported AMD VSDB version %u\n", 6416 + connector->base.id, connector->name, p->version); 6417 + return; 6418 + } 6419 + 6420 + info->amd_vsdb.version = p->version; 6421 + info->amd_vsdb.replay_mode = p->feature_caps & 0x40; 6422 + info->amd_vsdb.panel_type = (p->cs_eotf_support & 0xC0) >> 6; 6423 + info->amd_vsdb.luminance_range1.max_luminance = p->lum1_max; 6424 + info->amd_vsdb.luminance_range1.min_luminance = p->lum1_min; 6425 + info->amd_vsdb.luminance_range2.max_luminance = p->lum2_max; 6426 + info->amd_vsdb.luminance_range2.min_luminance = p->lum2_min; 6427 + 6428 + /* 6429 + * The AMD VSDB v3 payload length is variable (15..20 bytes). 6430 + * All fields through p->rsvd1 (byte 14) are always present, 6431 + * but p->extra[] (bytes 15+) may not be. Any future access to 6432 + * extra[] must be guarded with a runtime length check to avoid 6433 + * out-of-bounds reads on shorter (but spec-valid) payloads. 6434 + * For example: 6435 + * 6436 + * int len = cea_db_payload_len(db); 6437 + * 6438 + * if (len > AMD_VSDB_V3_PAYLOAD_MIN_LEN) 6439 + * info->amd_vsdb.foo = p->extra[0]; 6440 + */ 6441 + } 6442 + 6434 6443 static void drm_parse_cea_ext(struct drm_connector *connector, 6435 6444 const struct drm_edid *drm_edid) 6436 6445 { ··· 6518 6449 drm_parse_hdmi_forum_scds(connector, data); 6519 6450 else if (cea_db_is_microsoft_vsdb(db)) 6520 6451 drm_parse_microsoft_vsdb(connector, data); 6452 + else if (cea_db_is_amd_vsdb(db)) 6453 + drm_parse_amd_vsdb(connector, db); 6521 6454 else if (cea_db_is_y420cmdb(db)) 6522 6455 parse_cta_y420cmdb(connector, db, &y420cmdb_map); 6523 6456 else if (cea_db_is_y420vdb(db)) ··· 6712 6641 info->quirks = 0; 6713 6642 6714 6643 info->source_physical_address = CEC_PHYS_ADDR_INVALID; 6644 + memset(&info->amd_vsdb, 0, sizeof(info->amd_vsdb)); 6715 6645 } 6716 6646 6717 6647 static void update_displayid_info(struct drm_connector *connector,
+38
include/drm/drm_connector.h
··· 694 694 }; 695 695 696 696 /** 697 + * struct drm_amd_vsdb_info - AMD-specific VSDB information 698 + * 699 + * This structure holds information parsed from the AMD Vendor-Specific Data 700 + * Block (VSDB) version 3. 701 + */ 702 + struct drm_amd_vsdb_info { 703 + /** 704 + * @version: Version of the Vendor-Specific Data Block (VSDB) 705 + */ 706 + u8 version; 707 + 708 + /** 709 + * @replay_mode: Panel Replay supported 710 + */ 711 + bool replay_mode; 712 + 713 + /** 714 + * @panel_type: Panel technology type 715 + */ 716 + u8 panel_type; 717 + 718 + /** 719 + * @luminance_range1: Luminance for max back light 720 + */ 721 + struct drm_luminance_range_info luminance_range1; 722 + 723 + /** 724 + * @luminance_range2: Luminance for min back light 725 + */ 726 + struct drm_luminance_range_info luminance_range2; 727 + }; 728 + 729 + /** 697 730 * struct drm_display_info - runtime data about the connected sink 698 731 * 699 732 * Describes a given display (e.g. CRT or flat panel) and its limitations. For ··· 916 883 * Defaults to CEC_PHYS_ADDR_INVALID (0xffff). 917 884 */ 918 885 u16 source_physical_address; 886 + 887 + /** 888 + * @amd_vsdb: AMD-specific VSDB information. 889 + */ 890 + struct drm_amd_vsdb_info amd_vsdb; 919 891 }; 920 892 921 893 int drm_display_info_set_bus_formats(struct drm_display_info *info,