Commit 7ff2090c authored by Imre Deak's avatar Imre Deak
Browse files

drm/i915/dp: Pass actual BW overhead to m_n calculation



A follow-up MST patch will need to specify the total BW allocation
overhead, prepare for that here by passing the amount of overhead
to intel_link_compute_m_n(), keeping the existing behavior.

v2:
- Fix passing the correct crtc_state->fec_enable param in
  intel_dp_mst_compute_link_config() /
  intel_dp_dsc_mst_compute_link_config().

Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com> (v1)
Signed-off-by: default avatarImre Deak <imre.deak@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231030155843.2251023-13-imre.deak@intel.com
parent 3e306daa
Loading
Loading
Loading
Loading
+34 −6
Original line number Diff line number Diff line
@@ -2389,17 +2389,45 @@ static void compute_m_n(u32 *ret_m, u32 *ret_n,
	intel_reduce_m_n_ratio(ret_m, ret_n);
}

static void
add_bw_alloc_overhead(int link_clock, int bw_overhead,
		      int pixel_data_rate, int link_data_rate,
		      u32 *data_m, u32 *data_n)
{
	bool is_uhbr = intel_dp_is_uhbr_rate(link_clock);
	int ch_coding_efficiency =
		drm_dp_bw_channel_coding_efficiency(is_uhbr);

	/*
	 * TODO: adjust for actual UHBR channel coding efficiency and BW
	 * overhead.
	 */
	if (is_uhbr) {
		*data_m = pixel_data_rate;
		*data_n = link_data_rate * 8 / 10;
		return;
	}

	*data_m = DIV_ROUND_UP_ULL(mul_u32_u32(pixel_data_rate, bw_overhead),
				   1000000);
	*data_n = DIV_ROUND_DOWN_ULL(mul_u32_u32(link_data_rate, ch_coding_efficiency),
				     1000000);
}

void
intel_link_compute_m_n(u16 bits_per_pixel, int nlanes,
		       int pixel_clock, int link_clock,
		       struct intel_link_m_n *m_n,
		       bool fec_enable)
		       int bw_overhead,
		       struct intel_link_m_n *m_n)
{
	u32 data_clock = bits_per_pixel * pixel_clock;
	u32 data_m;
	u32 data_n;

	if (fec_enable)
		data_clock = intel_dp_mode_to_fec_clock(data_clock);

	add_bw_alloc_overhead(link_clock, bw_overhead,
			      data_clock,
			      link_clock * 10 * nlanes,
			      &data_m, &data_n);
	/*
	 * Windows/BIOS uses fixed M/N values always. Follow suit.
	 *
@@ -2409,7 +2437,7 @@ intel_link_compute_m_n(u16 bits_per_pixel, int nlanes,
	 */
	m_n->tu = 64;
	compute_m_n(&m_n->data_m, &m_n->data_n,
		    data_clock, link_clock * nlanes * 8,
		    data_m, data_n,
		    0x8000000);

	compute_m_n(&m_n->link_m, &m_n->link_n,
+2 −2
Original line number Diff line number Diff line
@@ -394,8 +394,8 @@ u8 intel_calc_active_pipes(struct intel_atomic_state *state,
			   u8 active_pipes);
void intel_link_compute_m_n(u16 bpp, int nlanes,
			    int pixel_clock, int link_clock,
			    struct intel_link_m_n *m_n,
			    bool fec_enable);
			    int bw_overhead,
			    struct intel_link_m_n *m_n);
u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
			      u32 pixel_format, u64 modifier);
enum drm_mode_status
+25 −5
Original line number Diff line number Diff line
@@ -121,10 +121,15 @@ bool intel_dp_is_edp(struct intel_dp *intel_dp)

static void intel_dp_unset_edid(struct intel_dp *intel_dp);

bool intel_dp_is_uhbr_rate(int rate)
{
	return rate >= 1000000;
}

/* Is link rate UHBR and thus 128b/132b? */
bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state)
{
	return crtc_state->port_clock >= 1000000;
	return intel_dp_is_uhbr_rate(crtc_state->port_clock);
}

static void intel_dp_set_default_sink_rates(struct intel_dp *intel_dp)
@@ -684,6 +689,20 @@ u32 intel_dp_mode_to_fec_clock(u32 mode_clock)
		       1000000U);
}

int intel_dp_bw_fec_overhead(bool fec_enabled)
{
	/*
	 * TODO: Calculate the actual overhead for a given mode.
	 * The hard-coded 1/0.972261=2.853% overhead factor
	 * corresponds (for instance) to the 8b/10b DP FEC 2.4% +
	 * 0.453% DSC overhead. This is enough for a 3840 width mode,
	 * which has a DSC overhead of up to ~0.2%, but may not be
	 * enough for a 1024 width mode where this is ~0.8% (on a 4
	 * lane DP link, with 2 DSC slices and 8 bpp color depth).
	 */
	return fec_enabled ? DP_DSC_FEC_OVERHEAD_FACTOR : 1000000;
}

static int
small_joiner_ram_size_bits(struct drm_i915_private *i915)
{
@@ -2655,8 +2674,9 @@ intel_dp_drrs_compute_config(struct intel_connector *connector,
		pixel_clock /= pipe_config->splitter.link_count;

	intel_link_compute_m_n(link_bpp, pipe_config->lane_count, pixel_clock,
			       pipe_config->port_clock, &pipe_config->dp_m2_n2,
			       pipe_config->fec_enable);
			       pipe_config->port_clock,
			       intel_dp_bw_fec_overhead(pipe_config->fec_enable),
			       &pipe_config->dp_m2_n2);

	/* FIXME: abstract this better */
	if (pipe_config->splitter.enable)
@@ -2837,8 +2857,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,
			       pipe_config->lane_count,
			       adjusted_mode->crtc_clock,
			       pipe_config->port_clock,
			       &pipe_config->dp_m_n,
			       pipe_config->fec_enable);
			       intel_dp_bw_fec_overhead(pipe_config->fec_enable),
			       &pipe_config->dp_m_n);

	/* FIXME: abstract this better */
	if (pipe_config->splitter.enable)
+2 −0
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ void intel_dp_audio_compute_config(struct intel_encoder *encoder,
				   struct drm_connector_state *conn_state);
bool intel_dp_has_hdmi_sink(struct intel_dp *intel_dp);
bool intel_dp_is_edp(struct intel_dp *intel_dp);
bool intel_dp_is_uhbr_rate(int rate);
bool intel_dp_is_uhbr(const struct intel_crtc_state *crtc_state);
bool intel_dp_is_port_edp(struct drm_i915_private *dev_priv, enum port port);
enum irqreturn intel_dp_hpd_pulse(struct intel_digital_port *dig_port,
@@ -137,6 +138,7 @@ static inline unsigned int intel_dp_unused_lane_mask(int lane_count)
}

u32 intel_dp_mode_to_fec_clock(u32 mode_clock);
int intel_dp_bw_fec_overhead(bool fec_enabled);

bool intel_dp_supports_fec(struct intel_dp *intel_dp,
			   const struct intel_connector *connector,
+4 −4
Original line number Diff line number Diff line
@@ -180,8 +180,8 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
			       crtc_state->lane_count,
			       adjusted_mode->crtc_clock,
			       crtc_state->port_clock,
			       &crtc_state->dp_m_n,
			       crtc_state->fec_enable);
			       intel_dp_bw_fec_overhead(crtc_state->fec_enable),
			       &crtc_state->dp_m_n);
	crtc_state->dp_m_n.tu = slots;

	return 0;
@@ -275,8 +275,8 @@ static int intel_dp_dsc_mst_compute_link_config(struct intel_encoder *encoder,
			       crtc_state->lane_count,
			       adjusted_mode->crtc_clock,
			       crtc_state->port_clock,
			       &crtc_state->dp_m_n,
			       crtc_state->fec_enable);
			       intel_dp_bw_fec_overhead(crtc_state->fec_enable),
			       &crtc_state->dp_m_n);
	crtc_state->dp_m_n.tu = slots;

	return 0;
Loading