drm/i915: Do panel VBT init early if the VBT declares an explicit panel type
authorjsg <jsg@openbsd.org>
Tue, 28 Mar 2023 00:22:33 +0000 (00:22 +0000)
committerjsg <jsg@openbsd.org>
Tue, 28 Mar 2023 00:22:33 +0000 (00:22 +0000)
From Ville Syrjala
bd61a84b5eee4eaf3daf1c69499a4eca1f972ca4 in linux-6.1.y/6.1.20
3f9ffce5765d68775163b8b134c4d7f156b48eec in mainline linux

sys/dev/pci/drm/i915/display/icl_dsi.c
sys/dev/pci/drm/i915/display/intel_bios.c
sys/dev/pci/drm/i915/display/intel_bios.h
sys/dev/pci/drm/i915/display/intel_display_types.h
sys/dev/pci/drm/i915/display/intel_dp.c
sys/dev/pci/drm/i915/display/intel_lvds.c
sys/dev/pci/drm/i915/display/intel_panel.c
sys/dev/pci/drm/i915/display/intel_sdvo.c
sys/dev/pci/drm/i915/display/vlv_dsi.c

index ed4d939..34b3ff9 100644 (file)
@@ -2053,7 +2053,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)
        /* attach connector to encoder */
        intel_connector_attach_encoder(intel_connector, encoder);
 
-       intel_bios_init_panel(dev_priv, &intel_connector->panel, NULL, NULL);
+       intel_bios_init_panel_late(dev_priv, &intel_connector->panel, NULL, NULL);
 
        mutex_lock(&dev->mode_config.mutex);
        intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
