From b48600bef81158785a4b2210d955102e2cd0de95 Mon Sep 17 00:00:00 2001 From: Sugar Zhang Date: Mon, 15 Aug 2022 23:32:41 +0800 Subject: [PATCH] drm/bridge: synopsys: dw-hdmi-qp; Add N/CTS for FRL mode Adds recommended N and Expected CTS Values for FRL Mode which defined in chapter 9.2.2 of HDMI Specification 2.1. Signed-off-by: Sugar Zhang Change-Id: I1a21a111a65beeb024e5740c8bd231f9f534c1b5 --- drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 64 ++++++++++++++++++++ include/drm/bridge/dw_hdmi.h | 7 +++ 2 files changed, 71 insertions(+) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c index 63f8d538b564..cc0090f39e72 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -56,6 +56,18 @@ static const unsigned int dw_hdmi_cable[] = { EXTCON_NONE, }; +/* + * Recommended N and Expected CTS Values in FRL Mode in chapter 9.2.2 + * of HDMI Specification 2.1. + */ +static const struct dw_hdmi_audio_frl_n common_frl_n_table[] = { + { .r_bit = 3, .n_32k = 4224, .n_44k1 = 5292, .n_48k = 5760, }, + { .r_bit = 6, .n_32k = 4032, .n_44k1 = 5292, .n_48k = 6048, }, + { .r_bit = 8, .n_32k = 4032, .n_44k1 = 3969, .n_48k = 6048, }, + { .r_bit = 10, .n_32k = 3456, .n_44k1 = 3969, .n_48k = 5184, }, + { .r_bit = 12, .n_32k = 3072, .n_44k1 = 3969, .n_48k = 4752, }, +}; + /* * Unless otherwise noted, entries in this table are 100% optimization. * Values can be obtained from hdmi_compute_n() but that function is @@ -341,6 +353,50 @@ static void hdmi_set_cts_n(struct dw_hdmi_qp *hdmi, unsigned int cts, AUDPKT_ACR_CONTROL1); } +static int hdmi_match_frl_n_table(struct dw_hdmi_qp *hdmi, + unsigned long r_bit, + unsigned long freq) +{ + const struct dw_hdmi_audio_frl_n *frl_n = NULL; + int i = 0, n = 0; + + for (i = 0; ARRAY_SIZE(common_frl_n_table); i++) { + if (r_bit == common_frl_n_table[i].r_bit) { + frl_n = &common_frl_n_table[i]; + break; + } + } + + if (!frl_n) + goto err; + + switch (freq) { + case 32000: + case 64000: + case 128000: + n = (freq / 32000) * frl_n->n_32k; + break; + case 44100: + case 88200: + case 176400: + n = (freq / 44100) * frl_n->n_44k1; + break; + case 48000: + case 96000: + case 192000: + n = (freq / 48000) * frl_n->n_48k; + break; + default: + goto err; + } + + return n; +err: + dev_err(hdmi->dev, "FRL; unexpected Rbit: %lu Gbps\n", r_bit); + + return 0; +} + static int hdmi_match_tmds_n_table(struct dw_hdmi_qp *hdmi, unsigned long pixel_clk, unsigned long freq) @@ -442,8 +498,16 @@ static unsigned int hdmi_compute_n(struct dw_hdmi_qp *hdmi, static unsigned int hdmi_find_n(struct dw_hdmi_qp *hdmi, unsigned long pixel_clk, unsigned long sample_rate) { + struct dw_hdmi_link_config *link_cfg = NULL; + void *data = hdmi->plat_data->phy_data; int n; + if (hdmi->plat_data->get_link_cfg) { + link_cfg = hdmi->plat_data->get_link_cfg(data); + if (link_cfg && link_cfg->frl_mode) + return hdmi_match_frl_n_table(hdmi, link_cfg->rate_per_lane, sample_rate); + } + n = hdmi_match_tmds_n_table(hdmi, pixel_clk, sample_rate); if (n > 0) return n; diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index b9db3cd803ca..600c87339ecf 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -95,6 +95,13 @@ enum dw_hdmi_phy_type { DW_HDMI_PHY_VENDOR_PHY = 0xfe, }; +struct dw_hdmi_audio_frl_n { + unsigned int r_bit; + unsigned int n_32k; + unsigned int n_44k1; + unsigned int n_48k; +}; + struct dw_hdmi_audio_tmds_n { unsigned long tmds; unsigned int n_32k;