drm/stm: dsi: Add 1.31 version support
authorPhilippe CORNU <philippe.cornu@st.com>
Mon, 22 Jan 2018 16:46:28 +0000 (17:46 +0100)
committerBenjamin Gaignard <benjamin.gaignard@linaro.org>
Tue, 30 Jan 2018 10:45:01 +0000 (11:45 +0100)
Add support for the stm dsi phy/wrapper version 1.31.
Only lane capabilities need to be modified.

Signed-off-by: Philippe Cornu <philippe.cornu@st.com>
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20180122164628.24728-1-philippe.cornu@st.com
drivers/gpu/drm/stm/dw_mipi_dsi-stm.c

index 0ba8635d738a1e4368cd13c7ae68d995270bb9de..a514b593f37c531b2a1f7fa3b04d625f64edd8a3 100644 (file)
 #include <drm/bridge/dw_mipi_dsi.h>
 #include <video/mipi_display.h>
 
-/* DSI wrapper register & bit definitions */
+#define HWVER_130                      0x31333000      /* IP version 1.30 */
+#define HWVER_131                      0x31333100      /* IP version 1.31 */
+
+/* DSI digital registers & bit definitions */
+#define DSI_VERSION                    0x00
+#define VERSION                                GENMASK(31, 8)
+
+/* DSI wrapper registers & bit definitions */
 /* Note: registers are named as in the Reference Manual */
 #define DSI_WCFGR      0x0400          /* Wrapper ConFiGuration Reg */
 #define WCFGR_DSIM     BIT(0)          /* DSI Mode */
@@ -66,6 +73,9 @@ struct dw_mipi_dsi_stm {
        void __iomem *base;
        struct clk *pllref_clk;
        struct dw_mipi_dsi *dsi;
+       u32 hw_version;
+       int lane_min_kbps;
+       int lane_max_kbps;
 };
 
 static inline void dsi_write(struct dw_mipi_dsi_stm *dsi, u32 reg, u32 val)
@@ -122,7 +132,8 @@ static int dsi_pll_get_clkout_khz(int clkin_khz, int idf, int ndiv, int odf)
        return DIV_ROUND_CLOSEST(clkin_khz * ndiv, divisor);
 }
 
-static int dsi_pll_get_params(int clkin_khz, int clkout_khz,
+static int dsi_pll_get_params(struct dw_mipi_dsi_stm *dsi,
+                             int clkin_khz, int clkout_khz,
                              int *idf, int *ndiv, int *odf)
 {
        int i, o, n, n_min, n_max;
@@ -132,8 +143,8 @@ static int dsi_pll_get_params(int clkin_khz, int clkout_khz,
        if (clkin_khz <= 0 || clkout_khz <= 0)
                return -EINVAL;
 
-       fvco_min = LANE_MIN_KBPS * 2 * ODF_MAX;
-       fvco_max = LANE_MAX_KBPS * 2 * ODF_MIN;
+       fvco_min = dsi->lane_min_kbps * 2 * ODF_MAX;
+       fvco_max = dsi->lane_max_kbps * 2 * ODF_MIN;
 
        best_delta = 1000000; /* big started value (1000000khz) */
 
@@ -213,6 +224,15 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, struct drm_display_mode *mode,
        int ret, bpp;
        u32 val;
 
+       /* Update lane capabilities according to hw version */
+       dsi->hw_version = dsi_read(dsi, DSI_VERSION) & VERSION;
+       dsi->lane_min_kbps = LANE_MIN_KBPS;
+       dsi->lane_max_kbps = LANE_MAX_KBPS;
+       if (dsi->hw_version == HWVER_131) {
+               dsi->lane_min_kbps *= 2;
+               dsi->lane_max_kbps *= 2;
+       }
+
        pll_in_khz = (unsigned int)(clk_get_rate(dsi->pllref_clk) / 1000);
 
        /* Compute requested pll out */
@@ -220,12 +240,12 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, struct drm_display_mode *mode,
        pll_out_khz = mode->clock * bpp / lanes;
        /* Add 20% to pll out to be higher than pixel bw (burst mode only) */
        pll_out_khz = (pll_out_khz * 12) / 10;
-       if (pll_out_khz > LANE_MAX_KBPS) {
-               pll_out_khz = LANE_MAX_KBPS;
+       if (pll_out_khz > dsi->lane_max_kbps) {
+               pll_out_khz = dsi->lane_max_kbps;
                DRM_WARN("Warning max phy mbps is used\n");
        }
-       if (pll_out_khz < LANE_MIN_KBPS) {
-               pll_out_khz = LANE_MIN_KBPS;
+       if (pll_out_khz < dsi->lane_min_kbps) {
+               pll_out_khz = dsi->lane_min_kbps;
                DRM_WARN("Warning min phy mbps is used\n");
        }
 
@@ -233,7 +253,8 @@ dw_mipi_dsi_get_lane_mbps(void *priv_data, struct drm_display_mode *mode,
        idf = 0;
        ndiv = 0;
        odf = 0;
-       ret = dsi_pll_get_params(pll_in_khz, pll_out_khz, &idf, &ndiv, &odf);
+       ret = dsi_pll_get_params(dsi, pll_in_khz, pll_out_khz,
+                                &idf, &ndiv, &odf);
        if (ret)
                DRM_WARN("Warning dsi_pll_get_params(): bad params\n");