From: Vandita Kulkarni <[email protected]> For HDMI FRL, the transcoder Link M/N carries the ratio of the average tribyte rate (ftb_avg) to the FRL div18 clock, unlike the pixel/link clock ratio used for DP.
Compute link_m/link_n from ftb_avg and the required FRL rate, reduced by their gcd. As PIPE_LINK_M1/N1 are 32-bit wide, scale both down preserving the ratio until they fit, and store them in crtc_state. v2: Use full 32 bits for LINK_M/N for HDMI2.1. Bspec: 68848 Signed-off-by: Vandita Kulkarni <[email protected]> Signed-off-by: Ankit Nautiyal <[email protected]> --- .../gpu/drm/i915/display/intel_display_regs.h | 1 + drivers/gpu/drm/i915/display/intel_hdmi.c | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_regs.h b/drivers/gpu/drm/i915/display/intel_display_regs.h index 1abd221f966b..7e1c12560a00 100644 --- a/drivers/gpu/drm/i915/display/intel_display_regs.h +++ b/drivers/gpu/drm/i915/display/intel_display_regs.h @@ -863,6 +863,7 @@ #define TU_SIZE(x) REG_FIELD_PREP(TU_SIZE_MASK, (x) - 1) /* default size 64 */ #define DATA_LINK_M_N_MASK REG_GENMASK(23, 0) #define DATA_LINK_N_MAX (0x800000) +#define HDMI_FRL_LINK_M_N_MAX REG_GENMASK(31, 0) #define _PIPEA_DATA_N_G4X 0x70054 #define _PIPEB_DATA_N_G4X 0x71054 diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index c5f25d2d6331..ce6ad9e28bee 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -27,6 +27,7 @@ */ #include <linux/delay.h> +#include <linux/gcd.h> #include <linux/hdmi.h> #include <linux/i2c.h> #include <linux/iopoll.h> @@ -2308,6 +2309,38 @@ static int intel_hdmi_compute_tmds_clock(struct intel_encoder *encoder, return 0; } +static void +compute_frl_mn(struct intel_crtc_state *crtc_state, u32 ftb_avg_k) +{ + u64 ftb_avg, div_18_clk, gcd_val; + u64 link_m, link_n; + + ftb_avg = (u64)ftb_avg_k * 1000; + div_18_clk = mult_frac(1000000000, crtc_state->frl.required_rate, 18); + gcd_val = gcd(ftb_avg, div_18_clk); + + link_m = DIV_ROUND_UP_ULL(ftb_avg, gcd_val); + link_n = DIV_ROUND_UP_ULL(div_18_clk, gcd_val); + + /* + * PIPE_LINK_M1/N1 are 32-bit for HDMI2.1. Scale both + * down preserving the ratio until they fit the register width. + * + * #TODO check if intel_reduce_m_n_ratio() can be exported. + */ + while (link_m > HDMI_FRL_LINK_M_N_MAX || + link_n > HDMI_FRL_LINK_M_N_MAX) { + link_m >>= 1; + link_n >>= 1; + } + + crtc_state->frl.link_m = (u32)link_m; + crtc_state->frl.link_n = (u32)link_n; + + /* Frl div 18 stored in Khz */ + crtc_state->frl.div18 = DIV_ROUND_UP_ULL(div_18_clk, 1000); +} + static int intel_hdmi_compute_frl_config(struct intel_encoder *encoder, struct intel_crtc_state *crtc_state) @@ -2378,6 +2411,11 @@ intel_hdmi_compute_frl_config(struct intel_encoder *encoder, else crtc_state->frl.tb_threshold_min = 492; + compute_frl_mn(crtc_state, frl_dfm.params.ftb_avg_k); + drm_dbg_kms(display->drm, "FRL Clock: link_m = %dHz, link_n = %dHz, div18 = %dKHz\n", + crtc_state->frl.link_m, crtc_state->frl.link_n, + crtc_state->frl.div18); + /* * TODO * 1. Calculate condition for Reseource based scheduling enable. -- 2.50.1
