Merge tag 'topic/dp-hdmi-2.1-pcon-2020-12-23' of git://anongit.freedesktop.org/drm...
[linux-2.6-microblaze.git] / drivers / gpu / drm / drm_edid.c
index e95cce8..394cc55 100644 (file)
@@ -4851,6 +4851,41 @@ static void drm_parse_vcdb(struct drm_connector *connector, const u8 *db)
                info->rgb_quant_range_selectable = true;
 }
 
+static
+void drm_get_max_frl_rate(int max_frl_rate, u8 *max_lanes, u8 *max_rate_per_lane)
+{
+       switch (max_frl_rate) {
+       case 1:
+               *max_lanes = 3;
+               *max_rate_per_lane = 3;
+               break;
+       case 2:
+               *max_lanes = 3;
+               *max_rate_per_lane = 6;
+               break;
+       case 3:
+               *max_lanes = 4;
+               *max_rate_per_lane = 6;
+               break;
+       case 4:
+               *max_lanes = 4;
+               *max_rate_per_lane = 8;
+               break;
+       case 5:
+               *max_lanes = 4;
+               *max_rate_per_lane = 10;
+               break;
+       case 6:
+               *max_lanes = 4;
+               *max_rate_per_lane = 12;
+               break;
+       case 0:
+       default:
+               *max_lanes = 0;
+               *max_rate_per_lane = 0;
+       }
+}
+
 static void drm_parse_ycbcr420_deep_color_info(struct drm_connector *connector,
                                               const u8 *db)
 {
@@ -4904,6 +4939,74 @@ static void drm_parse_hdmi_forum_vsdb(struct drm_connector *connector,
                }
        }
 
+       if (hf_vsdb[7]) {
+               u8 max_frl_rate;
+               u8 dsc_max_frl_rate;
+               u8 dsc_max_slices;
+               struct drm_hdmi_dsc_cap *hdmi_dsc = &hdmi->dsc_cap;
+
+               DRM_DEBUG_KMS("hdmi_21 sink detected. parsing edid\n");
+               max_frl_rate = (hf_vsdb[7] & DRM_EDID_MAX_FRL_RATE_MASK) >> 4;
+               drm_get_max_frl_rate(max_frl_rate, &hdmi->max_lanes,
+                                    &hdmi->max_frl_rate_per_lane);
+               hdmi_dsc->v_1p2 = hf_vsdb[11] & DRM_EDID_DSC_1P2;
+
+               if (hdmi_dsc->v_1p2) {
+                       hdmi_dsc->native_420 = hf_vsdb[11] & DRM_EDID_DSC_NATIVE_420;
+                       hdmi_dsc->all_bpp = hf_vsdb[11] & DRM_EDID_DSC_ALL_BPP;
+
+                       if (hf_vsdb[11] & DRM_EDID_DSC_16BPC)
+                               hdmi_dsc->bpc_supported = 16;
+                       else if (hf_vsdb[11] & DRM_EDID_DSC_12BPC)
+                               hdmi_dsc->bpc_supported = 12;
+                       else if (hf_vsdb[11] & DRM_EDID_DSC_10BPC)
+                               hdmi_dsc->bpc_supported = 10;
+                       else
+                               hdmi_dsc->bpc_supported = 0;
+
+                       dsc_max_frl_rate = (hf_vsdb[12] & DRM_EDID_DSC_MAX_FRL_RATE_MASK) >> 4;
+                       drm_get_max_frl_rate(dsc_max_frl_rate, &hdmi_dsc->max_lanes,
+                                            &hdmi_dsc->max_frl_rate_per_lane);
+                       hdmi_dsc->total_chunk_kbytes = hf_vsdb[13] & DRM_EDID_DSC_TOTAL_CHUNK_KBYTES;
+
+                       dsc_max_slices = hf_vsdb[12] & DRM_EDID_DSC_MAX_SLICES;
+                       switch (dsc_max_slices) {
+                       case 1:
+                               hdmi_dsc->max_slices = 1;
+                               hdmi_dsc->clk_per_slice = 340;
+                               break;
+                       case 2:
+                               hdmi_dsc->max_slices = 2;
+                               hdmi_dsc->clk_per_slice = 340;
+                               break;
+                       case 3:
+                               hdmi_dsc->max_slices = 4;
+                               hdmi_dsc->clk_per_slice = 340;
+                               break;
+                       case 4:
+                               hdmi_dsc->max_slices = 8;
+                               hdmi_dsc->clk_per_slice = 340;
+                               break;
+                       case 5:
+                               hdmi_dsc->max_slices = 8;
+                               hdmi_dsc->clk_per_slice = 400;
+                               break;
+                       case 6:
+                               hdmi_dsc->max_slices = 12;
+                               hdmi_dsc->clk_per_slice = 400;
+                               break;
+                       case 7:
+                               hdmi_dsc->max_slices = 16;
+                               hdmi_dsc->clk_per_slice = 400;
+                               break;
+                       case 0:
+                       default:
+                               hdmi_dsc->max_slices = 0;
+                               hdmi_dsc->clk_per_slice = 0;
+                       }
+               }
+       }
+
        drm_parse_ycbcr420_deep_color_info(connector, hf_vsdb);
 }