From 1bf2f3bf29a97037e695cc3e8695746fd8d2cde0 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Tue, 10 Dec 2019 12:50:47 +0200 Subject: [PATCH] drm/i915/bios: add support for querying DSC details for encoder MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Add function for retrieving the DSC data for an encoder. Initially, this is DSI specific, as DP does not use VBT settings for DSC at all. It's also not very pretty. In the future we might have a pointer from encoder to the child device, which would make the child device list query here so much more sensible. v3: - use crtc_state instead of pipe_config - return true by default from intel_bios_get_dsc_params() - expand the comment about rc_buffer_block_size and rc_buffer_size v2: - make more robust, debug log errors better Bspec: 29885 Cc: Vandita Kulkarni Cc: Ville Syrjälä Reviewed-by: Vandita Kulkarni Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/b895c349d964d70e4cad26f12a629ea1898bfcc2.1575974743.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 99 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_bios.h | 5 ++ 2 files changed, 104 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 726516a..bd674fd 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -29,6 +29,7 @@ #include #include "display/intel_display.h" +#include "display/intel_display_types.h" #include "display/intel_gmbus.h" #include "i915_drv.h" @@ -2394,6 +2395,104 @@ bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, return false; } +static void fill_dsc(struct intel_crtc_state *crtc_state, + struct dsc_compression_parameters_entry *dsc, + int dsc_max_bpc) +{ + struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; + int bpc = 8; + + vdsc_cfg->dsc_version_major = dsc->version_major; + vdsc_cfg->dsc_version_minor = dsc->version_minor; + + if (dsc->support_12bpc && dsc_max_bpc >= 12) + bpc = 12; + else if (dsc->support_10bpc && dsc_max_bpc >= 10) + bpc = 10; + else if (dsc->support_8bpc && dsc_max_bpc >= 8) + bpc = 8; + else + DRM_DEBUG_KMS("VBT: Unsupported BPC %d for DCS\n", + dsc_max_bpc); + + crtc_state->pipe_bpp = bpc * 3; + + crtc_state->dsc.compressed_bpp = min(crtc_state->pipe_bpp, + VBT_DSC_MAX_BPP(dsc->max_bpp)); + + /* + * FIXME: This is ugly, and slice count should take DSC engine + * throughput etc. into account. + * + * Also, per spec DSI supports 1, 2, 3 or 4 horizontal slices. + */ + if (dsc->slices_per_line & BIT(2)) { + crtc_state->dsc.slice_count = 4; + } else if (dsc->slices_per_line & BIT(1)) { + crtc_state->dsc.slice_count = 2; + } else { + /* FIXME */ + if (!(dsc->slices_per_line & BIT(0))) + DRM_DEBUG_KMS("VBT: Unsupported DSC slice count for DSI\n"); + + crtc_state->dsc.slice_count = 1; + } + + if (crtc_state->hw.adjusted_mode.crtc_hdisplay % + crtc_state->dsc.slice_count != 0) + DRM_DEBUG_KMS("VBT: DSC hdisplay %d not divisible by slice count %d\n", + crtc_state->hw.adjusted_mode.crtc_hdisplay, + crtc_state->dsc.slice_count); + + /* + * FIXME: Use VBT rc_buffer_block_size and rc_buffer_size for the + * implementation specific physical rate buffer size. Currently we use + * the required rate buffer model size calculated in + * drm_dsc_compute_rc_parameters() according to VESA DSC Annex E. + * + * The VBT rc_buffer_block_size and rc_buffer_size definitions + * correspond to DP 1.4 DPCD offsets 0x62 and 0x63. The DP DSC + * implementation should also use the DPCD (or perhaps VBT for eDP) + * provided value for the buffer size. + */ + + /* FIXME: DSI spec says bpc + 1 for this one */ + vdsc_cfg->line_buf_depth = VBT_DSC_LINE_BUFFER_DEPTH(dsc->line_buffer_depth); + + vdsc_cfg->block_pred_enable = dsc->block_prediction_enable; + + vdsc_cfg->slice_height = dsc->slice_height; +} + +/* FIXME: initially DSI specific */ +bool intel_bios_get_dsc_params(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + int dsc_max_bpc) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + const struct display_device_data *devdata; + const struct child_device_config *child; + + list_for_each_entry(devdata, &i915->vbt.display_devices, node) { + child = &devdata->child; + + if (!(child->device_type & DEVICE_TYPE_MIPI_OUTPUT)) + continue; + + if (child->dvo_port - DVO_PORT_MIPIA == encoder->port) { + if (!devdata->dsc) + return false; + + if (crtc_state) + fill_dsc(crtc_state, devdata->dsc, dsc_max_bpc); + + return true; + } + } + + return false; +} + /** * intel_bios_is_port_hpd_inverted - is HPD inverted for %port * @i915: i915 device instance diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h index 98f0648..d6a0c29 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.h +++ b/drivers/gpu/drm/i915/display/intel_bios.h @@ -35,6 +35,8 @@ #include struct drm_i915_private; +struct intel_crtc_state; +struct intel_encoder; enum port; enum intel_backlight_type { @@ -242,5 +244,8 @@ bool intel_bios_is_port_hpd_inverted(const struct drm_i915_private *i915, bool intel_bios_is_lspcon_present(const struct drm_i915_private *i915, enum port port); enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *dev_priv, enum port port); +bool intel_bios_get_dsc_params(struct intel_encoder *encoder, + struct intel_crtc_state *crtc_state, + int dsc_max_bpc); #endif /* _INTEL_BIOS_H_ */ -- 2.7.4