]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
drm/i915: Do panel VBT init early if the VBT declares an explicit panel type
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Fri, 25 Nov 2022 17:31:49 +0000 (19:31 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 17 Mar 2023 07:50:20 +0000 (08:50 +0100)
[ Upstream commit 3f9ffce5765d68775163b8b134c4d7f156b48eec ]

Lots of ADL machines out there with bogus VBTs that declare
two eDP child devices. In order for those to work we need to
figure out which power sequencer to use before we try the EDID
read. So let's do the panel VBT init early if we can, falling
back to the post-EDID init otherwise.

The post-EDID init panel_type=0xff approach of assuming the
power sequencer should already be enabled doesn't really work
with multiple eDP panels, and currently we just end up using
the same power sequencer for both eDP ports, which at least
confuses the wakeref tracking, and potentially also causes us
to toggle the VDD for the panel when we should not.

Cc: Animesh Manna <animesh.manna@intel.com>
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20221125173156.31689-3-ville.syrjala@linux.intel.com
Stable-dep-of: 14e591a1930c ("drm/i915: Populate encoder->devdata for DSI on icl+")
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/gpu/drm/i915/display/icl_dsi.c
drivers/gpu/drm/i915/display/intel_bios.c
drivers/gpu/drm/i915/display/intel_bios.h
drivers/gpu/drm/i915/display/intel_display_types.h
drivers/gpu/drm/i915/display/intel_dp.c
drivers/gpu/drm/i915/display/intel_lvds.c
drivers/gpu/drm/i915/display/intel_panel.c
drivers/gpu/drm/i915/display/intel_sdvo.c
drivers/gpu/drm/i915/display/vlv_dsi.c

index ed4d93942dbd20c254aaf32c79e94d767adc0459..34b3ff967a272ddea59bd1ed56277e430757b835 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 178a8cbb7583883058450d32cf8ac8cdd9b759d2..2378a2a48716e09740cae4a78e0c34c45987de41 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);
@@ -3191,14 +3192,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);
@@ -3213,6 +3226,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 e375405a7828413360e4f9b6dded44b1dd92b841..ff1fdd2e0c1c5cf367336ce036f6653dd5c2c77f 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 298d00a11f47316d7450a90ff2d593d1cd2d0e5d..135dbcab62b28612d104a83308e9dafca9f96677 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 b94bcceeff70597d5f51d019ad39a5f2d40ee6be..2e09899f2f9274df394a1a9d34c7b075f7b74195 100644 (file)
@@ -5179,6 +5179,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. */
@@ -5213,8 +5216,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 e5352239b2a2ffea5132efacad485655ecd149c6..a749a5a66d624aab57908160780aeb8ae0f71e37 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 8bd7af99cd2b94d529742a21bbdd84bd06bbe4bf..b50db0dd20fc56b35e26e9d73efa9c5e63cca291 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 774c1dc31a52107d3cf0b3cdfd62d393e3221072..a15e09b551708e374fcbbc42448dfc72725ced58 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 b3f5ca280ef2683e16806cd0af59bed38289ad10..90e3e41095b34be5dc4e4d11c80521be6297c932 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);