[PATCH 1/5] drm/i915/bios: Start to support two integrated panels

Animesh Manna animesh.manna at intel.com
Wed May 25 16:53:17 UTC 2022


VBT has support for up to two integrated panels but i915 only supports one.

So here stating to add the basic support for two integrated panels
and moving the DRRS to ddi_vbt_port_info instead of keeping a global
one.

While also nucking lvds_dither as it is not used.

Signed-off-by: Animesh Manna <animesh.manna at intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c     | 174 +++++++++++++-----
 drivers/gpu/drm/i915/display/intel_bios.h     |   2 +
 drivers/gpu/drm/i915/display/intel_vbt_defs.h |   3 +
 drivers/gpu/drm/i915/i915_drv.h               |   6 +-
 4 files changed, 143 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 3ac1860a0b6e..e7ebccb78ca7 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -673,26 +673,42 @@ static int get_panel_type(struct drm_i915_private *i915)
 	return panel_types[i].panel_type;
 }
 
-/* Parse general panel options */
-static void
-parse_panel_options(struct drm_i915_private *i915)
+
+/*
+ * Parse and set vbt.panel_type, it will be used by the VBT blocks that are
+ * not being called from parse_integrated_panel() yet.
+ */
+static void parse_panel_type(struct drm_i915_private *i915)
 {
 	const struct bdb_lvds_options *lvds_options;
 	int panel_type;
-	int drrs_mode;
 
 	lvds_options = find_section(i915, BDB_LVDS_OPTIONS);
 	if (!lvds_options)
 		return;
 
-	i915->vbt.lvds_dither = lvds_options->pixel_dither;
-
 	panel_type = get_panel_type(i915);
 
 	i915->vbt.panel_type = panel_type;
+}
+
+/* Parse general panel options */
+static void
+parse_panel_options(struct drm_i915_private *i915,
+		    const struct bdb_header *bdb,
+		    struct intel_bios_port_info *info,
+		    int panel_index)
+{
+	const struct bdb_lvds_options *lvds_options;
+	int drrs_mode;
+
+	lvds_options = find_section(i915, BDB_LVDS_OPTIONS);
+	if (!lvds_options)
+		return;
+
+	drrs_mode = lvds_options->dps_panel_type_bits >> (panel_index * 2);
+	drrs_mode &= MODE_MASK;
 
-	drrs_mode = (lvds_options->dps_panel_type_bits
-				>> (panel_type * 2)) & MODE_MASK;
 	/*
 	 * VBT has static DRRS = 0 and seamless DRRS = 2.
 	 * The below piece of code is required to adjust vbt.drrs_type
@@ -700,16 +716,16 @@ parse_panel_options(struct drm_i915_private *i915)
 	 */
 	switch (drrs_mode) {
 	case 0:
-		i915->vbt.drrs_type = DRRS_TYPE_STATIC;
+		info->drrs_type = DRRS_TYPE_STATIC;
 		drm_dbg_kms(&i915->drm, "DRRS supported mode is static\n");
 		break;
 	case 2:
-		i915->vbt.drrs_type = DRRS_TYPE_SEAMLESS;
+		info->drrs_type = DRRS_TYPE_SEAMLESS;
 		drm_dbg_kms(&i915->drm,
 			    "DRRS supported mode is seamless\n");
 		break;
 	default:
-		i915->vbt.drrs_type = DRRS_TYPE_NONE;
+		info->drrs_type = DRRS_TYPE_NONE;
 		drm_dbg_kms(&i915->drm,
 			    "DRRS not supported (VBT input)\n");
 		break;
@@ -1182,27 +1198,17 @@ parse_driver_features(struct drm_i915_private *i915)
 			i915->vbt.int_lvds_support = 0;
 	}
 
-	if (i915->vbt.version < 228) {
-		drm_dbg_kms(&i915->drm, "DRRS State Enabled:%d\n",
-			    driver->drrs_enabled);
-		/*
-		 * If DRRS is not supported, drrs_type has to be set to 0.
-		 * This is because, VBT is configured in such a way that
-		 * static DRRS is 0 and DRRS not supported is represented by
-		 * driver->drrs_enabled=false
-		 */
-		if (!driver->drrs_enabled)
-			i915->vbt.drrs_type = DRRS_TYPE_NONE;
-
+	if (i915->vbt.version < 228)
 		i915->vbt.psr.enable = driver->psr_enabled;
-	}
 }
 
 static void
