[RFC 3/5] drm/hdmi21: Add helpers to verify non-dsc DFM requirements

Vandita Kulkarni vandita.kulkarni at intel.com
Thu Feb 3 05:50:10 UTC 2022


Add helpers to compute DFM variables and to verify if the
DFM requirements are met or not in non dsc cases.

Signed-off-by: Vandita Kulkarni <vandita.kulkarni at intel.com>
---
 drivers/gpu/drm/drm_frl_dfm_helper.c | 161 +++++++++++++++++++++++++++
 include/drm/drm_frl_dfm_helper.h     |   2 +
 2 files changed, 163 insertions(+)

diff --git a/drivers/gpu/drm/drm_frl_dfm_helper.c b/drivers/gpu/drm/drm_frl_dfm_helper.c
index 8498083adf72..087905ed630a 100644
--- a/drivers/gpu/drm/drm_frl_dfm_helper.c
+++ b/drivers/gpu/drm/drm_frl_dfm_helper.c
@@ -394,3 +394,164 @@ drm_compute_payload_utilization(u32 frl_char_payload_actual, u32 frl_char_per_li
 	utilization = (frl_char_payload_actual * EFFICIENCY_MULTIPLIER) / frl_char_per_line_period;
 	return utilization;
 }
+
+/* Collect link characteristics */
+static void
+drm_frl_dfm_compute_link_characteristics(struct drm_hdmi_frl_dfm *frl_dfm)
+{
+	u32 frl_bit_rate_min_kbps;
+
+	frl_dfm->params.pixel_clock_max_khz =
+		drm_get_max_legal_pixel_rate(frl_dfm->config.pixel_clock_nominal_khz);
+	frl_dfm->params.line_time_ns =
+			drm_get_min_video_line_period(frl_dfm->config.hblank,
+						      frl_dfm->config.hactive,
+						      frl_dfm->params.pixel_clock_max_khz);
+	frl_bit_rate_min_kbps = drm_get_min_frl_bit_rate(frl_dfm->config.bit_rate_kbps);
+	frl_dfm->params.char_rate_min_kbps = drm_get_min_frl_char_rate(frl_bit_rate_min_kbps);
+	frl_dfm->params.cfrl_line =
+		drm_get_total_frl_char_per_line_period(frl_dfm->params.line_time_ns,
+						       frl_dfm->params.char_rate_min_kbps,
+						       frl_dfm->config.lanes);
+}
+
+/* Determine FRL link overhead */
+static void drm_frl_dfm_compute_max_frl_link_overhead(struct drm_hdmi_frl_dfm *frl_dfm)
+{
+	u32 overhead_min;
+
+	overhead_min = drm_get_total_minimum_overhead(frl_dfm->config.lanes);
+	frl_dfm->params.overhead_max = drm_get_max_overhead(overhead_min);
+}
+
+/* Audio support Verification computations */
+static void
+drm_frl_dfm_compute_audio_hblank_min(struct drm_hdmi_frl_dfm *frl_dfm)
+{
+	u32 num_audio_pkt, audio_pkt_rate;
+
+	/*
+	 * TBD: get the actual audio pkt type as described in
+	 * table 6.44 of HDMI2.1 spec to find the num_audio_pkt,
+	 * for now assume audio sample packet and audio packet
+	 * layout as 1, resulting in number of audio packets
+	 * required to carry each audio sample or audio frame
+	 * as 1
+	 */
+	num_audio_pkt = 1;
+	audio_pkt_rate = drm_get_audio_pkt_rate(frl_dfm->config.audio_hz, num_audio_pkt);
+	frl_dfm->params.num_audio_pkts_line =
+		 drm_get_audio_pkts_hblank(audio_pkt_rate, frl_dfm->params.line_time_ns);
+	frl_dfm->params.hblank_audio_min =
+		    drm_get_audio_hblank_min(frl_dfm->params.num_audio_pkts_line);
+}
+
+/*
+ * Determine the number of tribytes required for active video , blanking period
+ * with the pixel configuration
+ */
+static void
+drm_frl_dfm_compute_tbactive_tbblank(struct drm_hdmi_frl_dfm *frl_dfm)
+{
+	u32 bpp, bytes_per_line;
+
+	bpp = drm_get_frl_bits_per_pixel(frl_dfm->config.color_format, frl_dfm->config.bpc);
+	bytes_per_line = drm_get_video_bytes_per_line(bpp, frl_dfm->config.hactive);
+
+	frl_dfm->params.tb_active = drm_get_active_video_tribytes_reqd(bytes_per_line);
+	frl_dfm->params.tb_blank =
+		drm_get_blanking_tribytes_avail(frl_dfm->config.color_format,
+						frl_dfm->config.hblank,
+						frl_dfm->config.bpc);
+}
+
+/* Verify the configuration meets the capacity requirements for the FRL configuration*/
+static bool
+drm_frl_dfm_verify_frl_capacity_requirement(struct drm_hdmi_frl_dfm *frl_dfm)
+{
+	u32 tactive_ref_ns, tblank_ref_ns, tactive_min_ns, tblank_min_ns;
+	u32 tborrowed_ns;
+
+	frl_dfm->params.ftb_avg_k =
+			drm_get_avg_tribyte_rate(frl_dfm->params.pixel_clock_max_khz,
+						 frl_dfm->params.tb_active, frl_dfm->params.tb_blank,
+						 frl_dfm->config.hactive, frl_dfm->config.hblank);
+	tactive_ref_ns = drm_get_tactive_ref(frl_dfm->params.line_time_ns,
+					     frl_dfm->config.hblank,
+					     frl_dfm->config.hactive);
+	tblank_ref_ns = drm_get_tblank_ref(frl_dfm->params.line_time_ns,
+					   frl_dfm->config.hblank,
+					   frl_dfm->config.hactive);
+	tactive_min_ns = drm_get_tactive_min(frl_dfm->config.lanes,
+					     frl_dfm->params.tb_active,
+					     frl_dfm->params.overhead_max,
+					     frl_dfm->params.char_rate_min_kbps);
+	tblank_min_ns = drm_get_tblank_min(frl_dfm->config.lanes,
+					     frl_dfm->params.tb_blank,
+					     frl_dfm->params.overhead_max,
+					     frl_dfm->params.char_rate_min_kbps);
+
+	if ((tactive_ref_ns >= tactive_min_ns) &&
+	    (tblank_ref_ns >= tblank_min_ns)) {
+		tborrowed_ns = 0;
+		frl_dfm->params.tb_borrowed = 0;
+		return true;
+	}
+
+	if ((tactive_ref_ns < tactive_min_ns) &&
+	    (tblank_ref_ns >= tblank_min_ns)) {
+		tborrowed_ns = tactive_min_ns - tactive_ref_ns;
+		frl_dfm->params.tb_borrowed = drm_get_tribytes_borrowed(tborrowed_ns,
+								 frl_dfm->params.ftb_avg_k);
+		if (frl_dfm->params.tb_borrowed <= TB_BORROWED_MAX)
+			return true;
+	}
+
+	return false;
+}
+
+/* Verify utilization does not exceed capacity */
+static bool
+drm_frl_dfm_verify_utilization_possible(struct drm_hdmi_frl_dfm *frl_dfm)
+{
+	u32 cfrl_free, cfrl_savings, frl_char_payload_actual;
+	u32 utilization, margin;
+
+	cfrl_free = drm_get_num_char_rc_compressible(frl_dfm->config.color_format,
+						     frl_dfm->config.bpc,
+						     frl_dfm->params.num_audio_pkts_line,
+						     frl_dfm->config.hblank);
+	cfrl_savings = drm_get_num_char_compression_savings(cfrl_free);
+	frl_char_payload_actual = drm_get_frl_char_payload_actual(frl_dfm->params.tb_active,
+								  frl_dfm->params.tb_blank,
+								  cfrl_savings);
+	utilization = drm_compute_payload_utilization(frl_char_payload_actual,
+							frl_dfm->params.cfrl_line);
+
+	margin = 1000 - (utilization + frl_dfm->params.overhead_max);
+
+	if (margin > 0)
+		return true;
+
+	return false;
+}
+
+/* Check if DFM requirement is met */
+bool
+drm_frl_dfm_nondsc_requirement_met(struct drm_hdmi_frl_dfm *frl_dfm)
+{
+	bool frl_capacity_req_met;
+
+	drm_frl_dfm_compute_max_frl_link_overhead(frl_dfm);
+	drm_frl_dfm_compute_link_characteristics(frl_dfm);
+	drm_frl_dfm_compute_audio_hblank_min(frl_dfm);
+	drm_frl_dfm_compute_tbactive_tbblank(frl_dfm);
+
+	frl_capacity_req_met = drm_frl_dfm_verify_frl_capacity_requirement(frl_dfm);
+
+	if (frl_capacity_req_met)
+		return drm_frl_dfm_verify_utilization_possible(frl_dfm);
+
+	return false;
+}
+EXPORT_SYMBOL(drm_frl_dfm_nondsc_requirement_met);
diff --git a/include/drm/drm_frl_dfm_helper.h b/include/drm/drm_frl_dfm_helper.h
index 16b8fcc7cbcc..f36b6898e9dd 100644
--- a/include/drm/drm_frl_dfm_helper.h
+++ b/include/drm/drm_frl_dfm_helper.h
@@ -123,4 +123,6 @@ struct drm_hdmi_frl_dfm {
 	struct drm_frl_dfm_params params;
 };
 
+bool drm_frl_dfm_nondsc_requirement_met(struct drm_hdmi_frl_dfm *frl_dfm);
+
 #endif
-- 
2.32.0



More information about the dri-devel mailing list