diff options
Diffstat (limited to 'drivers/gpu/drm/stm/dw_mipi_dsi-stm.c')
-rw-r--r-- | drivers/gpu/drm/stm/dw_mipi_dsi-stm.c | 53 |
1 files changed, 39 insertions, 14 deletions
diff --git a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c index fd02506274da..a514b593f37c 100644 --- a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c +++ b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c @@ -14,7 +14,14 @@ #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 */ @@ -65,6 +72,10 @@ enum dsi_color { 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) @@ -121,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; @@ -131,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) */ @@ -212,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 */ @@ -219,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"); } @@ -232,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"); @@ -312,21 +334,24 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev) dw_mipi_dsi_stm_plat_data.base = dsi->base; dw_mipi_dsi_stm_plat_data.priv_data = dsi; - ret = dw_mipi_dsi_probe(pdev, &dw_mipi_dsi_stm_plat_data); - if (ret) { + platform_set_drvdata(pdev, dsi); + + dsi->dsi = dw_mipi_dsi_probe(pdev, &dw_mipi_dsi_stm_plat_data); + if (IS_ERR(dsi->dsi)) { DRM_ERROR("Failed to initialize mipi dsi host\n"); clk_disable_unprepare(dsi->pllref_clk); + return PTR_ERR(dsi->dsi); } - return ret; + return 0; } static int dw_mipi_dsi_stm_remove(struct platform_device *pdev) { - struct dw_mipi_dsi_stm *dsi = dw_mipi_dsi_stm_plat_data.priv_data; + struct dw_mipi_dsi_stm *dsi = platform_get_drvdata(pdev); clk_disable_unprepare(dsi->pllref_clk); - dw_mipi_dsi_remove(pdev); + dw_mipi_dsi_remove(dsi->dsi); return 0; } |