Re: [Intel-gfx] [PATCH 02/10] drm/i915/bios: Start to support two integrated panels

Matt Atwood
2021-07-26T21:34:13Z

On Wed, Jul 21, 2021 at 10:43:30PM -0700, José Roberto de Souza wrote:
> VBT has support for up 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.
> Other VBT blocks will be converted in following patches.
>
> While at is also nucking lvds_dither as it is not used.
>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Jani Nikula <jani.nikula@intel.com>
> Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
Reviewed-by: Matt Atwood <matthew.s.atwood@intel.com>
> ---
> drivers/gpu/drm/i915/display/intel_bios.c | 185 +++++++++++++-----
> drivers/gpu/drm/i915/display/intel_bios.h | 2 +
> drivers/gpu/drm/i915/display/intel_dp.c | 5 +-
> drivers/gpu/drm/i915/display/intel_vbt_defs.h | 3 +
> drivers/gpu/drm/i915/i915_drv.h | 5 +-
> 5 files changed, 150 insertions(+), 50 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index 5bc2c944d99b4..2b90efb41ecce 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -211,22 +211,20 @@ get_lvds_fp_timing(const struct bdb_header *bdb,
> return (const struct lvds_fp_timing *)((const u8 *)bdb + ofs);
> }
>
> -/* Parse general panel options */
> -static void
> -parse_panel_options(struct drm_i915_private *i915,
> - const struct bdb_header *bdb)
> +/*
> + * 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_header *bdb)
> {
> const struct bdb_lvds_options *lvds_options;
> - int panel_type;
> - int drrs_mode;
> - int ret;
> + int ret, panel_type;
>
> lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
> if (!lvds_options)
> return;
>
> - i915->vbt.lvds_dither = lvds_options->pixel_dither;
> -
> ret = intel_opregion_get_panel_type(i915);
> if (ret >= 0) {
> drm_WARN_ON(&i915->drm, ret > 0xf);
> @@ -246,9 +244,25 @@ parse_panel_options(struct drm_i915_private *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 ddi_vbt_port_info *info,
> + int panel_index)
> +{
> + const struct bdb_lvds_options *lvds_options;
> + int drrs_mode;
> +
> + lvds_options = find_section(bdb, 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
> @@ -256,16 +270,16 @@ parse_panel_options(struct drm_i915_private *i915,
> */
> switch (drrs_mode) {
> case 0:
> - i915->vbt.drrs_type = STATIC_DRRS_SUPPORT;
> + info->drrs_type = STATIC_DRRS_SUPPORT;
> drm_dbg_kms(&i915->drm, "DRRS supported mode is static\n");
> break;
> case 2:
> - i915->vbt.drrs_type = SEAMLESS_DRRS_SUPPORT;
> + info->drrs_type = SEAMLESS_DRRS_SUPPORT;
> drm_dbg_kms(&i915->drm,
> "DRRS supported mode is seamless\n");
> break;
> default:
> - i915->vbt.drrs_type = DRRS_NOT_SUPPORTED;
> + info->drrs_type = DRRS_NOT_SUPPORTED;
> drm_dbg_kms(&i915->drm,
> "DRRS not supported (VBT input)\n");
> break;
> @@ -710,28 +724,42 @@ parse_driver_features(struct drm_i915_private *i915,
> i915->vbt.int_lvds_support = 0;
> }
>
> - if (bdb->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_NOT_SUPPORTED;
> -
> + if (bdb->version < 228)
> i915->vbt.psr.enable = driver->psr_enabled;
> - }
> +}
> +
> +static void
> +parse_driver_features_drrs_only(struct drm_i915_private *i915,
> + const struct bdb_header *bdb,
> + struct ddi_vbt_port_info *info)
> +{
> + const struct bdb_driver_features *driver;
> +
> + if (bdb->version >= 228)
> + return;
> +
> + driver = find_section(bdb, 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_NOT_SUPPORTED;
> }
>
> static void
> parse_power_conservation_features(struct drm_i915_private *i915,
> - const struct bdb_header *bdb)
> + const struct bdb_header *bdb,
> + struct ddi_vbt_port_info *info,
> + int panel_index)
> {
> const struct bdb_lfp_power *power;
> - u8 panel_type = i915->vbt.panel_type;
>
> if (bdb->version < 228)
> return;
> @@ -740,7 +768,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.
> @@ -748,11 +776,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)))
> - i915->vbt.drrs_type = DRRS_NOT_SUPPORTED;
> + if (!(power->drrs & BIT(panel_index)))
> + info->drrs_type = DRRS_NOT_SUPPORTED;
>
> if (bdb->version >= 232)
> - i915->vbt.edp.hobl = power->hobl & BIT(panel_type);
> + i915->vbt.edp.hobl = power->hobl & BIT(panel_index);
> }
>
> static void
> @@ -1887,6 +1915,74 @@ 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(bdb, 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_integrated_panel(struct drm_i915_private *i915,
> + struct intel_bios_encoder_data *devdata,
> + struct ddi_vbt_port_info *info)
> +{
> + const struct vbt_header *vbt = i915->opregion.vbt;
> + const struct bdb_header *bdb;
> + int lfp_inst = 0, panel_index, opregion_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);
> +
> + opregion_panel_index = intel_opregion_get_panel_type(i915);
> + /*
> + * TODO: the current implementation always use the panel index from
> + * opregion if available due to issues with old platforms.
> + * But this do not supports two panels and in SKL or newer I never saw a
> + * system were this call returns a valid value.
> + * So will change this to only use opregion up to BDW in a separated
> + * commit.
> + */
> + if (opregion_panel_index >= 0)
> + panel_index = opregion_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)
> {
> @@ -2018,6 +2114,8 @@ static void parse_ddi_port(struct drm_i915_private *i915,
> port_name(port), info->dp_max_link_rate);
> }
>
> + parse_integrated_panel(i915, devdata, info);
> +
> info->devdata = devdata;
> }
>
> @@ -2144,9 +2242,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;
>
> @@ -2226,13 +2321,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
> @@ -2386,12 +2474,11 @@ void intel_bios_init(struct drm_i915_private *i915)
> /* Grab useful general definitions */
> parse_general_features(i915, bdb);
> parse_general_definitions(i915, bdb);
> - parse_panel_options(i915, bdb);
> + parse_panel_type(i915, bdb);
> parse_panel_dtd(i915, bdb);
> parse_lfp_backlight(i915, bdb);
> parse_sdvo_panel_data(i915, bdb);
> parse_driver_features(i915, bdb);
> - parse_power_conservation_features(i915, bdb);
> parse_edp(i915, bdb);
> parse_psr(i915, bdb);
> parse_mipi_config(i915, bdb);
> @@ -3011,3 +3098,11 @@ intel_bios_encoder_data_lookup(struct drm_i915_private *i915, enum port port)
> {
> return i915->vbt.ddi_port_info[port].devdata;
> }
> +
> +enum drrs_support_type
> +intel_bios_drrs_type(struct intel_encoder *encoder)
> +{
> + struct drm_i915_private *i915 = to_i915(encoder->base.dev);
> +
> + return i915->vbt.ddi_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 4709c4d298059..bad282b64c5e6 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_support_type intel_bios_drrs_type(struct intel_encoder *encoder);
> +
> #endif /* _INTEL_BIOS_H_ */
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index c386ef8eb2006..79d4e3edb2eef 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -5133,6 +5133,7 @@ intel_dp_drrs_init(struct intel_connector *connector,
> {
> struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
> struct drm_display_mode *downclock_mode = NULL;
> + enum drrs_support_type drrs_type = intel_bios_drrs_type(connector->encoder);
>
> INIT_DELAYED_WORK(&dev_priv->drrs.work, intel_edp_drrs_downclock_work);
> mutex_init(&dev_priv->drrs.mutex);
> @@ -5143,7 +5144,7 @@ intel_dp_drrs_init(struct intel_connector *connector,
> return NULL;
> }
>
> - if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) {
> + if (drrs_type != SEAMLESS_DRRS_SUPPORT) {
> drm_dbg_kms(&dev_priv->drm, "VBT doesn't support DRRS\n");
> return NULL;
> }
> @@ -5155,7 +5156,7 @@ intel_dp_drrs_init(struct intel_connector *connector,
> return NULL;
> }
>
> - dev_priv->drrs.type = dev_priv->vbt.drrs_type;
> + dev_priv->drrs.type = drrs_type;
>
> dev_priv->drrs.refresh_rate_type = DRRS_HIGH_RR;
> drm_dbg_kms(&dev_priv->drm,
> diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> index dbe24d7e73759..cd927d13250f1 100644
> --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> @@ -359,6 +359,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 0321a1f9738d6..d990ceb23c85e 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -656,6 +656,8 @@ struct ddi_vbt_port_info {
> u8 alternate_ddc_pin;
>
> int dp_max_link_rate; /* 0 for not limited by VBT */
> +
> + enum drrs_support_type drrs_type;
> };
>
> enum psr_lines_to_wait {
> @@ -674,7 +676,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;
> @@ -685,8 +686,6 @@ struct intel_vbt_data {
> unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
> enum drm_panel_orientation orientation;
>
> - enum drrs_support_type drrs_type;
> -
> struct {
> int rate;
> int lanes;
> --
> 2.32.0
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx