aboutsummaryrefslogtreecommitdiffstats
path: root/testing/linux-amlogic/0032-drm-meson-Add-support-for-VIC-alternate-timings.patch
diff options
context:
space:
mode:
Diffstat (limited to 'testing/linux-amlogic/0032-drm-meson-Add-support-for-VIC-alternate-timings.patch')
-rw-r--r--testing/linux-amlogic/0032-drm-meson-Add-support-for-VIC-alternate-timings.patch328
1 files changed, 328 insertions, 0 deletions
diff --git a/testing/linux-amlogic/0032-drm-meson-Add-support-for-VIC-alternate-timings.patch b/testing/linux-amlogic/0032-drm-meson-Add-support-for-VIC-alternate-timings.patch
new file mode 100644
index 0000000000..42673f4bc2
--- /dev/null
+++ b/testing/linux-amlogic/0032-drm-meson-Add-support-for-VIC-alternate-timings.patch
@@ -0,0 +1,328 @@
+From 96c3cc9c6943cb27ee519cafe17cb563c3fcc28d Mon Sep 17 00:00:00 2001
+From: Neil Armstrong <narmstrong@baylibre.com>
+Date: Tue, 6 Nov 2018 11:54:35 +0100
+Subject: [PATCH] drm/meson: Add support for VIC alternate timings
+
+This change is an attempt to handle the alternate clock for the CEA mode.
+60Hz vs. 59.94Hz, 30Hz vs 29.97Hz or 24Hz vs 23.97Hz on the Amlogic Meson SoC
+DRM Driver pixel clock generation.
+
+The actual clock generation will be moved to the Common Clock framework once
+all the video clock are handled by the Amlogic Meson SoC clock driver,
+then these alternate timings will be handled in the same time in a cleaner
+fashion.
+
+Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
+
+---
+ drivers/gpu/drm/meson/meson_dw_hdmi.c | 12 +---
+ drivers/gpu/drm/meson/meson_vclk.c | 127 +++++++++++++++++++++++-----------
+ drivers/gpu/drm/meson/meson_vclk.h | 2 +
+ 3 files changed, 89 insertions(+), 52 deletions(-)
+
+diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c
+index df7247c..d8c5cc3 100644
+--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c
++++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c
+@@ -594,17 +594,7 @@ dw_hdmi_mode_valid(struct drm_connector *connector,
+ dev_dbg(connector->dev->dev, "%s: vclk:%d venc=%d hdmi=%d\n", __func__,
+ vclk_freq, venc_freq, hdmi_freq);
+
+- /* Finally filter by configurable vclk frequencies for VIC modes */
+- switch (vclk_freq) {
+- case 54000:
+- case 74250:
+- case 148500:
+- case 297000:
+- case 594000:
+- return MODE_OK;
+- }
+-
+- return MODE_CLOCK_RANGE;
++ return meson_vclk_vic_supported_freq(vclk_freq);
+ }
+
+ /* Encoder */
+diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
+index ae54732..5accceb 100644
+--- a/drivers/gpu/drm/meson/meson_vclk.c
++++ b/drivers/gpu/drm/meson/meson_vclk.c
+@@ -117,6 +117,8 @@
+ #define HDMI_PLL_RESET BIT(28)
+ #define HDMI_PLL_LOCK BIT(31)
+
++#define FREQ_1000_1001(_freq) DIV_ROUND_CLOSEST(_freq * 1000, 1001)
++
+ /* VID PLL Dividers */
+ enum {
+ VID_PLL_DIV_1 = 0,
+@@ -323,7 +325,7 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
+ enum {
+ /* PLL O1 O2 O3 VP DV EN TX */
+ /* 4320 /4 /4 /1 /5 /1 => /2 /2 */
+- MESON_VCLK_HDMI_ENCI_54000 = 1,
++ MESON_VCLK_HDMI_ENCI_54000 = 0,
+ /* 4320 /4 /4 /1 /5 /1 => /1 /2 */
+ MESON_VCLK_HDMI_DDR_54000,
+ /* 2970 /4 /1 /1 /5 /1 => /1 /2 */
+@@ -339,6 +341,7 @@ enum {
+ };
+
+ struct meson_vclk_params {
++ unsigned int pixel_freq;
+ unsigned int pll_base_freq;
+ unsigned int pll_od1;
+ unsigned int pll_od2;
+@@ -347,6 +350,7 @@ struct meson_vclk_params {
+ unsigned int vclk_div;
+ } params[] = {
+ [MESON_VCLK_HDMI_ENCI_54000] = {
++ .pixel_freq = 54000,
+ .pll_base_freq = 4320000,
+ .pll_od1 = 4,
+ .pll_od2 = 4,
+@@ -355,6 +359,7 @@ struct meson_vclk_params {
+ .vclk_div = 1,
+ },
+ [MESON_VCLK_HDMI_DDR_54000] = {
++ .pixel_freq = 54000,
+ .pll_base_freq = 4320000,
+ .pll_od1 = 4,
+ .pll_od2 = 4,
+@@ -363,6 +368,7 @@ struct meson_vclk_params {
+ .vclk_div = 1,
+ },
+ [MESON_VCLK_HDMI_DDR_148500] = {
++ .pixel_freq = 148500,
+ .pll_base_freq = 2970000,
+ .pll_od1 = 4,
+ .pll_od2 = 1,
+@@ -371,6 +377,7 @@ struct meson_vclk_params {
+ .vclk_div = 1,
+ },
+ [MESON_VCLK_HDMI_74250] = {
++ .pixel_freq = 74250,
+ .pll_base_freq = 2970000,
+ .pll_od1 = 2,
+ .pll_od2 = 2,
+@@ -379,6 +386,7 @@ struct meson_vclk_params {
+ .vclk_div = 1,
+ },
+ [MESON_VCLK_HDMI_148500] = {
++ .pixel_freq = 148500,
+ .pll_base_freq = 2970000,
+ .pll_od1 = 1,
+ .pll_od2 = 2,
+@@ -387,6 +395,7 @@ struct meson_vclk_params {
+ .vclk_div = 1,
+ },
+ [MESON_VCLK_HDMI_297000] = {
++ .pixel_freq = 297000,
+ .pll_base_freq = 2970000,
+ .pll_od1 = 1,
+ .pll_od2 = 1,
+@@ -395,6 +404,7 @@ struct meson_vclk_params {
+ .vclk_div = 2,
+ },
+ [MESON_VCLK_HDMI_594000] = {
++ .pixel_freq = 594000,
+ .pll_base_freq = 5940000,
+ .pll_od1 = 1,
+ .pll_od2 = 1,
+@@ -402,6 +412,7 @@ struct meson_vclk_params {
+ .vid_pll_div = VID_PLL_DIV_5,
+ .vclk_div = 1,
+ },
++ { /* sentinel */ },
+ };
+
+ static inline unsigned int pll_od_to_reg(unsigned int od)
+@@ -626,12 +637,37 @@ static void meson_hdmi_pll_generic_set(struct meson_drm *priv,
+ pll_freq);
+ }
+
++enum drm_mode_status
++meson_vclk_vic_supported_freq(unsigned int freq)
++{
++ int i;
++
++ DRM_DEBUG_DRIVER("freq = %d\n", freq);
++
++ for (i = 0 ; params[i].pixel_freq ; ++i) {
++ DRM_DEBUG_DRIVER("i = %d pixel_freq = %d alt = %d\n",
++ i, params[i].pixel_freq,
++ FREQ_1000_1001(params[i].pixel_freq));
++ /* Match strict frequency */
++ if (freq == params[i].pixel_freq)
++ return MODE_OK;
++ /* Match 1000/1001 variant */
++ if (freq == FREQ_1000_1001(params[i].pixel_freq))
++ return MODE_OK;
++ }
++
++ return MODE_CLOCK_RANGE;
++}
++EXPORT_SYMBOL_GPL(meson_vclk_vic_supported_freq);
++
+ static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
+ unsigned int od1, unsigned int od2, unsigned int od3,
+ unsigned int vid_pll_div, unsigned int vclk_div,
+ unsigned int hdmi_tx_div, unsigned int venc_div,
+- bool hdmi_use_enci)
++ bool hdmi_use_enci, bool vic_alternate_clock)
+ {
++ unsigned int m, frac;
++
+ /* Set HDMI-TX sys clock */
+ regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
+ CTS_HDMI_SYS_SEL_MASK, 0);
+@@ -646,34 +682,38 @@ static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
+ } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
+ switch (pll_base_freq) {
+ case 2970000:
+- meson_hdmi_pll_set_params(priv, 0x3d, 0xe00,
+- od1, od2, od3);
++ m = 0x3d;
++ frac = vic_alternate_clock ? 0xd02 : 0xe00;
+ break;
+ case 4320000:
+- meson_hdmi_pll_set_params(priv, 0x5a, 0,
+- od1, od2, od3);
++ m = vic_alternate_clock ? 0x59 : 0x5a;
++ frac = vic_alternate_clock ? 0xe8f : 0;
+ break;
+ case 5940000:
+- meson_hdmi_pll_set_params(priv, 0x7b, 0xc00,
+- od1, od2, od3);
++ m = 0x7b;
++ frac = vic_alternate_clock ? 0xa05 : 0xc00;
+ break;
+ }
++
++ meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
+ } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
+ meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
+ switch (pll_base_freq) {
+ case 2970000:
+- meson_hdmi_pll_set_params(priv, 0x7b, 0x300,
+- od1, od2, od3);
++ m = 0x7b;
++ frac = vic_alternate_clock ? 0x281 : 0x300;
+ break;
+ case 4320000:
+- meson_hdmi_pll_set_params(priv, 0xb4, 0,
+- od1, od2, od3);
++ m = vic_alternate_clock ? 0xb3 : 0xb4;
++ frac = vic_alternate_clock ? 0x347 : 0;
+ break;
+ case 5940000:
+- meson_hdmi_pll_set_params(priv, 0xf7, 0x200,
+- od1, od2, od3);
++ m = 0xf7;
++ frac = vic_alternate_clock ? 0x102 : 0x200;
+ break;
+ }
++
++ meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
+ }
+
+ /* Setup vid_pll divider */
+@@ -826,6 +866,7 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
+ unsigned int vclk_freq, unsigned int venc_freq,
+ unsigned int dac_freq, bool hdmi_use_enci)
+ {
++ bool vic_alternate_clock = false;
+ unsigned int freq;
+ unsigned int hdmi_tx_div;
+ unsigned int venc_div;
+@@ -843,7 +884,7 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
+ * - encp encoder
+ */
+ meson_vclk_set(priv, vclk_freq * 10, 0, 0, 0,
+- VID_PLL_DIV_5, 2, 1, 1, false);
++ VID_PLL_DIV_5, 2, 1, 1, false, false);
+ return;
+ }
+
+@@ -863,31 +904,35 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
+ return;
+ }
+
+- switch (vclk_freq) {
+- case 54000:
+- if (hdmi_use_enci)
+- freq = MESON_VCLK_HDMI_ENCI_54000;
+- else
+- freq = MESON_VCLK_HDMI_DDR_54000;
+- break;
+- case 74250:
+- freq = MESON_VCLK_HDMI_74250;
+- break;
+- case 148500:
+- if (dac_freq != 148500)
+- freq = MESON_VCLK_HDMI_DDR_148500;
+- else
+- freq = MESON_VCLK_HDMI_148500;
+- break;
+- case 297000:
+- freq = MESON_VCLK_HDMI_297000;
+- break;
+- case 594000:
+- freq = MESON_VCLK_HDMI_594000;
+- break;
+- default:
+- pr_err("Fatal Error, invalid HDMI vclk freq %d\n",
+- vclk_freq);
++ for (freq = 0 ; params[freq].pixel_freq ; ++freq) {
++ if (vclk_freq == params[freq].pixel_freq ||
++ vclk_freq == FREQ_1000_1001(params[freq].pixel_freq)) {
++ if (vclk_freq != params[freq].pixel_freq)
++ vic_alternate_clock = true;
++ else
++ vic_alternate_clock = false;
++
++ if (freq == MESON_VCLK_HDMI_ENCI_54000 &&
++ !hdmi_use_enci)
++ continue;
++
++ if (freq == MESON_VCLK_HDMI_DDR_54000 &&
++ hdmi_use_enci)
++ continue;
++
++ if (freq == MESON_VCLK_HDMI_DDR_148500 &&
++ dac_freq == vclk_freq)
++ continue;
++
++ if (freq == MESON_VCLK_HDMI_148500 &&
++ dac_freq != vclk_freq)
++ continue;
++ break;
++ }
++ }
++
++ if (!params[freq].pixel_freq) {
++ pr_err("Fatal Error, invalid HDMI vclk freq %d\n", vclk_freq);
+ return;
+ }
+
+@@ -895,6 +940,6 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
+ params[freq].pll_od1, params[freq].pll_od2,
+ params[freq].pll_od3, params[freq].vid_pll_div,
+ params[freq].vclk_div, hdmi_tx_div, venc_div,
+- hdmi_use_enci);
++ hdmi_use_enci, vic_alternate_clock);
+ }
+ EXPORT_SYMBOL_GPL(meson_vclk_setup);
+diff --git a/drivers/gpu/drm/meson/meson_vclk.h b/drivers/gpu/drm/meson/meson_vclk.h
+index 869fa3a..4bd8752 100644
+--- a/drivers/gpu/drm/meson/meson_vclk.h
++++ b/drivers/gpu/drm/meson/meson_vclk.h
+@@ -32,6 +32,8 @@ enum {
+
+ enum drm_mode_status
+ meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned int freq);
++enum drm_mode_status
++meson_vclk_vic_supported_freq(unsigned int freq);
+
+ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
+ unsigned int vclk_freq, unsigned int venc_freq,