-parse_power_conservation_features(struct drm_i915_private *i915)
+parse_power_conservation_features(struct drm_i915_private *i915,
+				  const struct bdb_header *bdb,
+				  struct intel_bios_port_info *info,
+				  int panel_index)
 {
 	const struct bdb_lfp_power *power;
-	u8 panel_type = i915->vbt.panel_type;
 
 	if (i915->vbt.version < 228)
 		return;
@@ -1211,7 +1217,7 @@ parse_power_conservation_features(struct drm_i915_private *i915)
 	if (!power)
 		return;
 
-	i915->vbt.psr.enable = power->psr & BIT(panel_type);
+	i915->vbt.psr.enable = power->psr & BIT(panel_index);
 
 	/*
 	 * If DRRS is not supported, drrs_type has to be set to 0.
@@ -1219,11 +1225,11 @@ parse_power_conservation_features(struct drm_i915_private *i915)
 	 * static DRRS is 0 and DRRS not supported is represented by
 	 * power->drrs & BIT(panel_type)=false
 	 */
-	if (!(power->drrs & BIT(panel_type)))
+	if (!(power->drrs & BIT(panel_index)))
 		i915->vbt.drrs_type = DRRS_TYPE_NONE;
 
 	if (i915->vbt.version >= 232)
-		i915->vbt.edp.hobl = power->hobl & BIT(panel_type);
+		i915->vbt.edp.hobl = power->hobl & BIT(panel_index);
 }
 
 static void
@@ -2432,6 +2438,94 @@ static bool is_port_valid(struct drm_i915_private *i915, enum port port)
 	return true;
 }
 
+static const struct bdb_header *get_bdb_header(const struct vbt_header *vbt)
+{
+	const void *_vbt = vbt;
+
+	return _vbt + vbt->bdb_offset;
+}
+
+static int
+get_lfp_panel_index(struct drm_i915_private *i915,
+		    const struct bdb_header *bdb, int lfp_panel_instance)
+{
+	const struct bdb_lvds_options *lvds_options;
+
+	lvds_options = find_section(i915, BDB_LVDS_OPTIONS);
+	if (!lvds_options)
+		return -1;
+
+	switch (lfp_panel_instance) {
+	case 1:
+		return lvds_options->panel_type;
+	case 2:
+		return lvds_options->panel_type2;
+	default:
+		break;
+	}
+
+	return -1;
+}
+
+static void
+parse_driver_features_drrs_only(struct drm_i915_private *i915,
+                                const struct bdb_header *bdb,
+                                struct intel_bios_port_info *info)
+{
+        const struct bdb_driver_features *driver;
+
+        if (bdb->version >= 228)
+                return;
+
+        driver = find_section(i915, BDB_DRIVER_FEATURES);
+        if (!driver)
+                return;
+
+        drm_dbg_kms(&i915->drm, "DRRS State Enabled:%d\n", driver->drrs_enabled);
+        /*
+         * If DRRS is not supported, drrs_type has to be set to 0.
+         * This is because, VBT is configured in such a way that
+         * static DRRS is 0 and DRRS not supported is represented by
+         * driver->drrs_enabled=false
+         */
+        if (!driver->drrs_enabled)
+                info->drrs_type = DRRS_TYPE_NONE;
+}
+
+static void parse_integrated_panel(struct drm_i915_private *i915,
+				   struct intel_bios_encoder_data *devdata,
+				   struct intel_bios_port_info *info)
+{
+	const struct vbt_header *vbt = i915->opregion.vbt;
+	const struct bdb_header *bdb;
+	int lfp_inst = 0, panel_index;
+
+	if (devdata->child.handle == HANDLE_LFP_1)
+		lfp_inst = 1;
+	else if (devdata->child.handle == HANDLE_LFP_2)
+		lfp_inst = 2;
+
+	if (lfp_inst == 0)
+		return;
+
+	bdb = get_bdb_header(vbt);
+	panel_index = get_lfp_panel_index(i915, bdb, lfp_inst);
+
+	if (DISPLAY_VER(i915) < 9) {
+		int opregion_panel_index = intel_opregion_get_panel_type(i915);
+
+		if (opregion_panel_index >= 0)
+			opregion_panel_index = panel_index;
+	}
+
+	if (panel_index == -1)
+		return;
+
+	parse_panel_options(i915, bdb, info, panel_index);
+	parse_power_conservation_features(i915, bdb, info, panel_index);
+	parse_driver_features_drrs_only(i915, bdb, info);
+}
+
 static void parse_ddi_port(struct drm_i915_private *i915,
 			   struct intel_bios_encoder_data *devdata)
 {
@@ -2515,6 +2609,7 @@ static void parse_ddi_port(struct drm_i915_private *i915,
 			    port_name(port), dp_max_link_rate);
 
 	i915->vbt.ports[port] = devdata;
+	parse_integrated_panel(i915, devdata, &i915->vbt.port_info[port]);
 }
 
 static bool has_ddi_port_info(struct drm_i915_private *i915)
