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/amd/display: Use drm_display_info for AMD VSDB data

Replace the raw EDID byte-walking in parse_amd_vsdb() with a read
from connector->display_info.amd_vsdb, now populated by drm_edid.

Factor out panel type determination into dm_set_panel_type(), which
checks VSDB panel_type, DPCD ext caps, and a luminance heuristic as
fallbacks.

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
bf3fc94c 118362a9

+68 -66
+68 -52
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
··· 3833 3833 .atomic_commit_setup = amdgpu_dm_atomic_setup_commit, 3834 3834 }; 3835 3835 3836 + #define DDC_MANUFACTURERNAME_SAMSUNG 0x2D4C 3837 + 3838 + static void dm_set_panel_type(struct amdgpu_dm_connector *aconnector) 3839 + { 3840 + struct drm_connector *connector = &aconnector->base; 3841 + struct drm_display_info *display_info = &connector->display_info; 3842 + struct dc_link *link = aconnector->dc_link; 3843 + struct amdgpu_device *adev; 3844 + 3845 + adev = drm_to_adev(connector->dev); 3846 + 3847 + link->panel_type = PANEL_TYPE_NONE; 3848 + 3849 + switch (display_info->amd_vsdb.panel_type) { 3850 + case AMD_VSDB_PANEL_TYPE_OLED: 3851 + link->panel_type = PANEL_TYPE_OLED; 3852 + break; 3853 + case AMD_VSDB_PANEL_TYPE_MINILED: 3854 + link->panel_type = PANEL_TYPE_MINILED; 3855 + break; 3856 + } 3857 + 3858 + /* If VSDB didn't determine panel type, check DPCD ext caps */ 3859 + if (link->panel_type == PANEL_TYPE_NONE) { 3860 + if (link->dpcd_sink_ext_caps.bits.miniled == 1) 3861 + link->panel_type = PANEL_TYPE_MINILED; 3862 + if (link->dpcd_sink_ext_caps.bits.oled == 1) 3863 + link->panel_type = PANEL_TYPE_OLED; 3864 + } 3865 + 3866 + /* 3867 + * TODO: get panel type from DID2 that has device technology field 3868 + * to specify if it's OLED or not. But we need to wait for DID2 3869 + * support in DC and EDID parser to be able to use it here. 3870 + */ 3871 + 3872 + if (link->panel_type == PANEL_TYPE_NONE) { 3873 + struct drm_amd_vsdb_info *vsdb = &display_info->amd_vsdb; 3874 + u32 lum1_max = vsdb->luminance_range1.max_luminance; 3875 + u32 lum2_max = vsdb->luminance_range2.max_luminance; 3876 + 3877 + if (vsdb->version && link->local_sink && 3878 + link->local_sink->edid_caps.manufacturer_id == 3879 + DDC_MANUFACTURERNAME_SAMSUNG && 3880 + lum1_max >= ((lum2_max * 3) / 2)) 3881 + link->panel_type = PANEL_TYPE_MINILED; 3882 + } 3883 + 3884 + if (link->panel_type == PANEL_TYPE_OLED) 3885 + drm_object_property_set_value(&connector->base, 3886 + adev_to_drm(adev)->mode_config.panel_type_property, 3887 + DRM_MODE_PANEL_TYPE_OLED); 3888 + else 3889 + drm_object_property_set_value(&connector->base, 3890 + adev_to_drm(adev)->mode_config.panel_type_property, 3891 + DRM_MODE_PANEL_TYPE_UNKNOWN); 3892 + 3893 + drm_dbg_kms(aconnector->base.dev, "Panel type: %d\n", link->panel_type); 3894 + } 3895 + 3836 3896 static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) 3837 3897 { 3838 3898 const struct drm_panel_backlight_quirk *panel_backlight_quirk; ··· 3913 3853 caps = &adev->dm.backlight_caps[aconnector->bl_idx]; 3914 3854 caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps; 3915 3855 caps->aux_support = false; 3916 - 3917 - drm_object_property_set_value(&conn_base->base, 3918 - adev_to_drm(adev)->mode_config.panel_type_property, 3919 - caps->ext_caps->bits.oled ? DRM_MODE_PANEL_TYPE_OLED : DRM_MODE_PANEL_TYPE_UNKNOWN); 3920 3856 3921 3857 if (caps->ext_caps->bits.oled == 1 3922 3858 /* ··· 4087 4031 4088 4032 amdgpu_dm_update_freesync_caps(connector, aconnector->drm_edid); 4089 4033 update_connector_ext_caps(aconnector); 4034 + dm_set_panel_type(aconnector); 4090 4035 } else { 4091 4036 hdmi_cec_unset_edid(aconnector); 4092 4037 drm_dp_cec_unset_edid(&aconnector->dm_dp_aux.aux); ··· 13212 13155 } 13213 13156 } 13214 13157 13215 - static int parse_amd_vsdb(struct amdgpu_dm_connector *aconnector, 13216 - const struct edid *edid, struct amdgpu_hdmi_vsdb_info *vsdb_info) 13158 + static int get_amd_vsdb(struct amdgpu_dm_connector *aconnector, 13159 + struct amdgpu_hdmi_vsdb_info *vsdb_info) 13217 13160 { 13218 - u8 *edid_ext = NULL; 13219 - int i; 13220 - int j = 0; 13221 - int total_ext_block_len; 13161 + struct drm_connector *connector = &aconnector->base; 13222 13162 13223 - if (edid == NULL || edid->extensions == 0) 13224 - return -ENODEV; 13163 + vsdb_info->replay_mode = connector->display_info.amd_vsdb.replay_mode; 13164 + vsdb_info->amd_vsdb_version = connector->display_info.amd_vsdb.version; 13225 13165 13226 - /* Find DisplayID extension */ 13227 - for (i = 0; i < edid->extensions; i++) { 13228 - edid_ext = (void *)(edid + (i + 1)); 13229 - if (edid_ext[0] == DISPLAYID_EXT) 13230 - break; 13231 - } 13232 - 13233 - total_ext_block_len = EDID_LENGTH * edid->extensions; 13234 - while (j < total_ext_block_len - sizeof(struct amd_vsdb_block)) { 13235 - struct amd_vsdb_block *amd_vsdb = (struct amd_vsdb_block *)&edid_ext[j]; 13236 - unsigned int ieeeId = (amd_vsdb->ieee_id[2] << 16) | (amd_vsdb->ieee_id[1] << 8) | (amd_vsdb->ieee_id[0]); 13237 - 13238 - if (ieeeId == HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_IEEE_REGISTRATION_ID && 13239 - amd_vsdb->version == HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3) { 13240 - u8 panel_type; 13241 - vsdb_info->replay_mode = (amd_vsdb->feature_caps & AMD_VSDB_VERSION_3_FEATURECAP_REPLAYMODE) ? true : false; 13242 - vsdb_info->amd_vsdb_version = HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3; 13243 - drm_dbg_kms(aconnector->base.dev, "Panel supports Replay Mode: %d\n", vsdb_info->replay_mode); 13244 - panel_type = (amd_vsdb->color_space_eotf_support & AMD_VDSB_VERSION_3_PANEL_TYPE_MASK) >> AMD_VDSB_VERSION_3_PANEL_TYPE_SHIFT; 13245 - switch (panel_type) { 13246 - case AMD_VSDB_PANEL_TYPE_OLED: 13247 - aconnector->dc_link->panel_type = PANEL_TYPE_OLED; 13248 - break; 13249 - case AMD_VSDB_PANEL_TYPE_MINILED: 13250 - aconnector->dc_link->panel_type = PANEL_TYPE_MINILED; 13251 - break; 13252 - default: 13253 - aconnector->dc_link->panel_type = PANEL_TYPE_NONE; 13254 - break; 13255 - } 13256 - drm_dbg_kms(aconnector->base.dev, "Panel type: %d\n", 13257 - aconnector->dc_link->panel_type); 13258 - 13259 - return true; 13260 - } 13261 - j++; 13262 - } 13263 - 13264 - return false; 13166 + return connector->display_info.amd_vsdb.version != 0; 13265 13167 } 13266 13168 13267 13169 static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector, ··· 13323 13307 freesync_capable = true; 13324 13308 } 13325 13309 13326 - parse_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info); 13310 + get_amd_vsdb(amdgpu_dm_connector, &vsdb_info); 13327 13311 13328 13312 if (vsdb_info.replay_mode) { 13329 13313 amdgpu_dm_connector->vsdb_info.replay_mode = vsdb_info.replay_mode;
-14
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
··· 53 53 54 54 #define AMDGPU_DMUB_NOTIFICATION_MAX 8 55 55 56 - #define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_IEEE_REGISTRATION_ID 0x00001A 57 - #define AMD_VSDB_VERSION_3_FEATURECAP_REPLAYMODE 0x40 58 - #define AMD_VDSB_VERSION_3_PANEL_TYPE_MASK 0xC0 59 - #define AMD_VDSB_VERSION_3_PANEL_TYPE_SHIFT 6 60 - #define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3 0x3 61 - 62 56 enum amd_vsdb_panel_type { 63 57 AMD_VSDB_PANEL_TYPE_DEFAULT = 0, 64 58 AMD_VSDB_PANEL_TYPE_MINILED, ··· 90 96 struct dc_plane_state; 91 97 struct dmub_notification; 92 98 struct dmub_cmd_fused_request; 93 - 94 - struct amd_vsdb_block { 95 - unsigned char ieee_id[3]; 96 - unsigned char version; 97 - unsigned char feature_caps; 98 - unsigned char reserved[3]; 99 - unsigned char color_space_eotf_support; 100 - }; 101 99 102 100 struct common_irq_params { 103 101 struct amdgpu_device *adev;