From: Vandita Kulkarni <[email protected]> Add the clock valid checks for the HDMI FRL mode of transmission.
Introduce hdmi_port_frl_clock_valid() which validates the FRL link rate against the maximum FRL rate and the source PHY (c10/c20 or LT), and a common hdmi_port_clock_valid() wrapper that dispatches to the TMDS or FRL helper based on frl_mode. Similarly add intel_hdmi_frl_clock() and a common intel_hdmi_clock() wrapper to compute the required clock for the selected mode of transmission. Wire these into intel_hdmi_mode_clock_valid() via the common wrappers. FRL mode is not enabled yet, so the callers pass frl_mode as false and the existing TMDS behaviour is unchanged. A subsequent change will compute frl_mode and enable FRL based validation. Signed-off-by: Vandita Kulkarni <[email protected]> Signed-off-by: Ankit Nautiyal <[email protected]> --- drivers/gpu/drm/i915/display/intel_hdmi.c | 100 +++++++++++++++++++++- drivers/gpu/drm/i915/display/intel_hdmi.h | 4 +- 2 files changed, 101 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 5a3241c054f7..7170546f4779 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -64,6 +64,7 @@ #include "intel_hdmi.h" #include "intel_link_bw.h" #include "intel_lspcon.h" +#include "intel_lt_phy.h" #include "intel_panel.h" #include "intel_pfit.h" #include "intel_snps_phy.h" @@ -1921,6 +1922,78 @@ hdmi_port_tmds_clock_valid(struct intel_hdmi *hdmi, return MODE_OK; } +/* + * Returns the Fixed rate in 10 Kbps per lane required to support given + * pixel rate. + * Returns 0 for pixel rate demanding > 12 Gbps + */ +static int intel_hdmi_frl_required_bitrate(int pixel_rate_10kbps) +{ + /* + * 3 lane configurations: + * 3 Gbps * 3 = 9 Gbps; 6 Gbps * 3 = 18 Gbps. + * + * 4 lane configurations: + * 6 Gbps * 4 = 24 Gbps; 8 Gbps * 4 = 32 Gbp; + * 10 Gbps * 4 = 40 Gbps; 12 Gbps * 4 = 48 Gbps. + */ + if (pixel_rate_10kbps <= FRL_GBPS_TO_10KBPS(9)) + return FRL_GBPS_TO_10KBPS(3); + + if (pixel_rate_10kbps > FRL_GBPS_TO_10KBPS(9) && + pixel_rate_10kbps <= FRL_GBPS_TO_10KBPS(18)) + return FRL_GBPS_TO_10KBPS(6); + + if (pixel_rate_10kbps > FRL_GBPS_TO_10KBPS(18) && + pixel_rate_10kbps <= FRL_GBPS_TO_10KBPS(24)) + return FRL_GBPS_TO_10KBPS(6); + + if (pixel_rate_10kbps > FRL_GBPS_TO_10KBPS(24) && + pixel_rate_10kbps <= FRL_GBPS_TO_10KBPS(32)) + return FRL_GBPS_TO_10KBPS(8); + + if (pixel_rate_10kbps > FRL_GBPS_TO_10KBPS(32) && + pixel_rate_10kbps <= FRL_GBPS_TO_10KBPS(40)) + return FRL_GBPS_TO_10KBPS(10); + + if (pixel_rate_10kbps > FRL_GBPS_TO_10KBPS(40) && + pixel_rate_10kbps <= FRL_GBPS_TO_10KBPS(48)) + return FRL_GBPS_TO_10KBPS(12); + + /* + * pixel rate more than 48 Gbps rate, means more than + * 12 Gbps x 4 lanes. Such a rate not possible with FRL. + */ + return 0; +} + +static enum drm_mode_status +hdmi_port_frl_clock_valid(struct intel_hdmi *hdmi, int clock) +{ + struct intel_display *display = to_intel_display(hdmi); + + if (DISPLAY_VER(display) >= 35) + return intel_lt_phy_hdmi_frl_rate_valid(clock); + + if (DISPLAY_VER(display) >= 14) + return intel_cx0_phy_hdmi_frl_rate_valid(hdmi, clock); + + return MODE_OK; +} + +static enum drm_mode_status +hdmi_port_clock_valid(struct intel_hdmi *hdmi, + int clock, bool respect_downstream_limits, + bool has_hdmi_sink, bool frl_mode) +{ + if (frl_mode) + return hdmi_port_frl_clock_valid(hdmi, clock); + + return hdmi_port_tmds_clock_valid(hdmi, clock, + respect_downstream_limits, + has_hdmi_sink); +} + int intel_hdmi_tmds_clock(int clock, int bpc, enum intel_output_format sink_format) { @@ -1984,6 +2057,29 @@ static bool intel_hdmi_sink_bpc_possible(struct drm_connector *_connector, } } +static +int intel_hdmi_frl_clock(int clock, int bpc, enum intel_output_format sink_format) +{ + int pixel_rate_kbps; + + if (sink_format == INTEL_OUTPUT_FORMAT_YCBCR420) + clock /= 2; + + pixel_rate_kbps = clock * bpc * 3; + + /* find the closest frl bit rate */ + return intel_hdmi_frl_required_bitrate(pixel_rate_kbps / 10); +} + +static +int intel_hdmi_clock(int clock, int bpc, enum intel_output_format sink_format, bool frl_mode) +{ + if (frl_mode) + return intel_hdmi_frl_clock(clock, bpc, sink_format); + + return intel_hdmi_tmds_clock(clock, bpc, sink_format); +} + static enum drm_mode_status intel_hdmi_mode_clock_valid(struct drm_connector *_connector, int clock, bool has_hdmi_sink, @@ -2001,7 +2097,7 @@ intel_hdmi_mode_clock_valid(struct drm_connector *_connector, int clock, * least one color depth is accepted. */ for (bpc = 12; bpc >= 8; bpc -= 2) { - int tmds_clock = intel_hdmi_tmds_clock(clock, bpc, sink_format); + int hdmi_clock = intel_hdmi_clock(clock, bpc, sink_format, false); if (!intel_hdmi_source_bpc_possible(display, bpc)) continue; @@ -2010,7 +2106,7 @@ intel_hdmi_mode_clock_valid(struct drm_connector *_connector, int clock, sink_format)) continue; - status = hdmi_port_tmds_clock_valid(hdmi, tmds_clock, true, has_hdmi_sink); + status = hdmi_port_clock_valid(hdmi, hdmi_clock, true, has_hdmi_sink, false); if (status == MODE_OK) return MODE_OK; } diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h index 5baa38d326e5..0e78e700ebf9 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.h +++ b/drivers/gpu/drm/i915/display/intel_hdmi.h @@ -80,8 +80,10 @@ void hsw_read_infoframe(struct intel_encoder *encoder, void *frame, ssize_t len); void intel_hdmi_poll_for_scrambling_enable(const struct intel_crtc_state *crtc_state, struct drm_connector *_connector); - int intel_hdmi_sink_max_frl_rate(struct drm_connector *connector); int intel_hdmi_sink_dsc_max_frl_rate(struct drm_connector *connector); +/* FRL rate per lane (Gbps) -> PHY PLL table units (10 kbps) */ +#define FRL_GBPS_TO_10KBPS(rate) ((rate) * 100000) + #endif /* __INTEL_HDMI_H__ */ -- 2.50.1
