1 // SPDX-License-Identifier: GPL-2.0+
8 #include <linux/media-bus-format.h>
9 #include <linux/mfd/syscon.h>
10 #include <linux/module.h>
12 #include <linux/of_graph.h>
13 #include <linux/phy/phy.h>
14 #include <linux/platform_device.h>
15 #include <linux/pm_runtime.h>
16 #include <linux/regmap.h>
18 #include <drm/drm_atomic_state_helper.h>
19 #include <drm/drm_bridge.h>
20 #include <drm/drm_connector.h>
21 #include <drm/drm_fourcc.h>
22 #include <drm/drm_of.h>
23 #include <drm/drm_print.h>
25 #include "imx-ldb-helper.h"
27 #define LDB_CH0_10BIT_EN BIT(22)
28 #define LDB_CH1_10BIT_EN BIT(23)
29 #define LDB_CH0_DATA_WIDTH_24BIT BIT(24)
30 #define LDB_CH1_DATA_WIDTH_24BIT BIT(26)
31 #define LDB_CH0_DATA_WIDTH_30BIT (2 << 24)
32 #define LDB_CH1_DATA_WIDTH_30BIT (2 << 26)
35 #define CH_HSYNC_M(id) BIT(0 + ((id) * 2))
36 #define CH_VSYNC_M(id) BIT(1 + ((id) * 2))
37 #define CH_PHSYNC(id) BIT(0 + ((id) * 2))
38 #define CH_PVSYNC(id) BIT(1 + ((id) * 2))
40 #define DRIVER_NAME "imx8qm-ldb"
42 struct imx8qm_ldb_channel
{
43 struct ldb_channel base
;
50 struct imx8qm_ldb_channel channel
[MAX_LDB_CHAN_NUM
];
51 struct clk
*clk_pixel
;
52 struct clk
*clk_bypass
;
56 static inline struct imx8qm_ldb_channel
*
57 base_to_imx8qm_ldb_channel(struct ldb_channel
*base
)
59 return container_of(base
, struct imx8qm_ldb_channel
, base
);
62 static inline struct imx8qm_ldb
*base_to_imx8qm_ldb(struct ldb
*base
)
64 return container_of(base
, struct imx8qm_ldb
, base
);
67 static void imx8qm_ldb_set_phy_cfg(struct imx8qm_ldb
*imx8qm_ldb
,
69 bool is_split
, bool is_slave
,
70 struct phy_configure_opts_lvds
*phy_cfg
)
72 phy_cfg
->bits_per_lane_and_dclk_cycle
= 7;
74 phy_cfg
->differential_clk_rate
= is_split
? di_clk
/ 2 : di_clk
;
75 phy_cfg
->is_slave
= is_slave
;
78 static int imx8qm_ldb_bridge_atomic_check(struct drm_bridge
*bridge
,
79 struct drm_bridge_state
*bridge_state
,
80 struct drm_crtc_state
*crtc_state
,
81 struct drm_connector_state
*conn_state
)
83 struct ldb_channel
*ldb_ch
= bridge
->driver_private
;
84 struct ldb
*ldb
= ldb_ch
->ldb
;
85 struct imx8qm_ldb_channel
*imx8qm_ldb_ch
=
86 base_to_imx8qm_ldb_channel(ldb_ch
);
87 struct imx8qm_ldb
*imx8qm_ldb
= base_to_imx8qm_ldb(ldb
);
88 struct drm_display_mode
*adj
= &crtc_state
->adjusted_mode
;
89 unsigned long di_clk
= adj
->clock
* 1000;
90 bool is_split
= ldb_channel_is_split_link(ldb_ch
);
91 union phy_configure_opts opts
= { };
92 struct phy_configure_opts_lvds
*phy_cfg
= &opts
.lvds
;
95 ret
= ldb_bridge_atomic_check_helper(bridge
, bridge_state
,
96 crtc_state
, conn_state
);
100 imx8qm_ldb_set_phy_cfg(imx8qm_ldb
, di_clk
, is_split
, false, phy_cfg
);
101 ret
= phy_validate(imx8qm_ldb_ch
->phy
, PHY_MODE_LVDS
, 0, &opts
);
103 DRM_DEV_DEBUG_DRIVER(imx8qm_ldb
->dev
,
104 "failed to validate PHY: %d\n", ret
);
110 &imx8qm_ldb
->channel
[imx8qm_ldb
->active_chno
^ 1];
111 imx8qm_ldb_set_phy_cfg(imx8qm_ldb
, di_clk
, is_split
, true,
113 ret
= phy_validate(imx8qm_ldb_ch
->phy
, PHY_MODE_LVDS
, 0, &opts
);
115 DRM_DEV_DEBUG_DRIVER(imx8qm_ldb
->dev
,
116 "failed to validate slave PHY: %d\n",
126 imx8qm_ldb_bridge_mode_set(struct drm_bridge
*bridge
,
127 const struct drm_display_mode
*mode
,
128 const struct drm_display_mode
*adjusted_mode
)
130 struct ldb_channel
*ldb_ch
= bridge
->driver_private
;
131 struct ldb
*ldb
= ldb_ch
->ldb
;
132 struct imx8qm_ldb_channel
*imx8qm_ldb_ch
=
133 base_to_imx8qm_ldb_channel(ldb_ch
);
134 struct imx8qm_ldb
*imx8qm_ldb
= base_to_imx8qm_ldb(ldb
);
135 struct device
*dev
= imx8qm_ldb
->dev
;
136 unsigned long di_clk
= adjusted_mode
->clock
* 1000;
137 bool is_split
= ldb_channel_is_split_link(ldb_ch
);
138 union phy_configure_opts opts
= { };
139 struct phy_configure_opts_lvds
*phy_cfg
= &opts
.lvds
;
140 u32 chno
= ldb_ch
->chno
;
143 ret
= pm_runtime_get_sync(dev
);
145 DRM_DEV_ERROR(dev
, "failed to get runtime PM sync: %d\n", ret
);
147 ret
= phy_init(imx8qm_ldb_ch
->phy
);
149 DRM_DEV_ERROR(dev
, "failed to initialize PHY: %d\n", ret
);
151 clk_set_rate(imx8qm_ldb
->clk_bypass
, di_clk
);
152 clk_set_rate(imx8qm_ldb
->clk_pixel
, di_clk
);
154 imx8qm_ldb_set_phy_cfg(imx8qm_ldb
, di_clk
, is_split
, false, phy_cfg
);
155 ret
= phy_configure(imx8qm_ldb_ch
->phy
, &opts
);
157 DRM_DEV_ERROR(dev
, "failed to configure PHY: %d\n", ret
);
161 &imx8qm_ldb
->channel
[imx8qm_ldb
->active_chno
^ 1];
162 imx8qm_ldb_set_phy_cfg(imx8qm_ldb
, di_clk
, is_split
, true,
164 ret
= phy_configure(imx8qm_ldb_ch
->phy
, &opts
);
166 DRM_DEV_ERROR(dev
, "failed to configure slave PHY: %d\n",
170 /* input VSYNC signal from pixel link is active low */
171 if (ldb_ch
->chno
== 0 || is_split
)
172 ldb
->ldb_ctrl
|= LDB_DI0_VS_POL_ACT_LOW
;
173 if (ldb_ch
->chno
== 1 || is_split
)
174 ldb
->ldb_ctrl
|= LDB_DI1_VS_POL_ACT_LOW
;
176 switch (ldb_ch
->out_bus_format
) {
177 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG
:
179 case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA
:
180 case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG
:
181 if (ldb_ch
->chno
== 0 || is_split
)
182 ldb
->ldb_ctrl
|= LDB_CH0_DATA_WIDTH_24BIT
;
183 if (ldb_ch
->chno
== 1 || is_split
)
184 ldb
->ldb_ctrl
|= LDB_CH1_DATA_WIDTH_24BIT
;
188 ldb_bridge_mode_set_helper(bridge
, mode
, adjusted_mode
);
190 if (adjusted_mode
->flags
& DRM_MODE_FLAG_NVSYNC
)
191 regmap_update_bits(ldb
->regmap
, SS_CTRL
, CH_VSYNC_M(chno
), 0);
192 else if (adjusted_mode
->flags
& DRM_MODE_FLAG_PVSYNC
)
193 regmap_update_bits(ldb
->regmap
, SS_CTRL
,
194 CH_VSYNC_M(chno
), CH_PVSYNC(chno
));
196 if (adjusted_mode
->flags
& DRM_MODE_FLAG_NHSYNC
)
197 regmap_update_bits(ldb
->regmap
, SS_CTRL
, CH_HSYNC_M(chno
), 0);
198 else if (adjusted_mode
->flags
& DRM_MODE_FLAG_PHSYNC
)
199 regmap_update_bits(ldb
->regmap
, SS_CTRL
,
200 CH_HSYNC_M(chno
), CH_PHSYNC(chno
));
204 imx8qm_ldb_bridge_atomic_enable(struct drm_bridge
*bridge
,
205 struct drm_bridge_state
*old_bridge_state
)
207 struct ldb_channel
*ldb_ch
= bridge
->driver_private
;
208 struct ldb
*ldb
= ldb_ch
->ldb
;
209 struct imx8qm_ldb_channel
*imx8qm_ldb_ch
=
210 base_to_imx8qm_ldb_channel(ldb_ch
);
211 struct imx8qm_ldb
*imx8qm_ldb
= base_to_imx8qm_ldb(ldb
);
212 struct device
*dev
= imx8qm_ldb
->dev
;
213 bool is_split
= ldb_channel_is_split_link(ldb_ch
);
216 clk_prepare_enable(imx8qm_ldb
->clk_pixel
);
217 clk_prepare_enable(imx8qm_ldb
->clk_bypass
);
219 /* both DI0 and DI1 connect with pixel link, so ok to use DI0 only */
220 if (ldb_ch
->chno
== 0 || is_split
) {
221 ldb
->ldb_ctrl
&= ~LDB_CH0_MODE_EN_MASK
;
222 ldb
->ldb_ctrl
|= LDB_CH0_MODE_EN_TO_DI0
;
224 if (ldb_ch
->chno
== 1 || is_split
) {
225 ldb
->ldb_ctrl
&= ~LDB_CH1_MODE_EN_MASK
;
226 ldb
->ldb_ctrl
|= LDB_CH1_MODE_EN_TO_DI0
;
230 ret
= phy_power_on(imx8qm_ldb
->channel
[0].phy
);
233 "failed to power on channel0 PHY: %d\n",
236 ret
= phy_power_on(imx8qm_ldb
->channel
[1].phy
);
239 "failed to power on channel1 PHY: %d\n",
242 ret
= phy_power_on(imx8qm_ldb_ch
->phy
);
244 DRM_DEV_ERROR(dev
, "failed to power on PHY: %d\n", ret
);
247 ldb_bridge_enable_helper(bridge
);
251 imx8qm_ldb_bridge_atomic_disable(struct drm_bridge
*bridge
,
252 struct drm_bridge_state
*old_bridge_state
)
254 struct ldb_channel
*ldb_ch
= bridge
->driver_private
;
255 struct ldb
*ldb
= ldb_ch
->ldb
;
256 struct imx8qm_ldb_channel
*imx8qm_ldb_ch
=
257 base_to_imx8qm_ldb_channel(ldb_ch
);
258 struct imx8qm_ldb
*imx8qm_ldb
= base_to_imx8qm_ldb(ldb
);
259 struct device
*dev
= imx8qm_ldb
->dev
;
260 bool is_split
= ldb_channel_is_split_link(ldb_ch
);
263 ldb_bridge_disable_helper(bridge
);
266 ret
= phy_power_off(imx8qm_ldb
->channel
[0].phy
);
269 "failed to power off channel0 PHY: %d\n",
271 ret
= phy_power_off(imx8qm_ldb
->channel
[1].phy
);
274 "failed to power off channel1 PHY: %d\n",
277 ret
= phy_power_off(imx8qm_ldb_ch
->phy
);
279 DRM_DEV_ERROR(dev
, "failed to power off PHY: %d\n", ret
);
282 clk_disable_unprepare(imx8qm_ldb
->clk_bypass
);
283 clk_disable_unprepare(imx8qm_ldb
->clk_pixel
);
285 ret
= pm_runtime_put(dev
);
287 DRM_DEV_ERROR(dev
, "failed to put runtime PM: %d\n", ret
);
290 static const u32 imx8qm_ldb_bus_output_fmts
[] = {
291 MEDIA_BUS_FMT_RGB666_1X7X3_SPWG
,
292 MEDIA_BUS_FMT_RGB888_1X7X4_SPWG
,
293 MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA
,
297 static bool imx8qm_ldb_bus_output_fmt_supported(u32 fmt
)
301 for (i
= 0; i
< ARRAY_SIZE(imx8qm_ldb_bus_output_fmts
); i
++) {
302 if (imx8qm_ldb_bus_output_fmts
[i
] == fmt
)
310 imx8qm_ldb_bridge_atomic_get_input_bus_fmts(struct drm_bridge
*bridge
,
311 struct drm_bridge_state
*bridge_state
,
312 struct drm_crtc_state
*crtc_state
,
313 struct drm_connector_state
*conn_state
,
315 unsigned int *num_input_fmts
)
317 struct drm_display_info
*di
;
318 const struct drm_format_info
*finfo
;
321 if (!imx8qm_ldb_bus_output_fmt_supported(output_fmt
))
326 input_fmts
= kmalloc(sizeof(*input_fmts
), GFP_KERNEL
);
330 switch (output_fmt
) {
331 case MEDIA_BUS_FMT_FIXED
:
332 di
= &conn_state
->connector
->display_info
;
335 * Look at the first bus format to determine input format.
336 * Default to MEDIA_BUS_FMT_RGB888_1X36_CPADLO, if no match.
338 if (di
->num_bus_formats
) {
339 finfo
= drm_format_info(di
->bus_formats
[0]);
341 input_fmts
[0] = finfo
->depth
== 18 ?
342 MEDIA_BUS_FMT_RGB666_1X36_CPADLO
:
343 MEDIA_BUS_FMT_RGB888_1X36_CPADLO
;
345 input_fmts
[0] = MEDIA_BUS_FMT_RGB888_1X36_CPADLO
;
348 case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG
:
349 input_fmts
[0] = MEDIA_BUS_FMT_RGB666_1X36_CPADLO
;
351 case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG
:
352 case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA
:
353 input_fmts
[0] = MEDIA_BUS_FMT_RGB888_1X36_CPADLO
;
365 imx8qm_ldb_bridge_atomic_get_output_bus_fmts(struct drm_bridge
*bridge
,
366 struct drm_bridge_state
*bridge_state
,
367 struct drm_crtc_state
*crtc_state
,
368 struct drm_connector_state
*conn_state
,
369 unsigned int *num_output_fmts
)
371 *num_output_fmts
= ARRAY_SIZE(imx8qm_ldb_bus_output_fmts
);
372 return kmemdup(imx8qm_ldb_bus_output_fmts
,
373 sizeof(imx8qm_ldb_bus_output_fmts
), GFP_KERNEL
);
376 static enum drm_mode_status
377 imx8qm_ldb_bridge_mode_valid(struct drm_bridge
*bridge
,
378 const struct drm_display_info
*info
,
379 const struct drm_display_mode
*mode
)
381 struct ldb_channel
*ldb_ch
= bridge
->driver_private
;
382 bool is_single
= ldb_channel_is_single_link(ldb_ch
);
384 if (mode
->clock
> 300000)
385 return MODE_CLOCK_HIGH
;
387 if (mode
->clock
> 150000 && is_single
)
388 return MODE_CLOCK_HIGH
;
393 static const struct drm_bridge_funcs imx8qm_ldb_bridge_funcs
= {
394 .atomic_duplicate_state
= drm_atomic_helper_bridge_duplicate_state
,
395 .atomic_destroy_state
= drm_atomic_helper_bridge_destroy_state
,
396 .atomic_reset
= drm_atomic_helper_bridge_reset
,
397 .mode_valid
= imx8qm_ldb_bridge_mode_valid
,
398 .attach
= ldb_bridge_attach_helper
,
399 .atomic_check
= imx8qm_ldb_bridge_atomic_check
,
400 .mode_set
= imx8qm_ldb_bridge_mode_set
,
401 .atomic_enable
= imx8qm_ldb_bridge_atomic_enable
,
402 .atomic_disable
= imx8qm_ldb_bridge_atomic_disable
,
403 .atomic_get_input_bus_fmts
=
404 imx8qm_ldb_bridge_atomic_get_input_bus_fmts
,
405 .atomic_get_output_bus_fmts
=
406 imx8qm_ldb_bridge_atomic_get_output_bus_fmts
,
409 static int imx8qm_ldb_get_phy(struct imx8qm_ldb
*imx8qm_ldb
)
411 struct imx8qm_ldb_channel
*imx8qm_ldb_ch
;
412 struct ldb_channel
*ldb_ch
;
413 struct device
*dev
= imx8qm_ldb
->dev
;
416 for (i
= 0; i
< MAX_LDB_CHAN_NUM
; i
++) {
417 imx8qm_ldb_ch
= &imx8qm_ldb
->channel
[i
];
418 ldb_ch
= &imx8qm_ldb_ch
->base
;
420 if (!ldb_ch
->is_available
)
423 imx8qm_ldb_ch
->phy
= devm_of_phy_get(dev
, ldb_ch
->np
,
425 if (IS_ERR(imx8qm_ldb_ch
->phy
)) {
426 ret
= PTR_ERR(imx8qm_ldb_ch
->phy
);
427 if (ret
!= -EPROBE_DEFER
)
429 "failed to get channel%d PHY: %d\n",
438 static int imx8qm_ldb_probe(struct platform_device
*pdev
)
440 struct device
*dev
= &pdev
->dev
;
441 struct imx8qm_ldb
*imx8qm_ldb
;
442 struct imx8qm_ldb_channel
*imx8qm_ldb_ch
;
444 struct ldb_channel
*ldb_ch
;
445 struct device_node
*port1
, *port2
;
449 imx8qm_ldb
= devm_kzalloc(dev
, sizeof(*imx8qm_ldb
), GFP_KERNEL
);
453 imx8qm_ldb
->clk_pixel
= devm_clk_get(dev
, "pixel");
454 if (IS_ERR(imx8qm_ldb
->clk_pixel
)) {
455 ret
= PTR_ERR(imx8qm_ldb
->clk_pixel
);
456 if (ret
!= -EPROBE_DEFER
)
458 "failed to get pixel clock: %d\n", ret
);
462 imx8qm_ldb
->clk_bypass
= devm_clk_get(dev
, "bypass");
463 if (IS_ERR(imx8qm_ldb
->clk_bypass
)) {
464 ret
= PTR_ERR(imx8qm_ldb
->clk_bypass
);
465 if (ret
!= -EPROBE_DEFER
)
467 "failed to get bypass clock: %d\n", ret
);
471 imx8qm_ldb
->dev
= dev
;
473 ldb
= &imx8qm_ldb
->base
;
475 ldb
->ctrl_reg
= 0xe0;
477 for (i
= 0; i
< MAX_LDB_CHAN_NUM
; i
++)
478 ldb
->channel
[i
] = &imx8qm_ldb
->channel
[i
].base
;
480 ret
= ldb_init_helper(ldb
);
484 if (ldb
->available_ch_cnt
== 0) {
485 DRM_DEV_DEBUG_DRIVER(dev
, "no available channel\n");
489 if (ldb
->available_ch_cnt
== 2) {
490 port1
= of_graph_get_port_by_id(ldb
->channel
[0]->np
, 1);
491 port2
= of_graph_get_port_by_id(ldb
->channel
[1]->np
, 1);
493 drm_of_lvds_get_dual_link_pixel_order(port1
, port2
);
497 if (pixel_order
!= DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS
) {
498 DRM_DEV_ERROR(dev
, "invalid dual link pixel order: %d\n",
503 imx8qm_ldb
->active_chno
= 0;
504 imx8qm_ldb_ch
= &imx8qm_ldb
->channel
[0];
505 ldb_ch
= &imx8qm_ldb_ch
->base
;
506 ldb_ch
->link_type
= pixel_order
;
508 for (i
= 0; i
< MAX_LDB_CHAN_NUM
; i
++) {
509 imx8qm_ldb_ch
= &imx8qm_ldb
->channel
[i
];
510 ldb_ch
= &imx8qm_ldb_ch
->base
;
512 if (ldb_ch
->is_available
) {
513 imx8qm_ldb
->active_chno
= ldb_ch
->chno
;
519 ret
= imx8qm_ldb_get_phy(imx8qm_ldb
);
523 ret
= ldb_find_next_bridge_helper(ldb
);
527 platform_set_drvdata(pdev
, imx8qm_ldb
);
528 pm_runtime_enable(dev
);
530 ldb_add_bridge_helper(ldb
, &imx8qm_ldb_bridge_funcs
);
535 static void imx8qm_ldb_remove(struct platform_device
*pdev
)
537 struct imx8qm_ldb
*imx8qm_ldb
= platform_get_drvdata(pdev
);
538 struct ldb
*ldb
= &imx8qm_ldb
->base
;
540 ldb_remove_bridge_helper(ldb
);
542 pm_runtime_disable(&pdev
->dev
);
545 static int imx8qm_ldb_runtime_suspend(struct device
*dev
)
550 static int imx8qm_ldb_runtime_resume(struct device
*dev
)
552 struct imx8qm_ldb
*imx8qm_ldb
= dev_get_drvdata(dev
);
553 struct ldb
*ldb
= &imx8qm_ldb
->base
;
555 /* disable LDB by resetting the control register to POR default */
556 regmap_write(ldb
->regmap
, ldb
->ctrl_reg
, 0);
561 static const struct dev_pm_ops imx8qm_ldb_pm_ops
= {
562 RUNTIME_PM_OPS(imx8qm_ldb_runtime_suspend
, imx8qm_ldb_runtime_resume
, NULL
)
565 static const struct of_device_id imx8qm_ldb_dt_ids
[] = {
566 { .compatible
= "fsl,imx8qm-ldb" },
569 MODULE_DEVICE_TABLE(of
, imx8qm_ldb_dt_ids
);
571 static struct platform_driver imx8qm_ldb_driver
= {
572 .probe
= imx8qm_ldb_probe
,
573 .remove
= imx8qm_ldb_remove
,
575 .pm
= pm_ptr(&imx8qm_ldb_pm_ops
),
577 .of_match_table
= imx8qm_ldb_dt_ids
,
580 module_platform_driver(imx8qm_ldb_driver
);
582 MODULE_DESCRIPTION("i.MX8QM LVDS Display Bridge(LDB)/Pixel Mapper bridge driver");
583 MODULE_AUTHOR("Liu Ying <victor.liu@nxp.com>");
584 MODULE_LICENSE("GPL v2");
585 MODULE_ALIAS("platform:" DRIVER_NAME
);