Commit 2dd43144 authored by Ville Syrjälä's avatar Ville Syrjälä

drm/i915: Streamline the artihmetic

All these ROUNDING_FACTORs and whatnot are making this thing hard to
read. Get rid of them. And let's massage some of the fractions to
give us less questionable intermediate results and perhaps less
divisions.

Also looks like a good helping of 64bit math stuff is needed to
avoid some of overflows present in the current code. There
might still be a few overflows, namely when calculating
link_clks_available/samples_room (would require a huge hblank
though), and potentially when calculating hblank_rise (not sure
how large link_clks_active can get).

It looks like we're still not calculating exactly what the spec says
since we truncate tu_data and tu_line early. But I'm too lazy to
figure out if we could avoid that.

v2: Fix typo in commit msg (Uma)
    Remove ROUNDING_FACTOR define (Uma)
    s/5*link_clk+5*cdclk/5*(link_clk+cdclk)/ (Chris)

Cc: Anshuman Gupta <anshuman.gupta@intel.com>
Cc: Uma Shankar <uma.shankar@intel.com>
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200429185457.26235-3-ville.syrjala@linux.intel.comReviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarUma Shankar <uma.shankar@intel.com>
parent 41ee86d6
...@@ -514,19 +514,16 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder, ...@@ -514,19 +514,16 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder,
mutex_unlock(&dev_priv->av_mutex); mutex_unlock(&dev_priv->av_mutex);
} }
/* Add a factor to take care of rounding and truncations */ static unsigned int calc_hblank_early_prog(struct intel_encoder *encoder,
#define ROUNDING_FACTOR 10000 const struct intel_crtc_state *crtc_state)
static unsigned int get_hblank_early_enable_config(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{ {
struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct drm_i915_private *i915 = to_i915(encoder->base.dev);
unsigned int link_clks_available, link_clks_required; unsigned int link_clks_available, link_clks_required;
unsigned int tu_data, tu_line, link_clks_active; unsigned int tu_data, tu_line, link_clks_active;
unsigned int hblank_rise, hblank_early_prog;
unsigned int h_active, h_total, hblank_delta, pixel_clk; unsigned int h_active, h_total, hblank_delta, pixel_clk;
unsigned int fec_coeff, cdclk, vdsc_bpp; unsigned int fec_coeff, cdclk, vdsc_bpp;
unsigned int link_clk, lanes; unsigned int link_clk, lanes;
unsigned int hblank_rise;
h_active = crtc_state->hw.adjusted_mode.crtc_hdisplay; h_active = crtc_state->hw.adjusted_mode.crtc_hdisplay;
h_total = crtc_state->hw.adjusted_mode.crtc_htotal; h_total = crtc_state->hw.adjusted_mode.crtc_htotal;
...@@ -542,44 +539,33 @@ static unsigned int get_hblank_early_enable_config(struct intel_encoder *encoder ...@@ -542,44 +539,33 @@ static unsigned int get_hblank_early_enable_config(struct intel_encoder *encoder
"lanes = %u vdsc_bpp = %u cdclk = %u\n", "lanes = %u vdsc_bpp = %u cdclk = %u\n",
h_active, link_clk, lanes, vdsc_bpp, cdclk); h_active, link_clk, lanes, vdsc_bpp, cdclk);
if (WARN_ON(!link_clk || !lanes || !vdsc_bpp || !cdclk)) if (WARN_ON(!link_clk || !pixel_clk || !lanes || !vdsc_bpp || !cdclk))
return 0; return 0;
link_clks_available = ((((h_total - h_active) * link_clks_available = (h_total - h_active) * link_clk / pixel_clk - 28;
((link_clk * ROUNDING_FACTOR) / link_clks_required = DIV_ROUND_UP(192000 * h_total, 1000 * pixel_clk) * (48 / lanes + 2);
pixel_clk)) / ROUNDING_FACTOR) - 28);
link_clks_required = DIV_ROUND_UP(192000, (1000 * pixel_clk / h_total)) * ((48 /
lanes) + 2);
if (link_clks_available > link_clks_required) if (link_clks_available > link_clks_required)
hblank_delta = 32; hblank_delta = 32;
else else
hblank_delta = DIV_ROUND_UP(((((5 * ROUNDING_FACTOR) / hblank_delta = DIV64_U64_ROUND_UP(mul_u32_u32(5 * (link_clk + cdclk), pixel_clk),
link_clk) + ((5 * mul_u32_u32(link_clk, cdclk));
ROUNDING_FACTOR) /
cdclk)) * pixel_clk),
ROUNDING_FACTOR);
tu_data = (pixel_clk * vdsc_bpp * 8) / ((link_clk *
lanes * fec_coeff) / 1000000);
tu_line = (((h_active * link_clk * fec_coeff) /
1000000) / (64 * pixel_clk));
link_clks_active = (tu_line - 1) * 64 + tu_data;
hblank_rise = ((link_clks_active + 6 * DIV_ROUND_UP(link_clks_active, tu_data = div64_u64(mul_u32_u32(pixel_clk * vdsc_bpp * 8, 1000000),
250) + 4) * ((pixel_clk * ROUNDING_FACTOR) / mul_u32_u32(link_clk * lanes, fec_coeff));
link_clk)) / ROUNDING_FACTOR; tu_line = div64_u64(h_active * mul_u32_u32(link_clk, fec_coeff),
mul_u32_u32(64 * pixel_clk, 1000000));
link_clks_active = (tu_line - 1) * 64 + tu_data;
hblank_early_prog = h_active - hblank_rise + hblank_delta; hblank_rise = (link_clks_active + 6 * DIV_ROUND_UP(link_clks_active, 250) + 4) * pixel_clk / link_clk;
return hblank_early_prog; return h_active - hblank_rise + hblank_delta;
} }
static unsigned int get_sample_room_req_config(const struct intel_crtc_state *crtc_state) static unsigned int calc_samples_room(const struct intel_crtc_state *crtc_state)
{ {
unsigned int h_active, h_total, pixel_clk; unsigned int h_active, h_total, pixel_clk;
unsigned int link_clk, lanes; unsigned int link_clk, lanes;
unsigned int samples_room;
h_active = crtc_state->hw.adjusted_mode.hdisplay; h_active = crtc_state->hw.adjusted_mode.hdisplay;
h_total = crtc_state->hw.adjusted_mode.htotal; h_total = crtc_state->hw.adjusted_mode.htotal;
...@@ -587,12 +573,8 @@ static unsigned int get_sample_room_req_config(const struct intel_crtc_state *cr ...@@ -587,12 +573,8 @@ static unsigned int get_sample_room_req_config(const struct intel_crtc_state *cr
link_clk = crtc_state->port_clock; link_clk = crtc_state->port_clock;
lanes = crtc_state->lane_count; lanes = crtc_state->lane_count;
samples_room = ((((h_total - h_active) * ((link_clk * return ((h_total - h_active) * link_clk - 12 * pixel_clk) /
ROUNDING_FACTOR) / pixel_clk)) / (pixel_clk * (48 / lanes + 2));
ROUNDING_FACTOR) - 12) / ((48 /
lanes) + 2);
return samples_room;
} }
static void enable_audio_dsc_wa(struct intel_encoder *encoder, static void enable_audio_dsc_wa(struct intel_encoder *encoder,
...@@ -618,8 +600,7 @@ static void enable_audio_dsc_wa(struct intel_encoder *encoder, ...@@ -618,8 +600,7 @@ static void enable_audio_dsc_wa(struct intel_encoder *encoder,
(crtc_state->hw.adjusted_mode.hdisplay >= 3840 && (crtc_state->hw.adjusted_mode.hdisplay >= 3840 &&
crtc_state->hw.adjusted_mode.vdisplay >= 2160)) { crtc_state->hw.adjusted_mode.vdisplay >= 2160)) {
/* Get hblank early enable value required */ /* Get hblank early enable value required */
hblank_early_prog = get_hblank_early_enable_config(encoder, hblank_early_prog = calc_hblank_early_prog(encoder, crtc_state);
crtc_state);
if (hblank_early_prog < 32) { if (hblank_early_prog < 32) {
val &= ~HBLANK_START_COUNT_MASK(pipe); val &= ~HBLANK_START_COUNT_MASK(pipe);
val |= HBLANK_START_COUNT(pipe, HBLANK_START_COUNT_32); val |= HBLANK_START_COUNT(pipe, HBLANK_START_COUNT_32);
...@@ -635,7 +616,7 @@ static void enable_audio_dsc_wa(struct intel_encoder *encoder, ...@@ -635,7 +616,7 @@ static void enable_audio_dsc_wa(struct intel_encoder *encoder,
} }
/* Get samples room value required */ /* Get samples room value required */
samples_room = get_sample_room_req_config(crtc_state); samples_room = calc_samples_room(crtc_state);
if (samples_room < 3) { if (samples_room < 3) {
val &= ~NUMBER_SAMPLES_PER_LINE_MASK(pipe); val &= ~NUMBER_SAMPLES_PER_LINE_MASK(pipe);
val |= NUMBER_SAMPLES_PER_LINE(pipe, samples_room); val |= NUMBER_SAMPLES_PER_LINE(pipe, samples_room);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment