[Intel-gfx] [CI v5 2/2] drm/i915/vbt: Handle generic DTD block
Jani Nikula
jani.nikula at intel.com
Mon Nov 18 11:38:09 UTC 2019
On Fri, 15 Nov 2019, Matt Roper <matthew.d.roper at intel.com> wrote:
> VBT revision 229 adds a new "Generic DTD" block 58 and deprecates the
> old LFP panel mode data in block 42. Let's start parsing this block to
> fill in the panel fixed mode on devices with a >=229 VBT.
>
> v2:
> * Update according to the recent updates:
> - DTD size is now 16 bits instead of 24
> - polarity is now just a single bit for hsync and vsync and is
> properly documented
> * Minor checkpatch fix
>
> v3:
> * Now that panel options are parsed separately from the previous patch,
> move generic DTD parsing into a function parallel to
> parse_lfp_panel_dtd. We'll still fall back to looking at the legacy
> LVDS timing block if the generic DTD fails. (Jani)
> * Don't forget to actually set lfp_lvds_vbt_mode! (Jani)
> * Drop "bdb_" prefix from dtd entry structure. (Jani)
> * Follow C99 standard for structure's flexible array member. (Jani)
>
> v4:
> * Add "positive" to polarity field names for clarity. (Jani)
> * Move VBT version check and fallback to legacy DTD parsing logic to a
> helper to keep top-level VBT parsing uncluttered. (Jani)
> * Restructure reserved bit packing at end of generic_dtd_entry from
> "u32 rsvd:24" to "u8 rsvd[3]" to prevent copy/paste mistakes in the
> future. (Jani)
Thanks, looks nice.
BR,
Jani.
>
> Bspec: 54751
> Bspec: 20148
> Cc: Jani Nikula <jani.nikula at intel.com>
> Signed-off-by: Matt Roper <matthew.d.roper at intel.com>
> Reviewed-by: Jani Nikula <jani.nikula at intel.com>
> ---
> drivers/gpu/drm/i915/display/intel_bios.c | 96 ++++++++++++++++++-
> drivers/gpu/drm/i915/display/intel_vbt_defs.h | 31 ++++++
> 2 files changed, 125 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index d13ce0b7db8b..f6a9a5ccb556 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -296,7 +296,7 @@ parse_lfp_panel_dtd(struct drm_i915_private *dev_priv,
>
> dev_priv->vbt.lfp_lvds_vbt_mode = panel_fixed_mode;
>
> - DRM_DEBUG_KMS("Found panel mode in BIOS VBT tables:\n");
> + DRM_DEBUG_KMS("Found panel mode in BIOS VBT legacy lfp table:\n");
> drm_mode_debug_printmodeline(panel_fixed_mode);
>
> fp_timing = get_lvds_fp_timing(bdb, lvds_lfp_data,
> @@ -313,6 +313,98 @@ parse_lfp_panel_dtd(struct drm_i915_private *dev_priv,
> }
> }
>
> +static void
> +parse_generic_dtd(struct drm_i915_private *dev_priv,
> + const struct bdb_header *bdb)
> +{
> + const struct bdb_generic_dtd *generic_dtd;
> + const struct generic_dtd_entry *dtd;
> + struct drm_display_mode *panel_fixed_mode;
> + int num_dtd;
> +
> + generic_dtd = find_section(bdb, BDB_GENERIC_DTD);
> + if (!generic_dtd)
> + return;
> +
> + if (generic_dtd->gdtd_size < sizeof(struct generic_dtd_entry)) {
> + DRM_ERROR("GDTD size %u is too small.\n",
> + generic_dtd->gdtd_size);
> + return;
> + } else if (generic_dtd->gdtd_size !=
> + sizeof(struct generic_dtd_entry)) {
> + DRM_ERROR("Unexpected GDTD size %u\n", generic_dtd->gdtd_size);
> + /* DTD has unknown fields, but keep going */
> + }
> +
> + num_dtd = (get_blocksize(generic_dtd) -
> + sizeof(struct bdb_generic_dtd)) / generic_dtd->gdtd_size;
> + if (dev_priv->vbt.panel_type > num_dtd) {
> + DRM_ERROR("Panel type %d not found in table of %d DTD's\n",
> + dev_priv->vbt.panel_type, num_dtd);
> + return;
> + }
> +
> + dtd = &generic_dtd->dtd[dev_priv->vbt.panel_type];
> +
> + panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
> + if (!panel_fixed_mode)
> + return;
> +
> + panel_fixed_mode->hdisplay = dtd->hactive;
> + panel_fixed_mode->hsync_start =
> + panel_fixed_mode->hdisplay + dtd->hfront_porch;
> + panel_fixed_mode->hsync_end =
> + panel_fixed_mode->hsync_start + dtd->hsync;
> + panel_fixed_mode->htotal = panel_fixed_mode->hsync_end;
> +
> + panel_fixed_mode->vdisplay = dtd->vactive;
> + panel_fixed_mode->vsync_start =
> + panel_fixed_mode->vdisplay + dtd->vfront_porch;
> + panel_fixed_mode->vsync_end =
> + panel_fixed_mode->vsync_start + dtd->vsync;
> + panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end;
> +
> + panel_fixed_mode->clock = dtd->pixel_clock;
> + panel_fixed_mode->width_mm = dtd->width_mm;
> + panel_fixed_mode->height_mm = dtd->height_mm;
> +
> + panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
> + drm_mode_set_name(panel_fixed_mode);
> +
> + if (dtd->hsync_positive_polarity)
> + panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC;
> + else
> + panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC;
> +
> + if (dtd->vsync_positive_polarity)
> + panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC;
> + else
> + panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;
> +
> + DRM_DEBUG_KMS("Found panel mode in BIOS VBT generic dtd table:\n");
> + drm_mode_debug_printmodeline(panel_fixed_mode);
> +
> + dev_priv->vbt.lfp_lvds_vbt_mode = panel_fixed_mode;
> +}
> +
> +static void
> +parse_panel_dtd(struct drm_i915_private *dev_priv,
> + const struct bdb_header *bdb)
> +{
> + /*
> + * Older VBTs provided provided DTD information for internal displays
> + * through the "LFP panel DTD" block (42). As of VBT revision 229,
> + * that block is now deprecated and DTD information should be provided
> + * via a newer "generic DTD" block (58). Just to be safe, we'll
> + * try the new generic DTD block first on VBT >= 229, but still fall
> + * back to trying the old LFP block if that fails.
> + */
> + if (bdb->version >= 229)
> + parse_generic_dtd(dev_priv, bdb);
> + if (!dev_priv->vbt.lfp_lvds_vbt_mode)
> + parse_lfp_panel_dtd(dev_priv, bdb);
> +}
> +
> static void
> parse_lfp_backlight(struct drm_i915_private *dev_priv,
> const struct bdb_header *bdb)
> @@ -1877,7 +1969,7 @@ void intel_bios_init(struct drm_i915_private *dev_priv)
> parse_general_features(dev_priv, bdb);
> parse_general_definitions(dev_priv, bdb);
> parse_panel_options(dev_priv, bdb);
> - parse_lfp_panel_dtd(dev_priv, bdb);
> + parse_panel_dtd(dev_priv, bdb);
> parse_lfp_backlight(dev_priv, bdb);
> parse_sdvo_panel_data(dev_priv, bdb);
> parse_driver_features(dev_priv, bdb);
> diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> index 69a7cb1fa121..f0338da3a82a 100644
> --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> @@ -115,6 +115,7 @@ enum bdb_block_id {
> BDB_MIPI_CONFIG = 52,
> BDB_MIPI_SEQUENCE = 53,
> BDB_COMPRESSION_PARAMETERS = 56,
> + BDB_GENERIC_DTD = 58,
> BDB_SKIP = 254, /* VBIOS private block, ignore */
> };
>
> @@ -863,4 +864,34 @@ struct bdb_compression_parameters {
> struct dsc_compression_parameters_entry data[16];
> } __packed;
>
> +/*
> + * Block 58 - Generic DTD Block
> + */
> +
> +struct generic_dtd_entry {
> + u32 pixel_clock;
> + u16 hactive;
> + u16 hblank;
> + u16 hfront_porch;
> + u16 hsync;
> + u16 vactive;
> + u16 vblank;
> + u16 vfront_porch;
> + u16 vsync;
> + u16 width_mm;
> + u16 height_mm;
> +
> + /* Flags */
> + u8 rsvd_flags:6;
> + u8 vsync_positive_polarity:1;
> + u8 hsync_positive_polarity:1;
> +
> + u8 rsvd[3];
> +} __packed;
> +
> +struct bdb_generic_dtd {
> + u16 gdtd_size;
> + struct generic_dtd_entry dtd[]; /* up to 24 DTD's */
> +} __packed;
> +
> #endif /* _INTEL_VBT_DEFS_H_ */
--
Jani Nikula, Intel Open Source Graphics Center
More information about the Intel-gfx
mailing list