@@ -2641,9 +2736,6 @@ init_vbt_defaults(struct drm_i915_private *i915)
 	/* Default to having backlight */
 	i915->vbt.backlight.present = true;
 
-	/* LFP panel data */
-	i915->vbt.lvds_dither = 1;
-
 	/* SDVO panel data */
 	i915->vbt.sdvo_lvds_vbt_mode = NULL;
 
@@ -2724,13 +2816,6 @@ init_vbt_missing_defaults(struct drm_i915_private *i915)
 	i915->vbt.version = 155;
 }
 
-static const struct bdb_header *get_bdb_header(const struct vbt_header *vbt)
-{
-	const void *_vbt = vbt;
-
-	return _vbt + vbt->bdb_offset;
-}
-
 /**
  * intel_bios_is_valid_vbt - does the given buffer contain a valid VBT
  * @buf:	pointer to a buffer to validate
@@ -2952,13 +3037,12 @@ void intel_bios_init(struct drm_i915_private *i915)
 	/* Grab useful general definitions */
 	parse_general_features(i915);
 	parse_general_definitions(i915);
-	parse_panel_options(i915);
+	parse_panel_type(i915);
 	parse_generic_dtd(i915);
 	parse_lfp_data(i915);
 	parse_lfp_backlight(i915);
 	parse_sdvo_panel_data(i915);
 	parse_driver_features(i915);
-	parse_power_conservation_features(i915);
 	parse_edp(i915);
 	parse_psr(i915);
 	parse_mipi_config(i915);
@@ -3511,3 +3595,11 @@ intel_bios_encoder_data_lookup(struct drm_i915_private *i915, enum port port)
 {
 	return i915->vbt.ports[port];
 }
+
+enum drrs_type
+intel_bios_drrs_type(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+	return i915->vbt.port_info[encoder->port].drrs_type;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h
index 4709c4d29805..8e743101b2f6 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.h
+++ b/drivers/gpu/drm/i915/display/intel_bios.h
@@ -266,4 +266,6 @@ bool intel_bios_encoder_supports_tbt(const struct intel_bios_encoder_data *devda
 int intel_bios_encoder_dp_boost_level(const struct intel_bios_encoder_data *devdata);
 int intel_bios_encoder_hdmi_boost_level(const struct intel_bios_encoder_data *devdata);
 
+enum drrs_type intel_bios_drrs_type(struct intel_encoder *encoder);
+
 #endif /* _INTEL_BIOS_H_ */
diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
index 4b98bab3b890..c2e96b7e1f97 100644
--- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h
+++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
@@ -349,6 +349,9 @@ enum vbt_gmbus_ddi {
 #define BDB_230_VBT_DP_MAX_LINK_RATE_UHBR13P5	6
 #define BDB_230_VBT_DP_MAX_LINK_RATE_UHBR20	7
 
+#define HANDLE_LFP_1 0x0008
+#define HANDLE_LFP_2 0x0080
+
 /*
  * The child device config, aka the display device data structure, provides a
  * description of a port and its configuration on the platform.
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 74b3caccd839..f2dbed67f567 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -304,6 +304,10 @@ i915_fence_timeout(const struct drm_i915_private *i915)
 /* Amount of PSF GV points, BSpec precisely defines this */
 #define I915_NUM_PSF_GV_POINTS 3
 
+struct intel_bios_port_info {
+	enum drrs_type drrs_type;
+};
+
 struct intel_vbt_data {
 	/* bdb version */
 	u16 version;
@@ -313,7 +317,6 @@ struct intel_vbt_data {
 
 	/* Feature bits */
 	unsigned int int_tv_support:1;
-	unsigned int lvds_dither:1;
 	unsigned int int_crt_support:1;
 	unsigned int lvds_use_ssc:1;
 	unsigned int int_lvds_support:1;
@@ -385,6 +388,7 @@ struct intel_vbt_data {
 
 	struct intel_bios_encoder_data *ports[I915_MAX_PORTS]; /* Non-NULL if port present. */
 	struct sdvo_device_mapping sdvo_mappings[2];
+	struct intel_bios_port_info port_info[I915_MAX_PORTS];
 };
 
 struct i915_frontbuffer_tracking {
-- 
2.29.0



More information about the Intel-gfx-trybot mailing list