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/mod_devicetable.h>
12 #include <linux/module.h>
13 #include <linux/platform_device.h>
14 #include <linux/regulator/consumer.h>
16 #include <video/mipi_display.h>
18 #include <drm/bridge/dw_mipi_dsi.h>
19 #include <drm/drm_mipi_dsi.h>
20 #include <drm/drm_print.h>
22 #define HWVER_130 0x31333000 /* IP version 1.30 */
23 #define HWVER_131 0x31333100 /* IP version 1.31 */
25 /* DSI digital registers & bit definitions */
26 #define DSI_VERSION 0x00
27 #define VERSION GENMASK(31, 8)
29 /* DSI wrapper registers & bit definitions */
30 /* Note: registers are named as in the Reference Manual */
31 #define DSI_WCFGR 0x0400 /* Wrapper ConFiGuration Reg */
32 #define WCFGR_DSIM BIT(0) /* DSI Mode */
33 #define WCFGR_COLMUX GENMASK(3, 1) /* COLor MUltipleXing */
35 #define DSI_WCR 0x0404 /* Wrapper Control Reg */
36 #define WCR_DSIEN BIT(3) /* DSI ENable */
38 #define DSI_WISR 0x040C /* Wrapper Interrupt and Status Reg */
39 #define WISR_PLLLS BIT(8) /* PLL Lock Status */
40 #define WISR_RRS BIT(12) /* Regulator Ready Status */
42 #define DSI_WPCR0 0x0418 /* Wrapper Phy Conf Reg 0 */
43 #define WPCR0_UIX4 GENMASK(5, 0) /* Unit Interval X 4 */
44 #define WPCR0_TDDL BIT(16) /* Turn Disable Data Lanes */
46 #define DSI_WRPCR 0x0430 /* Wrapper Regulator & Pll Ctrl Reg */
47 #define WRPCR_PLLEN BIT(0) /* PLL ENable */
48 #define WRPCR_NDIV GENMASK(8, 2) /* pll loop DIVision Factor */
49 #define WRPCR_IDF GENMASK(14, 11) /* pll Input Division Factor */
50 #define WRPCR_ODF GENMASK(17, 16) /* pll Output Division Factor */
51 #define WRPCR_REGEN BIT(24) /* REGulator ENable */
52 #define WRPCR_BGREN BIT(28) /* BandGap Reference ENable */
60 /* dsi color format coding according to the datasheet */
70 #define LANE_MIN_KBPS 31250
71 #define LANE_MAX_KBPS 500000
73 /* Sleep & timeout for regulator on/off, pll lock/unlock & fifo empty */
75 #define TIMEOUT_US 200000
77 struct dw_mipi_dsi_stm
{
79 struct clk
*pllref_clk
;
80 struct dw_mipi_dsi
*dsi
;
84 struct regulator
*vdd_supply
;
87 static inline void dsi_write(struct dw_mipi_dsi_stm
*dsi
, u32 reg
, u32 val
)
89 writel(val
, dsi
->base
+ reg
);
92 static inline u32
dsi_read(struct dw_mipi_dsi_stm
*dsi
, u32 reg
)
94 return readl(dsi
->base
+ reg
);
97 static inline void dsi_set(struct dw_mipi_dsi_stm
*dsi
, u32 reg
, u32 mask
)
99 dsi_write(dsi
, reg
, dsi_read(dsi
, reg
) | mask
);
102 static inline void dsi_clear(struct dw_mipi_dsi_stm
*dsi
, u32 reg
, u32 mask
)
104 dsi_write(dsi
, reg
, dsi_read(dsi
, reg
) & ~mask
);
107 static inline void dsi_update_bits(struct dw_mipi_dsi_stm
*dsi
, u32 reg
,
110 dsi_write(dsi
, reg
, (dsi_read(dsi
, reg
) & ~mask
) | val
);
113 static enum dsi_color
dsi_color_from_mipi(enum mipi_dsi_pixel_format fmt
)
116 case MIPI_DSI_FMT_RGB888
:
118 case MIPI_DSI_FMT_RGB666
:
119 return DSI_RGB666_CONF2
;
120 case MIPI_DSI_FMT_RGB666_PACKED
:
121 return DSI_RGB666_CONF1
;
122 case MIPI_DSI_FMT_RGB565
:
123 return DSI_RGB565_CONF1
;
125 DRM_DEBUG_DRIVER("MIPI color invalid, so we use rgb888\n");
130 static int dsi_pll_get_clkout_khz(int clkin_khz
, int idf
, int ndiv
, int odf
)
132 int divisor
= idf
* odf
;
134 /* prevent from division by 0 */
138 return DIV_ROUND_CLOSEST(clkin_khz
* ndiv
, divisor
);
141 static int dsi_pll_get_params(struct dw_mipi_dsi_stm
*dsi
,
142 int clkin_khz
, int clkout_khz
,
143 int *idf
, int *ndiv
, int *odf
)
145 int i
, o
, n
, n_min
, n_max
;
146 int fvco_min
, fvco_max
, delta
, best_delta
; /* all in khz */
148 /* Early checks preventing division by 0 & odd results */
149 if (clkin_khz
<= 0 || clkout_khz
<= 0)
152 fvco_min
= dsi
->lane_min_kbps
* 2 * ODF_MAX
;
153 fvco_max
= dsi
->lane_max_kbps
* 2 * ODF_MIN
;
155 best_delta
= 1000000; /* big started value (1000000khz) */
157 for (i
= IDF_MIN
; i
<= IDF_MAX
; i
++) {
158 /* Compute ndiv range according to Fvco */
159 n_min
= ((fvco_min
* i
) / (2 * clkin_khz
)) + 1;
160 n_max
= (fvco_max
* i
) / (2 * clkin_khz
);
162 /* No need to continue idf loop if we reach ndiv max */
163 if (n_min
>= NDIV_MAX
)
166 /* Clamp ndiv to valid values */
167 if (n_min
< NDIV_MIN
)
169 if (n_max
> NDIV_MAX
)
172 for (o
= ODF_MIN
; o
<= ODF_MAX
; o
*= 2) {
173 n
= DIV_ROUND_CLOSEST(i
* o
* clkout_khz
, clkin_khz
);
174 /* Check ndiv according to vco range */
175 if (n
< n_min
|| n
> n_max
)
177 /* Check if new delta is better & saves parameters */
178 delta
= dsi_pll_get_clkout_khz(clkin_khz
, i
, n
, o
) -
182 if (delta
< best_delta
) {
188 /* fast return in case of "perfect result" */
197 static int dw_mipi_dsi_phy_init(void *priv_data
)
199 struct dw_mipi_dsi_stm
*dsi
= priv_data
;
203 /* Enable the regulator */
204 dsi_set(dsi
, DSI_WRPCR
, WRPCR_REGEN
| WRPCR_BGREN
);
205 ret
= readl_poll_timeout(dsi
->base
+ DSI_WISR
, val
, val
& WISR_RRS
,
206 SLEEP_US
, TIMEOUT_US
);
208 DRM_DEBUG_DRIVER("!TIMEOUT! waiting REGU, let's continue\n");
210 /* Enable the DSI PLL & wait for its lock */
211 dsi_set(dsi
, DSI_WRPCR
, WRPCR_PLLEN
);
212 ret
= readl_poll_timeout(dsi
->base
+ DSI_WISR
, val
, val
& WISR_PLLLS
,
213 SLEEP_US
, TIMEOUT_US
);
215 DRM_DEBUG_DRIVER("!TIMEOUT! waiting PLL, let's continue\n");
220 static void dw_mipi_dsi_phy_power_on(void *priv_data
)
222 struct dw_mipi_dsi_stm
*dsi
= priv_data
;
224 DRM_DEBUG_DRIVER("\n");
226 /* Enable the DSI wrapper */
227 dsi_set(dsi
, DSI_WCR
, WCR_DSIEN
);
230 static void dw_mipi_dsi_phy_power_off(void *priv_data
)
232 struct dw_mipi_dsi_stm
*dsi
= priv_data
;
234 DRM_DEBUG_DRIVER("\n");
236 /* Disable the DSI wrapper */
237 dsi_clear(dsi
, DSI_WCR
, WCR_DSIEN
);
241 dw_mipi_dsi_get_lane_mbps(void *priv_data
, const struct drm_display_mode
*mode
,
242 unsigned long mode_flags
, u32 lanes
, u32 format
,
243 unsigned int *lane_mbps
)
245 struct dw_mipi_dsi_stm
*dsi
= priv_data
;
246 unsigned int idf
, ndiv
, odf
, pll_in_khz
, pll_out_khz
;
250 /* Update lane capabilities according to hw version */
251 dsi
->lane_min_kbps
= LANE_MIN_KBPS
;
252 dsi
->lane_max_kbps
= LANE_MAX_KBPS
;
253 if (dsi
->hw_version
== HWVER_131
) {
254 dsi
->lane_min_kbps
*= 2;
255 dsi
->lane_max_kbps
*= 2;
258 pll_in_khz
= (unsigned int)(clk_get_rate(dsi
->pllref_clk
) / 1000);
260 /* Compute requested pll out */
261 bpp
= mipi_dsi_pixel_format_to_bpp(format
);
262 pll_out_khz
= mode
->clock
* bpp
/ lanes
;
264 /* Add 20% to pll out to be higher than pixel bw (burst mode only) */
265 if (mode_flags
& MIPI_DSI_MODE_VIDEO_BURST
)
266 pll_out_khz
= (pll_out_khz
* 12) / 10;
268 if (pll_out_khz
> dsi
->lane_max_kbps
) {
269 pll_out_khz
= dsi
->lane_max_kbps
;
270 DRM_WARN("Warning max phy mbps is used\n");
272 if (pll_out_khz
< dsi
->lane_min_kbps
) {
273 pll_out_khz
= dsi
->lane_min_kbps
;
274 DRM_WARN("Warning min phy mbps is used\n");
277 /* Compute best pll parameters */
281 ret
= dsi_pll_get_params(dsi
, pll_in_khz
, pll_out_khz
,
284 DRM_WARN("Warning dsi_pll_get_params(): bad params\n");
286 /* Get the adjusted pll out value */
287 pll_out_khz
= dsi_pll_get_clkout_khz(pll_in_khz
, idf
, ndiv
, odf
);
289 /* Set the PLL division factors */
290 dsi_update_bits(dsi
, DSI_WRPCR
, WRPCR_NDIV
| WRPCR_IDF
| WRPCR_ODF
,
291 (ndiv
<< 2) | (idf
<< 11) | ((ffs(odf
) - 1) << 16));
293 /* Compute uix4 & set the bit period in high-speed mode */
294 val
= 4000000 / pll_out_khz
;
295 dsi_update_bits(dsi
, DSI_WPCR0
, WPCR0_UIX4
, val
);
297 /* Select video mode by resetting DSIM bit */
298 dsi_clear(dsi
, DSI_WCFGR
, WCFGR_DSIM
);
300 /* Select the color coding */
301 dsi_update_bits(dsi
, DSI_WCFGR
, WCFGR_COLMUX
,
302 dsi_color_from_mipi(format
) << 1);
304 *lane_mbps
= pll_out_khz
/ 1000;
306 DRM_DEBUG_DRIVER("pll_in %ukHz pll_out %ukHz lane_mbps %uMHz\n",
307 pll_in_khz
, pll_out_khz
, *lane_mbps
);
313 dw_mipi_dsi_phy_get_timing(void *priv_data
, unsigned int lane_mbps
,
314 struct dw_mipi_dsi_dphy_timing
*timing
)
316 timing
->clk_hs2lp
= 0x40;
317 timing
->clk_lp2hs
= 0x40;
318 timing
->data_hs2lp
= 0x40;
319 timing
->data_lp2hs
= 0x40;
324 static const struct dw_mipi_dsi_phy_ops dw_mipi_dsi_stm_phy_ops
= {
325 .init
= dw_mipi_dsi_phy_init
,
326 .power_on
= dw_mipi_dsi_phy_power_on
,
327 .power_off
= dw_mipi_dsi_phy_power_off
,
328 .get_lane_mbps
= dw_mipi_dsi_get_lane_mbps
,
329 .get_timing
= dw_mipi_dsi_phy_get_timing
,
332 static struct dw_mipi_dsi_plat_data dw_mipi_dsi_stm_plat_data
= {
334 .phy_ops
= &dw_mipi_dsi_stm_phy_ops
,
337 static const struct of_device_id dw_mipi_dsi_stm_dt_ids
[] = {
338 { .compatible
= "st,stm32-dsi", .data
= &dw_mipi_dsi_stm_plat_data
, },
341 MODULE_DEVICE_TABLE(of
, dw_mipi_dsi_stm_dt_ids
);
343 static int dw_mipi_dsi_stm_probe(struct platform_device
*pdev
)
345 struct device
*dev
= &pdev
->dev
;
346 struct dw_mipi_dsi_stm
*dsi
;
348 struct resource
*res
;
351 dsi
= devm_kzalloc(dev
, sizeof(*dsi
), GFP_KERNEL
);
355 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
356 dsi
->base
= devm_ioremap_resource(dev
, res
);
357 if (IS_ERR(dsi
->base
)) {
358 ret
= PTR_ERR(dsi
->base
);
359 DRM_ERROR("Unable to get dsi registers %d\n", ret
);
363 dsi
->vdd_supply
= devm_regulator_get(dev
, "phy-dsi");
364 if (IS_ERR(dsi
->vdd_supply
)) {
365 ret
= PTR_ERR(dsi
->vdd_supply
);
366 if (ret
!= -EPROBE_DEFER
)
367 DRM_ERROR("Failed to request regulator: %d\n", ret
);
371 ret
= regulator_enable(dsi
->vdd_supply
);
373 DRM_ERROR("Failed to enable regulator: %d\n", ret
);
377 dsi
->pllref_clk
= devm_clk_get(dev
, "ref");
378 if (IS_ERR(dsi
->pllref_clk
)) {
379 ret
= PTR_ERR(dsi
->pllref_clk
);
380 if (ret
!= -EPROBE_DEFER
)
381 DRM_ERROR("Unable to get pll reference clock: %d\n",
386 ret
= clk_prepare_enable(dsi
->pllref_clk
);
388 DRM_ERROR("Failed to enable pllref_clk: %d\n", ret
);
392 pclk
= devm_clk_get(dev
, "pclk");
395 DRM_ERROR("Unable to get peripheral clock: %d\n", ret
);
399 ret
= clk_prepare_enable(pclk
);
401 DRM_ERROR("%s: Failed to enable peripheral clk\n", __func__
);
405 dsi
->hw_version
= dsi_read(dsi
, DSI_VERSION
) & VERSION
;
406 clk_disable_unprepare(pclk
);
408 if (dsi
->hw_version
!= HWVER_130
&& dsi
->hw_version
!= HWVER_131
) {
410 DRM_ERROR("bad dsi hardware version\n");
414 dw_mipi_dsi_stm_plat_data
.base
= dsi
->base
;
415 dw_mipi_dsi_stm_plat_data
.priv_data
= dsi
;
417 platform_set_drvdata(pdev
, dsi
);
419 dsi
->dsi
= dw_mipi_dsi_probe(pdev
, &dw_mipi_dsi_stm_plat_data
);
420 if (IS_ERR(dsi
->dsi
)) {
421 ret
= PTR_ERR(dsi
->dsi
);
422 DRM_ERROR("Failed to initialize mipi dsi host: %d\n", ret
);
429 clk_disable_unprepare(dsi
->pllref_clk
);
431 regulator_disable(dsi
->vdd_supply
);
436 static int dw_mipi_dsi_stm_remove(struct platform_device
*pdev
)
438 struct dw_mipi_dsi_stm
*dsi
= platform_get_drvdata(pdev
);
440 dw_mipi_dsi_remove(dsi
->dsi
);
441 clk_disable_unprepare(dsi
->pllref_clk
);
442 regulator_disable(dsi
->vdd_supply
);
447 static int __maybe_unused
dw_mipi_dsi_stm_suspend(struct device
*dev
)
449 struct dw_mipi_dsi_stm
*dsi
= dw_mipi_dsi_stm_plat_data
.priv_data
;
451 DRM_DEBUG_DRIVER("\n");
453 clk_disable_unprepare(dsi
->pllref_clk
);
454 regulator_disable(dsi
->vdd_supply
);
459 static int __maybe_unused
dw_mipi_dsi_stm_resume(struct device
*dev
)
461 struct dw_mipi_dsi_stm
*dsi
= dw_mipi_dsi_stm_plat_data
.priv_data
;
464 DRM_DEBUG_DRIVER("\n");
466 ret
= regulator_enable(dsi
->vdd_supply
);
468 DRM_ERROR("Failed to enable regulator: %d\n", ret
);
472 ret
= clk_prepare_enable(dsi
->pllref_clk
);
474 regulator_disable(dsi
->vdd_supply
);
475 DRM_ERROR("Failed to enable pllref_clk: %d\n", ret
);
482 static const struct dev_pm_ops dw_mipi_dsi_stm_pm_ops
= {
483 SET_SYSTEM_SLEEP_PM_OPS(dw_mipi_dsi_stm_suspend
,
484 dw_mipi_dsi_stm_resume
)
487 static struct platform_driver dw_mipi_dsi_stm_driver
= {
488 .probe
= dw_mipi_dsi_stm_probe
,
489 .remove
= dw_mipi_dsi_stm_remove
,
491 .of_match_table
= dw_mipi_dsi_stm_dt_ids
,
492 .name
= "stm32-display-dsi",
493 .pm
= &dw_mipi_dsi_stm_pm_ops
,
497 module_platform_driver(dw_mipi_dsi_stm_driver
);
499 MODULE_AUTHOR("Philippe Cornu <philippe.cornu@st.com>");
500 MODULE_AUTHOR("Yannick Fertre <yannick.fertre@st.com>");
501 MODULE_DESCRIPTION("STMicroelectronics DW MIPI DSI host controller driver");
502 MODULE_LICENSE("GPL v2");