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 <[email protected]>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 120 ++++++++++--------
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  14 --
 2 files changed, 68 insertions(+), 66 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 48e12f9a1818..717e8d3feb8d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3823,6 +3823,66 @@ static struct drm_mode_config_helper_funcs 
amdgpu_dm_mode_config_helperfuncs = {
        .atomic_commit_setup = amdgpu_dm_atomic_setup_commit,
 };
 
+#define DDC_MANUFACTURERNAME_SAMSUNG 0x2D4C
+
+static void dm_set_panel_type(struct amdgpu_dm_connector *aconnector)
+{
+       struct drm_connector *connector = &aconnector->base;
+       struct drm_display_info *display_info = &connector->display_info;
+       struct dc_link *link = aconnector->dc_link;
+       struct amdgpu_device *adev;
+
+       adev = drm_to_adev(connector->dev);
+
+       link->panel_type = PANEL_TYPE_NONE;
+
+       switch (display_info->amd_vsdb.panel_type) {
+       case AMD_VSDB_PANEL_TYPE_OLED:
+               link->panel_type = PANEL_TYPE_OLED;
+               break;
+       case AMD_VSDB_PANEL_TYPE_MINILED:
+               link->panel_type = PANEL_TYPE_MINILED;
+               break;
+       }
+
+       /* If VSDB didn't determine panel type, check DPCD ext caps */
+       if (link->panel_type == PANEL_TYPE_NONE) {
+               if (link->dpcd_sink_ext_caps.bits.miniled == 1)
+                       link->panel_type = PANEL_TYPE_MINILED;
+               if (link->dpcd_sink_ext_caps.bits.oled == 1)
+                       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 (link->panel_type == PANEL_TYPE_NONE) {
+               struct drm_amd_vsdb_info *vsdb = &display_info->amd_vsdb;
+               u32 lum1_max = vsdb->luminance_range1.max_luminance;
+               u32 lum2_max = vsdb->luminance_range2.max_luminance;
+
+               if (vsdb->version && link->local_sink &&
+                   link->local_sink->edid_caps.manufacturer_id ==
+                   DDC_MANUFACTURERNAME_SAMSUNG &&
+                   lum1_max >= ((lum2_max * 3) / 2))
+                       link->panel_type = PANEL_TYPE_MINILED;
+       }
+
+       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);
+
+       drm_dbg_kms(aconnector->base.dev, "Panel type: %d\n", link->panel_type);
+}
+
 static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
 {
        const struct drm_panel_backlight_quirk *panel_backlight_quirk;
@@ -3844,10 +3904,6 @@ static void update_connector_ext_caps(struct 
amdgpu_dm_connector *aconnector)
        caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps;
        caps->aux_support = false;
 
-       drm_object_property_set_value(&conn_base->base,
-                                     
adev_to_drm(adev)->mode_config.panel_type_property,
-                                     caps->ext_caps->bits.oled ? 
DRM_MODE_PANEL_TYPE_OLED : DRM_MODE_PANEL_TYPE_UNKNOWN);
-
        if (caps->ext_caps->bits.oled == 1
            /*
             * ||
@@ -4021,6 +4077,7 @@ void amdgpu_dm_update_connector_after_detect(
 
                amdgpu_dm_update_freesync_caps(connector, aconnector->drm_edid);
                update_connector_ext_caps(aconnector);
+               dm_set_panel_type(aconnector);
        } else {
                hdmi_cec_unset_edid(aconnector);
                drm_dp_cec_unset_edid(&aconnector->dm_dp_aux.aux);
@@ -13167,56 +13224,15 @@ static void parse_edid_displayid_vrr(struct 
drm_connector *connector,
        }
 }
 
-static int parse_amd_vsdb(struct amdgpu_dm_connector *aconnector,
-                         const struct edid *edid, struct amdgpu_hdmi_vsdb_info 
*vsdb_info)
+static int get_amd_vsdb(struct amdgpu_dm_connector *aconnector,
+                       struct amdgpu_hdmi_vsdb_info *vsdb_info)
 {
-       u8 *edid_ext = NULL;
-       int i;
-       int j = 0;
-       int total_ext_block_len;
-
-       if (edid == NULL || edid->extensions == 0)
-               return -ENODEV;
-
-       /* Find DisplayID extension */
-       for (i = 0; i < edid->extensions; i++) {
-               edid_ext = (void *)(edid + (i + 1));
-               if (edid_ext[0] == DISPLAYID_EXT)
-                       break;
-       }
-
-       total_ext_block_len = EDID_LENGTH * edid->extensions;
-       while (j < total_ext_block_len - sizeof(struct amd_vsdb_block)) {
-               struct amd_vsdb_block *amd_vsdb = (struct amd_vsdb_block 
*)&edid_ext[j];
-               unsigned int ieeeId = (amd_vsdb->ieee_id[2] << 16) | 
(amd_vsdb->ieee_id[1] << 8) | (amd_vsdb->ieee_id[0]);
-
-               if (ieeeId == 
HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_IEEE_REGISTRATION_ID &&
-                               amd_vsdb->version == 
HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3) {
-                       u8 panel_type;
-                       vsdb_info->replay_mode = (amd_vsdb->feature_caps & 
AMD_VSDB_VERSION_3_FEATURECAP_REPLAYMODE) ? true : false;
-                       vsdb_info->amd_vsdb_version = 
HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3;
-                       drm_dbg_kms(aconnector->base.dev, "Panel supports 
Replay Mode: %d\n", vsdb_info->replay_mode);
-                       panel_type = (amd_vsdb->color_space_eotf_support & 
AMD_VDSB_VERSION_3_PANEL_TYPE_MASK) >> AMD_VDSB_VERSION_3_PANEL_TYPE_SHIFT;
-                       switch (panel_type) {
-                       case AMD_VSDB_PANEL_TYPE_OLED:
-                               aconnector->dc_link->panel_type = 
PANEL_TYPE_OLED;
-                               break;
-                       case AMD_VSDB_PANEL_TYPE_MINILED:
-                               aconnector->dc_link->panel_type = 
PANEL_TYPE_MINILED;
-                               break;
-                       default:
-                               aconnector->dc_link->panel_type = 
PANEL_TYPE_NONE;
-                               break;
-                       }
-                       drm_dbg_kms(aconnector->base.dev, "Panel type: %d\n",
-                                   aconnector->dc_link->panel_type);
+       struct drm_connector *connector = &aconnector->base;
 
-                       return true;
-               }
-               j++;
-       }
+       vsdb_info->replay_mode = connector->display_info.amd_vsdb.replay_mode;
+       vsdb_info->amd_vsdb_version = connector->display_info.amd_vsdb.version;
 
-       return false;
+       return connector->display_info.amd_vsdb.version != 0;
 }
 
 static int parse_hdmi_amd_vsdb(struct amdgpu_dm_connector *aconnector,
@@ -13319,7 +13335,7 @@ void amdgpu_dm_update_freesync_caps(struct 
drm_connector *connector,
                                freesync_capable = true;
                }
 
-               parse_amd_vsdb(amdgpu_dm_connector, edid, &vsdb_info);
+               get_amd_vsdb(amdgpu_dm_connector, &vsdb_info);
 
                if (vsdb_info.replay_mode) {
                        amdgpu_dm_connector->vsdb_info.replay_mode = 
vsdb_info.replay_mode;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index d1a14e0c12bd..63ce1f52b697 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -53,12 +53,6 @@
 
 #define AMDGPU_DMUB_NOTIFICATION_MAX 8
 
-#define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_IEEE_REGISTRATION_ID 0x00001A
-#define AMD_VSDB_VERSION_3_FEATURECAP_REPLAYMODE 0x40
-#define AMD_VDSB_VERSION_3_PANEL_TYPE_MASK 0xC0
-#define AMD_VDSB_VERSION_3_PANEL_TYPE_SHIFT 6
-#define HDMI_AMD_VENDOR_SPECIFIC_DATA_BLOCK_VERSION_3 0x3
-
 enum amd_vsdb_panel_type {
        AMD_VSDB_PANEL_TYPE_DEFAULT = 0,
        AMD_VSDB_PANEL_TYPE_MINILED,
@@ -97,14 +91,6 @@ struct dc_plane_state;
 struct dmub_notification;
 struct dmub_cmd_fused_request;
 
-struct amd_vsdb_block {
-       unsigned char ieee_id[3];
-       unsigned char version;
-       unsigned char feature_caps;
-       unsigned char reserved[3];
-       unsigned char color_space_eotf_support;
-};
-
 struct common_irq_params {
        struct amdgpu_device *adev;
        enum dc_irq_source irq_src;
-- 
2.43.0

Reply via email to