1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) STMicroelectronics SA 2017
5 * Authors: Philippe Cornu <philippe.cornu@st.com>
6 * Yannick Fertre <yannick.fertre@st.com>
10 #include <linux/iopoll.h>
11 #include <linux/module.h>
13 #include <drm/drm_mipi_dsi.h>
14 #include <drm/bridge/dw_mipi_dsi.h>
15 #include <video/mipi_display.h>
17 #define HWVER_130 0x31333000 /* IP version 1.30 */
18 #define HWVER_131 0x31333100 /* IP version 1.31 */
20 /* DSI digital registers & bit definitions */
21 #define DSI_VERSION 0x00
22 #define VERSION GENMASK(31, 8)
24 /* DSI wrapper registers & bit definitions */
25 /* Note: registers are named as in the Reference Manual */
26 #define DSI_WCFGR 0x0400 /* Wrapper ConFiGuration Reg */
27 #define WCFGR_DSIM BIT(0) /* DSI Mode */
28 #define WCFGR_COLMUX GENMASK(3, 1) /* COLor MUltipleXing */
30 #define DSI_WCR 0x0404 /* Wrapper Control Reg */
31 #define WCR_DSIEN BIT(3) /* DSI ENable */
33 #define DSI_WISR 0x040C /* Wrapper Interrupt and Status Reg */
34 #define WISR_PLLLS BIT(8) /* PLL Lock Status */
35 #define WISR_RRS BIT(12) /* Regulator Ready Status */
37 #define DSI_WPCR0 0x0418 /* Wrapper Phy Conf Reg 0 */
38 #define WPCR0_UIX4 GENMASK(5, 0) /* Unit Interval X 4 */
39 #define WPCR0_TDDL BIT(16) /* Turn Disable Data Lanes */
41 #define DSI_WRPCR 0x0430 /* Wrapper Regulator & Pll Ctrl Reg */
42 #define WRPCR_PLLEN BIT(0) /* PLL ENable */
43 #define WRPCR_NDIV GENMASK(8, 2) /* pll loop DIVision Factor */
44 #define WRPCR_IDF GENMASK(14, 11) /* pll Input Division Factor */
45 #define WRPCR_ODF GENMASK(17, 16) /* pll Output Division Factor */
46 #define WRPCR_REGEN BIT(24) /* REGulator ENable */
47 #define WRPCR_BGREN BIT(28) /* BandGap Reference ENable */
55 /* dsi color format coding according to the datasheet */
65 #define LANE_MIN_KBPS 31250
66 #define LANE_MAX_KBPS 500000
68 /* Sleep & timeout for regulator on/off, pll lock/unlock & fifo empty */
70 #define TIMEOUT_US 200000
72 struct dw_mipi_dsi_stm
{
74 struct clk
*pllref_clk
;
75 struct dw_mipi_dsi
*dsi
;
81 static inline void dsi_write(struct dw_mipi_dsi_stm
*dsi
, u32 reg
, u32 val
)
83 writel(val
, dsi
->base
+ reg
);
86 static inline u32
dsi_read(struct dw_mipi_dsi_stm
*dsi
, u32 reg
)
88 return readl(dsi
->base
+ reg
);
91 static inline void dsi_set(struct dw_mipi_dsi_stm
*dsi
, u32 reg
, u32 mask
)
93 dsi_write(dsi
, reg
, dsi_read(dsi
, reg
) | mask
);
96 static inline void dsi_clear(struct dw_mipi_dsi_stm
*dsi
, u32 reg
, u32 mask
)
98 dsi_write(dsi
, reg
, dsi_read(dsi
, reg
) & ~mask
);
101 static inline void dsi_update_bits(struct dw_mipi_dsi_stm
*dsi
, u32 reg
,
104 dsi_write(dsi
, reg
, (dsi_read(dsi
, reg
) & ~mask
) | val
);
107 static enum dsi_color
dsi_color_from_mipi(enum mipi_dsi_pixel_format fmt
)
110 case MIPI_DSI_FMT_RGB888
:
112 case MIPI_DSI_FMT_RGB666
:
113 return DSI_RGB666_CONF2
;
114 case MIPI_DSI_FMT_RGB666_PACKED
:
115 return DSI_RGB666_CONF1
;
116 case MIPI_DSI_FMT_RGB565
:
117 return DSI_RGB565_CONF1
;
119 DRM_DEBUG_DRIVER("MIPI color invalid, so we use rgb888\n");
124 static int dsi_pll_get_clkout_khz(int clkin_khz
, int idf
, int ndiv
, int odf
)
126 int divisor
= idf
* odf
;
128 /* prevent from division by 0 */
132 return DIV_ROUND_CLOSEST(clkin_khz
* ndiv
, divisor
);
135 static int dsi_pll_get_params(struct dw_mipi_dsi_stm
*dsi
,
136 int clkin_khz
, int clkout_khz
,
137 int *idf
, int *ndiv
, int *odf
)
139 int i
, o
, n
, n_min
, n_max
;
140 int fvco_min
, fvco_max
, delta
, best_delta
; /* all in khz */
142 /* Early checks preventing division by 0 & odd results */
143 if (clkin_khz
<= 0 || clkout_khz
<= 0)
146 fvco_min
= dsi
->lane_min_kbps
* 2 * ODF_MAX
;
147 fvco_max
= dsi
->lane_max_kbps
* 2 * ODF_MIN
;
149 best_delta
= 1000000; /* big started value (1000000khz) */
151 for (i
= IDF_MIN
; i
<= IDF_MAX
; i
++) {
152 /* Compute ndiv range according to Fvco */
153 n_min
= ((fvco_min
* i
) / (2 * clkin_khz
)) + 1;
154 n_max
= (fvco_max
* i
) / (2 * clkin_khz
);
156 /* No need to continue idf loop if we reach ndiv max */
157 if (n_min
>= NDIV_MAX
)
160 /* Clamp ndiv to valid values */
161 if (n_min
< NDIV_MIN
)
163 if (n_max
> NDIV_MAX
)
166 for (o
= ODF_MIN
; o
<= ODF_MAX
; o
*= 2) {
167 n
= DIV_ROUND_CLOSEST(i
* o
* clkout_khz
, clkin_khz
);
168 /* Check ndiv according to vco range */
169 if (n
< n_min
|| n
> n_max
)
171 /* Check if new delta is better & saves parameters */
172 delta
= dsi_pll_get_clkout_khz(clkin_khz
, i
, n
, o
) -
176 if (delta
< best_delta
) {
182 /* fast return in case of "perfect result" */
191 static int dw_mipi_dsi_phy_init(void *priv_data
)
193 struct dw_mipi_dsi_stm
*dsi
= priv_data
;
197 /* Enable the regulator */
198 dsi_set(dsi
, DSI_WRPCR
, WRPCR_REGEN
| WRPCR_BGREN
);
199 ret
= readl_poll_timeout(dsi
->base
+ DSI_WISR
, val
, val
& WISR_RRS
,
200 SLEEP_US
, TIMEOUT_US
);
202 DRM_DEBUG_DRIVER("!TIMEOUT! waiting REGU, let's continue\n");
204 /* Enable the DSI PLL & wait for its lock */
205 dsi_set(dsi
, DSI_WRPCR
, WRPCR_PLLEN
);
206 ret
= readl_poll_timeout(dsi
->base
+ DSI_WISR
, val
, val
& WISR_PLLLS
,
207 SLEEP_US
, TIMEOUT_US
);
209 DRM_DEBUG_DRIVER("!TIMEOUT! waiting PLL, let's continue\n");
211 /* Enable the DSI wrapper */
212 dsi_set(dsi
, DSI_WCR
, WCR_DSIEN
);
218 dw_mipi_dsi_get_lane_mbps(void *priv_data
, struct drm_display_mode
*mode
,
219 unsigned long mode_flags
, u32 lanes
, u32 format
,
220 unsigned int *lane_mbps
)
222 struct dw_mipi_dsi_stm
*dsi
= priv_data
;
223 unsigned int idf
, ndiv
, odf
, pll_in_khz
, pll_out_khz
;
227 /* Update lane capabilities according to hw version */
228 dsi
->hw_version
= dsi_read(dsi
, DSI_VERSION
) & VERSION
;
229 dsi
->lane_min_kbps
= LANE_MIN_KBPS
;
230 dsi
->lane_max_kbps
= LANE_MAX_KBPS
;
231 if (dsi
->hw_version
== HWVER_131
) {
232 dsi
->lane_min_kbps
*= 2;
233 dsi
->lane_max_kbps
*= 2;
236 pll_in_khz
= (unsigned int)(clk_get_rate(dsi
->pllref_clk
) / 1000);
238 /* Compute requested pll out */
239 bpp
= mipi_dsi_pixel_format_to_bpp(format
);
240 pll_out_khz
= mode
->clock
* bpp
/ lanes
;
241 /* Add 20% to pll out to be higher than pixel bw (burst mode only) */
242 pll_out_khz
= (pll_out_khz
* 12) / 10;
243 if (pll_out_khz
> dsi
->lane_max_kbps
) {
244 pll_out_khz
= dsi
->lane_max_kbps
;
245 DRM_WARN("Warning max phy mbps is used\n");
247 if (pll_out_khz
< dsi
->lane_min_kbps
) {
248 pll_out_khz
= dsi
->lane_min_kbps
;
249 DRM_WARN("Warning min phy mbps is used\n");
252 /* Compute best pll parameters */
256 ret
= dsi_pll_get_params(dsi
, pll_in_khz
, pll_out_khz
,
259 DRM_WARN("Warning dsi_pll_get_params(): bad params\n");
261 /* Get the adjusted pll out value */
262 pll_out_khz
= dsi_pll_get_clkout_khz(pll_in_khz
, idf
, ndiv
, odf
);
264 /* Set the PLL division factors */
265 dsi_update_bits(dsi
, DSI_WRPCR
, WRPCR_NDIV
| WRPCR_IDF
| WRPCR_ODF
,
266 (ndiv
<< 2) | (idf
<< 11) | ((ffs(odf
) - 1) << 16));
268 /* Compute uix4 & set the bit period in high-speed mode */
269 val
= 4000000 / pll_out_khz
;
270 dsi_update_bits(dsi
, DSI_WPCR0
, WPCR0_UIX4
, val
);
272 /* Select video mode by resetting DSIM bit */
273 dsi_clear(dsi
, DSI_WCFGR
, WCFGR_DSIM
);
275 /* Select the color coding */
276 dsi_update_bits(dsi
, DSI_WCFGR
, WCFGR_COLMUX
,
277 dsi_color_from_mipi(format
) << 1);
279 *lane_mbps
= pll_out_khz
/ 1000;
281 DRM_DEBUG_DRIVER("pll_in %ukHz pll_out %ukHz lane_mbps %uMHz\n",
282 pll_in_khz
, pll_out_khz
, *lane_mbps
);
287 static const struct dw_mipi_dsi_phy_ops dw_mipi_dsi_stm_phy_ops
= {
288 .init
= dw_mipi_dsi_phy_init
,
289 .get_lane_mbps
= dw_mipi_dsi_get_lane_mbps
,
292 static struct dw_mipi_dsi_plat_data dw_mipi_dsi_stm_plat_data
= {
294 .phy_ops
= &dw_mipi_dsi_stm_phy_ops
,
297 static const struct of_device_id dw_mipi_dsi_stm_dt_ids
[] = {
298 { .compatible
= "st,stm32-dsi", .data
= &dw_mipi_dsi_stm_plat_data
, },
301 MODULE_DEVICE_TABLE(of
, dw_mipi_dsi_stm_dt_ids
);
303 static int dw_mipi_dsi_stm_probe(struct platform_device
*pdev
)
305 struct device
*dev
= &pdev
->dev
;
306 struct dw_mipi_dsi_stm
*dsi
;
307 struct resource
*res
;
310 dsi
= devm_kzalloc(dev
, sizeof(*dsi
), GFP_KERNEL
);
314 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
315 dsi
->base
= devm_ioremap_resource(dev
, res
);
316 if (IS_ERR(dsi
->base
)) {
317 DRM_ERROR("Unable to get dsi registers\n");
318 return PTR_ERR(dsi
->base
);
321 dsi
->pllref_clk
= devm_clk_get(dev
, "ref");
322 if (IS_ERR(dsi
->pllref_clk
)) {
323 ret
= PTR_ERR(dsi
->pllref_clk
);
324 dev_err(dev
, "Unable to get pll reference clock: %d\n", ret
);
328 ret
= clk_prepare_enable(dsi
->pllref_clk
);
330 dev_err(dev
, "%s: Failed to enable pllref_clk\n", __func__
);
334 dw_mipi_dsi_stm_plat_data
.base
= dsi
->base
;
335 dw_mipi_dsi_stm_plat_data
.priv_data
= dsi
;
337 platform_set_drvdata(pdev
, dsi
);
339 dsi
->dsi
= dw_mipi_dsi_probe(pdev
, &dw_mipi_dsi_stm_plat_data
);
340 if (IS_ERR(dsi
->dsi
)) {
341 DRM_ERROR("Failed to initialize mipi dsi host\n");
342 clk_disable_unprepare(dsi
->pllref_clk
);
343 return PTR_ERR(dsi
->dsi
);
349 static int dw_mipi_dsi_stm_remove(struct platform_device
*pdev
)
351 struct dw_mipi_dsi_stm
*dsi
= platform_get_drvdata(pdev
);
353 clk_disable_unprepare(dsi
->pllref_clk
);
354 dw_mipi_dsi_remove(dsi
->dsi
);
359 static struct platform_driver dw_mipi_dsi_stm_driver
= {
360 .probe
= dw_mipi_dsi_stm_probe
,
361 .remove
= dw_mipi_dsi_stm_remove
,
363 .of_match_table
= dw_mipi_dsi_stm_dt_ids
,
364 .name
= "stm32-display-dsi",
368 module_platform_driver(dw_mipi_dsi_stm_driver
);
370 MODULE_AUTHOR("Philippe Cornu <philippe.cornu@st.com>");
371 MODULE_AUTHOR("Yannick Fertre <yannick.fertre@st.com>");
372 MODULE_DESCRIPTION("STMicroelectronics DW MIPI DSI host controller driver");
373 MODULE_LICENSE("GPL v2");