index 05a4bea..2242eb0 100644 (file)
@@ -620,14 +620,14 @@ static void dump_pnp_id(struct drm_i915_private *i915,
 
 static int opregion_get_panel_type(struct drm_i915_private *i915,
                                   const struct intel_bios_encoder_data *devdata,
-                                  const struct edid *edid)
+                                  const struct edid *edid, bool use_fallback)
 {
        return intel_opregion_get_panel_type(i915);
 }
 
 static int vbt_get_panel_type(struct drm_i915_private *i915,
                              const struct intel_bios_encoder_data *devdata,
-                             const struct edid *edid)
+                             const struct edid *edid, bool use_fallback)
 {
        const struct bdb_lvds_options *lvds_options;
 
@@ -652,7 +652,7 @@ static int vbt_get_panel_type(struct drm_i915_private *i915,
 
 static int pnpid_get_panel_type(struct drm_i915_private *i915,
                                const struct intel_bios_encoder_data *devdata,
-                               const struct edid *edid)
+                               const struct edid *edid, bool use_fallback)
 {
        const struct bdb_lvds_lfp_data *data;
        const struct bdb_lvds_lfp_data_ptrs *ptrs;
@@ -701,9 +701,9 @@ static int pnpid_get_panel_type(struct drm_i915_private *i915,
 
 static int fallback_get_panel_type(struct drm_i915_private *i915,
                                   const struct intel_bios_encoder_data *devdata,
-                                  const struct edid *edid)
+                                  const struct edid *edid, bool use_fallback)
 {
-       return 0;
+       return use_fallback ? 0 : -1;
 }
 
 enum panel_type {
@@ -715,13 +715,13 @@ enum panel_type {
 
 static int get_panel_type(struct drm_i915_private *i915,
                          const struct intel_bios_encoder_data *devdata,
-                         const struct edid *edid)
+                         const struct edid *edid, bool use_fallback)
 {
        struct {
                const char *name;
                int (*get_panel_type)(struct drm_i915_private *i915,
                                      const struct intel_bios_encoder_data *devdata,
-                                     const struct edid *edid);
+                                     const struct edid *edid, bool use_fallback);
                int panel_type;
        } panel_types[] = {
                [PANEL_TYPE_OPREGION] = {
@@ -744,7 +744,8 @@ static int get_panel_type(struct drm_i915_private *i915,
        int i;
 
        for (i = 0; i < ARRAY_SIZE(panel_types); i++) {
-               panel_types[i].panel_type = panel_types[i].get_panel_type(i915, devdata, edid);
+               panel_types[i].panel_type = panel_types[i].get_panel_type(i915, devdata,
+                                                                         edid, use_fallback);
 
                drm_WARN_ON(&i915->drm, panel_types[i].panel_type > 0xf &&
                            panel_types[i].panel_type != 0xff);
@@ -3208,14 +3209,26 @@ out:
        kfree(oprom_vbt);
 }
 
-void intel_bios_init_panel(struct drm_i915_private *i915,
-                          struct intel_panel *panel,
-                          const struct intel_bios_encoder_data *devdata,
-                          const struct edid *edid)
+static void intel_bios_init_panel(struct drm_i915_private *i915,
+                                 struct intel_panel *panel,
+                                 const struct intel_bios_encoder_data *devdata,
+                                 const struct edid *edid,
+                                 bool use_fallback)
 {
-       init_vbt_panel_defaults(panel);
+       /* already have it? */
+       if (panel->vbt.panel_type >= 0) {
+               drm_WARN_ON(&i915->drm, !use_fallback);
+               return;
+       }
 
-       panel->vbt.panel_type = get_panel_type(i915, devdata, edid);
+       panel->vbt.panel_type = get_panel_type(i915, devdata,
+                                              edid, use_fallback);
+       if (panel->vbt.panel_type < 0) {
+               drm_WARN_ON(&i915->drm, use_fallback);
+               return;
+       }
+
+       init_vbt_panel_defaults(panel);
 
        parse_panel_options(i915, panel);
        parse_generic_dtd(i915, panel);
@@ -3230,6 +3243,21 @@ void intel_bios_init_panel(struct drm_i915_private *i915,
        parse_mipi_sequence(i915, panel);
 }
 
+void intel_bios_init_panel_early(struct drm_i915_private *i915,
+                                struct intel_panel *panel,
+                                const struct intel_bios_encoder_data *devdata)
+{
+       intel_bios_init_panel(i915, panel, devdata, NULL, false);
+}
+
+void intel_bios_init_panel_late(struct drm_i915_private *i915,
+                               struct intel_panel *panel,
+                               const struct intel_bios_encoder_data *devdata,
+                               const struct edid *edid)
+{
+       intel_bios_init_panel(i915, panel, devdata, edid, true);
+}
+
 /**
  * intel_bios_driver_remove - Free any resources allocated by intel_bios_init()
  * @i915: i915 device instance
index e375405..ff1fdd2 100644 (file)
@@ -232,10 +232,13 @@ struct mipi_pps_data {
 } __packed;
 
 void intel_bios_init(struct drm_i915_private *dev_priv);
-void intel_bios_init_panel(struct drm_i915_private *dev_priv,
-                          struct intel_panel *panel,
-                          const struct intel_bios_encoder_data *devdata,
-                          const struct edid *edid);
+void intel_bios_init_panel_early(struct drm_i915_private *dev_priv,
+                                struct intel_panel *panel,
+                                const struct intel_bios_encoder_data *devdata);
+void intel_bios_init_panel_late(struct drm_i915_private *dev_priv,
+                               struct intel_panel *panel,
+                               const struct intel_bios_encoder_data *devdata,
+                               const struct edid *edid);
 void intel_bios_fini_panel(struct intel_panel *panel);
 void intel_bios_driver_remove(struct drm_i915_private *dev_priv);
 bool intel_bios_is_valid_vbt(const void *buf, size_t size);
index 8c8d647..52c7083 100644 (file)
@@ -291,7 +291,7 @@ struct intel_vbt_panel_data {
        struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
 
        /* Feature bits */
-       unsigned int panel_type:4;
+       int panel_type;
        unsigned int lvds_dither:1;
        unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
 
index 9e91071..dd62aea 100644 (file)
@@ -5181,6 +5181,9 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
                return false;
        }
 
+       intel_bios_init_panel_early(dev_priv, &intel_connector->panel,
+                                   encoder->devdata);
+
        intel_pps_init(intel_dp);
 
        /* Cache DPCD and EDID for edp. */
@@ -5215,8 +5218,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
        }
        intel_connector->edid = edid;
 
-       intel_bios_init_panel(dev_priv, &intel_connector->panel,
-                             encoder->devdata, IS_ERR(edid) ? NULL : edid);
+       intel_bios_init_panel_late(dev_priv, &intel_connector->panel,
+                                  encoder->devdata, IS_ERR(edid) ? NULL : edid);
 
        intel_panel_add_edid_fixed_modes(intel_connector, true);
 
index e535223..a749a5a 100644 (file)
@@ -967,8 +967,8 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
        }
        intel_connector->edid = edid;
 
-       intel_bios_init_panel(dev_priv, &intel_connector->panel, NULL,
-                             IS_ERR(edid) ? NULL : edid);
+       intel_bios_init_panel_late(dev_priv, &intel_connector->panel, NULL,
+                                  IS_ERR(edid) ? NULL : edid);
 
        /* Try EDID first */
        intel_panel_add_edid_fixed_modes(intel_connector,
index 8bd7af9..b50db0d 100644 (file)
@@ -652,6 +652,7 @@ void intel_panel_init_alloc(struct intel_connector *connector)
 {
        struct intel_panel *panel = &connector->panel;
 
+       connector->panel.vbt.panel_type = -1;
        INIT_LIST_HEAD(&panel->fixed_modes);
 }
 
index a68f68e..23d40ac 100644 (file)
@@ -2891,7 +2891,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
        if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
                goto err;
 
-       intel_bios_init_panel(i915, &intel_connector->panel, NULL, NULL);
+       intel_bios_init_panel_late(i915, &intel_connector->panel, NULL, NULL);
 
        /*
         * Fetch modes from VBT. For SDVO prefer the VBT mode since some
index e996860..da70c53 100644 (file)
@@ -1925,7 +1925,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
 
        intel_dsi->panel_power_off_time = ktime_get_boottime();
 
-       intel_bios_init_panel(dev_priv, &intel_connector->panel, NULL, NULL);
+       intel_bios_init_panel_late(dev_priv, &intel_connector->panel, NULL, NULL);
 
        if (intel_connector->panel.vbt.dsi.config->dual_link)
                intel_dsi->ports = BIT(PORT_A) | BIT(PORT_C);