Add support for EDID based quirks which can be queried outside of the
EDID parser iteself by DRM core and drivers. There at least two such
quirks applicable to all drivers: the DPCD register access probe quirk
and the 128b/132b DPRX Lane Count Conversion quirk (see 3.5.2.16.3 in
the v2.1a DP Standard). The latter quirk applies to panels with specific
EDID panel names, accordingly add support for defining quirks based on
the EDID panel name.

Cc: Ville Syrjälä <ville.syrj...@linux.intel.com>
Cc: Jani Nikula <jani.nik...@linux.intel.com>
Signed-off-by: Imre Deak <imre.d...@intel.com>
---
 drivers/gpu/drm/drm_edid.c  | 33 ++++++++++++++++++++++++++-------
 include/drm/drm_connector.h |  5 +++++
 include/drm/drm_edid.h      |  5 +++++
 3 files changed, 36 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 74e77742b2bd4..e867315253493 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -114,15 +114,21 @@ struct drm_edid_match_closure {
 #define LEVEL_GTF2     2
 #define LEVEL_CVT      3
 
-#define EDID_QUIRK(vend_chr_0, vend_chr_1, vend_chr_2, product_id, _quirks) \
+#define PANEL_NAME_ANY NULL
+
+#define DRM_EDID_QUIRK(_panel_id, _panel_name, _quirks) \
 { \
        .ident = { \
-               .panel_id = drm_edid_encode_panel_id(vend_chr_0, vend_chr_1, \
-                                                    vend_chr_2, product_id), \
+               .panel_id = _panel_id, \
+               .name = _panel_name, \
        }, \
        .quirks = _quirks \
 }
 
+#define EDID_QUIRK(vend_chr_0, vend_chr_1, vend_chr_2, product_id, _quirks) \
+       DRM_EDID_QUIRK(drm_edid_encode_panel_id(vend_chr_0, vend_chr_1, 
vend_chr_2, product_id), \
+                      PANEL_NAME_ANY, _quirks)
+
 static const struct edid_quirk {
        const struct drm_edid_ident ident;
        u32 quirks;
@@ -248,6 +254,9 @@ static const struct edid_quirk {
        EDID_QUIRK('A', 'U', 'O', 0x1111, EDID_QUIRK_NON_DESKTOP),
 };
 
+static const struct edid_quirk global_edid_quirk_list[] = {
+};
+
 /*
  * Autogenerated from the DMT spec.
  * This table is copied from xfree86/modes/xf86EdidModes.c.
@@ -2937,13 +2946,14 @@ EXPORT_SYMBOL(drm_edid_duplicate);
  *
  * Return: A u32 represents the quirks to apply.
  */
-static u32 edid_get_quirks(const struct drm_edid *drm_edid)
+static u32 edid_get_quirks(const struct drm_edid *drm_edid,
+                          const struct edid_quirk *quirk_list, int 
quirk_list_size)
 {
        const struct edid_quirk *quirk;
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(edid_quirk_list); i++) {
-               quirk = &edid_quirk_list[i];
+       for (i = 0; i < quirk_list_size; i++) {
+               quirk = &quirk_list[i];
                if (drm_edid_match(drm_edid, &quirk->ident))
                        return quirk->quirks;
        }
@@ -6660,7 +6670,10 @@ static void update_display_info(struct drm_connector 
*connector,
 
        edid = drm_edid->edid;
 
-       info->quirks = edid_get_quirks(drm_edid);
+       info->quirks = edid_get_quirks(drm_edid, edid_quirk_list,
+                                      ARRAY_SIZE(edid_quirk_list));
+       info->global_quirks = edid_get_quirks(drm_edid, global_edid_quirk_list,
+                                             
ARRAY_SIZE(global_edid_quirk_list));
 
        info->width_mm = edid->width_cm * 10;
        info->height_mm = edid->height_cm * 10;
@@ -7566,3 +7579,9 @@ bool drm_edid_is_digital(const struct drm_edid *drm_edid)
                drm_edid->edid->input & DRM_EDID_INPUT_DIGITAL;
 }
 EXPORT_SYMBOL(drm_edid_is_digital);
+
+bool drm_edid_has_quirk(struct drm_connector *connector, enum drm_edid_quirk 
quirk)
+{
+       return connector->display_info.global_quirks & BIT(quirk);
+}
+EXPORT_SYMBOL(drm_edid_has_quirk);
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 73903c3c842f3..996ecf229f8c7 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -847,6 +847,11 @@ struct drm_display_info {
         */
        u32 quirks;
 
+       /**
+        * @global_quirks: EDID based quirks. Can be queried by DRM core and 
drivers.
+        */
+       u32 global_quirks;
+
        /**
         * @source_physical_address: Source Physical Address from HDMI
         * Vendor-Specific Data Block, for CEC usage.
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index b38409670868d..3d8e168521c82 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -109,6 +109,10 @@ struct detailed_data_string {
 #define DRM_EDID_CVT_FLAGS_STANDARD_BLANKING (1 << 3)
 #define DRM_EDID_CVT_FLAGS_REDUCED_BLANKING  (1 << 4)
 
+enum drm_edid_quirk {
+       DRM_EDID_QUIRK_NONE,
+};
+
 struct detailed_data_monitor_range {
        u8 min_vfreq;
        u8 max_vfreq;
@@ -476,5 +480,6 @@ void drm_edid_print_product_id(struct drm_printer *p,
 u32 drm_edid_get_panel_id(const struct drm_edid *drm_edid);
 bool drm_edid_match(const struct drm_edid *drm_edid,
                    const struct drm_edid_ident *ident);
+bool drm_edid_has_quirk(struct drm_connector *connector, enum drm_edid_quirk 
quirk);
 
 #endif /* __DRM_EDID_H__ */
-- 
2.44.2

Reply via email to