Get decompression capabilities from DP sink by doing
DPCD reads of different offsets as per eDP/DP specs.

Signed-off-by: Gaurav K Singh <gaurav.k.si...@intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 167 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 167 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 1868f73f730c..f494a851ff89 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -5883,6 +5883,149 @@ void intel_edp_drrs_flush(struct drm_i915_private 
*dev_priv,
        return downclock_mode;
 }
 
+static void intel_dp_sink_get_dsc_capability(struct intel_dp *intel_dp,
+                                       struct dp_sink_dsc_caps *dp_dsc_caps)
+{
+       u8 rcbuffer_blocksize;
+       u8 fec_dpcd;
+       unsigned long line_buffer_bit_depth, sink_support_max_bpp_msb;
+
+       /* VDSC is supported only for eDp v1.4 or higher, DPCD 0x00700 offset */
+       if (intel_dp->edp_dpcd[0] < 0x03)
+               return;
+
+       /* Read DPCD 0x060 to 0x06a */
+       if (drm_dp_dpcd_read(&intel_dp->aux, DP_DSC_SUPPORT, intel_dp->dsc_dpcd,
+                            sizeof(intel_dp->dsc_dpcd)) < 0)
+               return;
+
+       dp_dsc_caps->is_dsc_supported = intel_dp->dsc_dpcd[0] &
+                                       DP_DSC_DECOMPRESSION_IS_SUPPORTED;
+
+       if (!dp_dsc_caps->is_dsc_supported)
+               return;
+
+       drm_dp_dpcd_readb(&intel_dp->aux, 0x090, &fec_dpcd);
+       intel_dp->fec_dpcd = fec_dpcd;
+
+       /* For DP DSC, FEC support is must */
+       if (!(intel_dp->fec_dpcd & 0x1))
+               return;
+
+       /* No VDSC support for less than 8 BPC */
+       if (intel_dp->dsc_dpcd[0xa] < DP_DSC_8_BPC)
+               return;
+
+       if (intel_dp->dsc_dpcd[0xa] & DP_DSC_8_BPC)
+               DRM_INFO("8 Bits per color support\n");
+       if (intel_dp->dsc_dpcd[0xa] & DP_DSC_10_BPC)
+               DRM_INFO("10 Bits per color support\n");
+       if (intel_dp->dsc_dpcd[0xa] & DP_DSC_12_BPC)
+               DRM_INFO("12 Bits per color support\n");
+
+       dp_dsc_caps->dsc_major_ver = intel_dp->dsc_dpcd[1] & DP_DSC_MAJOR_MASK;
+       dp_dsc_caps->dsc_minor_ver = (intel_dp->dsc_dpcd[1] &
+                               DP_DSC_MINOR_MASK) >> DP_DSC_MINOR_SHIFT;
+
+       rcbuffer_blocksize = intel_dp->dsc_dpcd[2] & 0x3;
+
+       switch (rcbuffer_blocksize) {
+       case 0:
+               dp_dsc_caps->rcbuffer_blocksize = 1;
+               break;
+       case 1:
+               dp_dsc_caps->rcbuffer_blocksize = 4;
+               break;
+       case 2:
+               dp_dsc_caps->rcbuffer_blocksize = 16;
+               break;
+       case 3:
+               dp_dsc_caps->rcbuffer_blocksize = 64;
+               break;
+       default:
+               break;
+
+       }
+       dp_dsc_caps->rcbuffer_size_in_blocks = intel_dp->dsc_dpcd[3] + 1;
+
+       dp_dsc_caps->rcbuffer_size =
+                       dp_dsc_caps->rcbuffer_size_in_blocks *
+                       dp_dsc_caps->rcbuffer_blocksize * 1024 * 8;
+
+       dp_dsc_caps->slice_caps = intel_dp->dsc_dpcd[4];
+       line_buffer_bit_depth = intel_dp->dsc_dpcd[5];
+
+       if (line_buffer_bit_depth == 8)
+               dp_dsc_caps->line_buffer_bit_depth = intel_dp->dsc_dpcd[5];
+       else
+               dp_dsc_caps->line_buffer_bit_depth = intel_dp->dsc_dpcd[5] + 9;
+
+       dp_dsc_caps->is_block_pred_supported = intel_dp->dsc_dpcd[6] &
+                                       DP_DSC_BLK_PREDICTION_IS_SUPPORTED;
+
+       dp_dsc_caps->sink_support_max_bpp = intel_dp->dsc_dpcd[7];
+       sink_support_max_bpp_msb = (intel_dp->dsc_dpcd[8] & 0x3) << 8;
+       dp_dsc_caps->sink_support_max_bpp |= sink_support_max_bpp_msb;
+
+       dp_dsc_caps->color_format_caps = intel_dp->dsc_dpcd[9];
+       dp_dsc_caps->color_depth_caps = intel_dp->dsc_dpcd[0xa];
+}
+
+static void intel_dp_get_compression_data(struct intel_dp *intel_dp,
+                                       struct dp_sink_dsc_caps dp_dsc_caps)
+{
+       if (!dp_dsc_caps.is_dsc_supported)
+               return;
+
+       intel_dp->compr_params.compression_support =
+                                               dp_dsc_caps.is_dsc_supported;
+       intel_dp->compr_params.dsc_cfg.dsc_version_major =
+                                               dp_dsc_caps.dsc_major_ver;
+       intel_dp->compr_params.dsc_cfg.dsc_version_minor =
+                                               dp_dsc_caps.dsc_minor_ver;
+
+       /* By default set bpc to 8 */
+       intel_dp->compr_params.dsc_cfg.bits_per_component = 8;
+
+       /* Take the max for Bits per component */
+       if (intel_dp->dsc_dpcd[0xa] & DP_DSC_8_BPC)
+               intel_dp->compr_params.dsc_cfg.bits_per_component = 8;
+       if (intel_dp->dsc_dpcd[0xa] & DP_DSC_10_BPC)
+               intel_dp->compr_params.dsc_cfg.bits_per_component = 10;
+       if (intel_dp->dsc_dpcd[0xa] & DP_DSC_12_BPC)
+               intel_dp->compr_params.dsc_cfg.bits_per_component = 12;
+
+       intel_dp->compr_params.compression_bpp =
+                                       dp_dsc_caps.sink_support_max_bpp >> 4;
+       intel_dp->compr_params.dsc_cfg.bits_per_pixel =
+                                       dp_dsc_caps.sink_support_max_bpp;
+       intel_dp->compr_params.dsc_cfg.convert_rgb = dp_dsc_caps.RGB_support;
+       intel_dp->compr_params.dsc_cfg.enable422 = dp_dsc_caps.YCbCr422_support;
+       intel_dp->compr_params.dsc_cfg.block_pred_enable =
+                                       dp_dsc_caps.is_block_pred_supported;
+
+       /* Always try to enable 2 DSC instances, by default */
+       intel_dp->compr_params.dsc_cfg.num_vdsc_instances = 2;
+
+       if (dp_dsc_caps.four_slice_per_line_support)
+               intel_dp->compr_params.dsc_cfg.slice_count = 4;
+       else if (dp_dsc_caps.two_slice_per_line_support)
+               intel_dp->compr_params.dsc_cfg.slice_count = 2;
+       else if (dp_dsc_caps.one_slice_per_line_support) {
+               /*
+                * Cannot use 2 DSC engines simultaneously when
+                * slice per line support is only 1
+                */
+               intel_dp->compr_params.dsc_cfg.slice_count = 1;
+               intel_dp->compr_params.dsc_cfg.num_vdsc_instances = 1;
+       } else
+               DRM_INFO("Slice count not supported:%d\n",
+                                                       dp_dsc_caps.slice_caps);
+
+       intel_dp->compr_params.dsc_cfg.line_buf_depth =
+                                       dp_dsc_caps.line_buffer_bit_depth;
+}
+
 static bool intel_edp_init_connector(struct intel_dp *intel_dp,
                                     struct intel_connector *intel_connector)
 {
@@ -5892,6 +6035,7 @@ static bool intel_edp_init_connector(struct intel_dp 
*intel_dp,
        struct drm_display_mode *fixed_mode = NULL;
        struct drm_display_mode *alt_fixed_mode = NULL;
        struct drm_display_mode *downclock_mode = NULL;
+       struct dp_sink_dsc_caps sink_dp_dsc_caps = {0};
        bool has_dpcd;
        struct drm_display_mode *scan;
        struct edid *edid;
@@ -5930,6 +6074,12 @@ static bool intel_edp_init_connector(struct intel_dp 
*intel_dp,
                goto out_vdd_off;
        }
 
+       /* Get DSC capability of DP sink */
+       if (INTEL_GEN(dev_priv) >= 9) {
+               intel_dp_sink_get_dsc_capability(intel_dp, &sink_dp_dsc_caps);
+               intel_dp_get_compression_data(intel_dp, sink_dp_dsc_caps);
+       }
+
        mutex_lock(&dev->mode_config.mutex);
        edid = drm_get_edid(connector, &intel_dp->aux.ddc);
        if (edid) {
@@ -5968,6 +6118,23 @@ static bool intel_edp_init_connector(struct intel_dp 
*intel_dp,
        }
        mutex_unlock(&dev->mode_config.mutex);
 
+       if (intel_dp->compr_params.compression_support) {
+               intel_dp->compr_params.dsc_cfg.pic_width = fixed_mode->hdisplay;
+               intel_dp->compr_params.dsc_cfg.pic_height =
+                                                       fixed_mode->vdisplay;
+               intel_dp->compr_params.dsc_cfg.slice_width = DIV_ROUND_UP(
+                               intel_dp->compr_params.dsc_cfg.pic_width,
+                               intel_dp->compr_params.dsc_cfg.slice_count);
+
+               /* slice height data is not available from dpcd */
+               if (intel_dp->compr_params.dsc_cfg.pic_height % 8 == 0)
+                       intel_dp->compr_params.dsc_cfg.slice_height = 8;
+               if (intel_dp->compr_params.dsc_cfg.pic_height % 4 == 0)
+                       intel_dp->compr_params.dsc_cfg.slice_height = 4;
+               if (intel_dp->compr_params.dsc_cfg.pic_height % 2 == 0)
+                       intel_dp->compr_params.dsc_cfg.slice_height = 2;
+       }
+
        if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
                intel_dp->edp_notifier.notifier_call = edp_notify_handler;
                register_reboot_notifier(&intel_dp->edp_notifier);
-- 
1.9.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to