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@xxxxxxxxxxxxxxx> > Cc: Jani Nikula <jani.nikula@xxxxxxxxx> > Signed-off-by: José Roberto de Souza <jose.souza@xxxxxxxxx> Reviewed-by: Matt Atwood <matthew.s.atwood@xxxxxxxxx> > --- > 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@xxxxxxxxxxxxxxxxxxxxx > https://lists.freedesktop.org/mailman/listinfo/intel-gfx _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx