1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
5 * Mark Yao <mark.yao@rock-chips.com>
6 * Sandy Huang <hjc@rock-chips.com>
10 #include <drm/drm_atomic_helper.h>
11 #include <drm/drm_dp_helper.h>
12 #include <drm/drm_panel.h>
13 #include <drm/drm_of.h>
14 #include <drm/drm_probe_helper.h>
16 #include <linux/component.h>
17 #include <linux/clk.h>
18 #include <linux/mfd/syscon.h>
19 #include <linux/of_graph.h>
20 #include <linux/pinctrl/devinfo.h>
21 #include <linux/pm_runtime.h>
22 #include <linux/regmap.h>
23 #include <linux/reset.h>
25 #include "rockchip_drm_drv.h"
26 #include "rockchip_drm_vop.h"
27 #include "rockchip_lvds.h"
29 #define DISPLAY_OUTPUT_RGB 0
30 #define DISPLAY_OUTPUT_LVDS 1
31 #define DISPLAY_OUTPUT_DUAL_LVDS 2
33 #define connector_to_lvds(c) \
34 container_of(c, struct rockchip_lvds, connector)
36 #define encoder_to_lvds(c) \
37 container_of(c, struct rockchip_lvds, encoder)
40 * rockchip_lvds_soc_data - rockchip lvds Soc private data
41 * @ch1_offset: lvds channel 1 registe offset
42 * grf_soc_con6: general registe offset for LVDS contrl
43 * grf_soc_con7: general registe offset for LVDS contrl
44 * has_vop_sel: to indicate whether need to choose from different VOP.
46 struct rockchip_lvds_soc_data
{
53 struct rockchip_lvds
{
58 const struct rockchip_lvds_soc_data
*soc_data
;
59 int output
; /* rgb lvds or dual lvds output */
60 int format
; /* vesa or jeida format */
61 struct drm_device
*drm_dev
;
62 struct drm_panel
*panel
;
63 struct drm_bridge
*bridge
;
64 struct drm_connector connector
;
65 struct drm_encoder encoder
;
66 struct dev_pin_info
*pins
;
69 static inline void lvds_writel(struct rockchip_lvds
*lvds
, u32 offset
, u32 val
)
71 writel_relaxed(val
, lvds
->regs
+ offset
);
72 if (lvds
->output
== DISPLAY_OUTPUT_LVDS
)
74 writel_relaxed(val
, lvds
->regs
+ offset
+ lvds
->soc_data
->ch1_offset
);
77 static inline int lvds_name_to_format(const char *s
)
79 if (strncmp(s
, "jeida-18", 8) == 0)
81 else if (strncmp(s
, "jeida-24", 8) == 0)
83 else if (strncmp(s
, "vesa-24", 7) == 0)
89 static inline int lvds_name_to_output(const char *s
)
91 if (strncmp(s
, "rgb", 3) == 0)
92 return DISPLAY_OUTPUT_RGB
;
93 else if (strncmp(s
, "lvds", 4) == 0)
94 return DISPLAY_OUTPUT_LVDS
;
95 else if (strncmp(s
, "duallvds", 8) == 0)
96 return DISPLAY_OUTPUT_DUAL_LVDS
;
101 static int rockchip_lvds_poweron(struct rockchip_lvds
*lvds
)
106 ret
= clk_enable(lvds
->pclk
);
108 DRM_DEV_ERROR(lvds
->dev
, "failed to enable lvds pclk %d\n", ret
);
111 ret
= pm_runtime_get_sync(lvds
->dev
);
113 DRM_DEV_ERROR(lvds
->dev
, "failed to get pm runtime: %d\n", ret
);
114 clk_disable(lvds
->pclk
);
117 val
= RK3288_LVDS_CH0_REG0_LANE4_EN
| RK3288_LVDS_CH0_REG0_LANE3_EN
|
118 RK3288_LVDS_CH0_REG0_LANE2_EN
| RK3288_LVDS_CH0_REG0_LANE1_EN
|
119 RK3288_LVDS_CH0_REG0_LANE0_EN
;
120 if (lvds
->output
== DISPLAY_OUTPUT_RGB
) {
121 val
|= RK3288_LVDS_CH0_REG0_TTL_EN
|
122 RK3288_LVDS_CH0_REG0_LANECK_EN
;
123 lvds_writel(lvds
, RK3288_LVDS_CH0_REG0
, val
);
124 lvds_writel(lvds
, RK3288_LVDS_CH0_REG2
,
125 RK3288_LVDS_PLL_FBDIV_REG2(0x46));
126 lvds_writel(lvds
, RK3288_LVDS_CH0_REG4
,
127 RK3288_LVDS_CH0_REG4_LANECK_TTL_MODE
|
128 RK3288_LVDS_CH0_REG4_LANE4_TTL_MODE
|
129 RK3288_LVDS_CH0_REG4_LANE3_TTL_MODE
|
130 RK3288_LVDS_CH0_REG4_LANE2_TTL_MODE
|
131 RK3288_LVDS_CH0_REG4_LANE1_TTL_MODE
|
132 RK3288_LVDS_CH0_REG4_LANE0_TTL_MODE
);
133 lvds_writel(lvds
, RK3288_LVDS_CH0_REG5
,
134 RK3288_LVDS_CH0_REG5_LANECK_TTL_DATA
|
135 RK3288_LVDS_CH0_REG5_LANE4_TTL_DATA
|
136 RK3288_LVDS_CH0_REG5_LANE3_TTL_DATA
|
137 RK3288_LVDS_CH0_REG5_LANE2_TTL_DATA
|
138 RK3288_LVDS_CH0_REG5_LANE1_TTL_DATA
|
139 RK3288_LVDS_CH0_REG5_LANE0_TTL_DATA
);
141 val
|= RK3288_LVDS_CH0_REG0_LVDS_EN
|
142 RK3288_LVDS_CH0_REG0_LANECK_EN
;
143 lvds_writel(lvds
, RK3288_LVDS_CH0_REG0
, val
);
144 lvds_writel(lvds
, RK3288_LVDS_CH0_REG1
,
145 RK3288_LVDS_CH0_REG1_LANECK_BIAS
|
146 RK3288_LVDS_CH0_REG1_LANE4_BIAS
|
147 RK3288_LVDS_CH0_REG1_LANE3_BIAS
|
148 RK3288_LVDS_CH0_REG1_LANE2_BIAS
|
149 RK3288_LVDS_CH0_REG1_LANE1_BIAS
|
150 RK3288_LVDS_CH0_REG1_LANE0_BIAS
);
151 lvds_writel(lvds
, RK3288_LVDS_CH0_REG2
,
152 RK3288_LVDS_CH0_REG2_RESERVE_ON
|
153 RK3288_LVDS_CH0_REG2_LANECK_LVDS_MODE
|
154 RK3288_LVDS_CH0_REG2_LANE4_LVDS_MODE
|
155 RK3288_LVDS_CH0_REG2_LANE3_LVDS_MODE
|
156 RK3288_LVDS_CH0_REG2_LANE2_LVDS_MODE
|
157 RK3288_LVDS_CH0_REG2_LANE1_LVDS_MODE
|
158 RK3288_LVDS_CH0_REG2_LANE0_LVDS_MODE
|
159 RK3288_LVDS_PLL_FBDIV_REG2(0x46));
160 lvds_writel(lvds
, RK3288_LVDS_CH0_REG4
, 0x00);
161 lvds_writel(lvds
, RK3288_LVDS_CH0_REG5
, 0x00);
163 lvds_writel(lvds
, RK3288_LVDS_CH0_REG3
, RK3288_LVDS_PLL_FBDIV_REG3(0x46));
164 lvds_writel(lvds
, RK3288_LVDS_CH0_REGD
, RK3288_LVDS_PLL_PREDIV_REGD(0x0a));
165 lvds_writel(lvds
, RK3288_LVDS_CH0_REG20
, RK3288_LVDS_CH0_REG20_LSB
);
167 lvds_writel(lvds
, RK3288_LVDS_CFG_REGC
, RK3288_LVDS_CFG_REGC_PLL_ENABLE
);
168 lvds_writel(lvds
, RK3288_LVDS_CFG_REG21
, RK3288_LVDS_CFG_REG21_TX_ENABLE
);
173 static void rockchip_lvds_poweroff(struct rockchip_lvds
*lvds
)
178 lvds_writel(lvds
, RK3288_LVDS_CFG_REG21
, RK3288_LVDS_CFG_REG21_TX_ENABLE
);
179 lvds_writel(lvds
, RK3288_LVDS_CFG_REGC
, RK3288_LVDS_CFG_REGC_PLL_ENABLE
);
180 val
= LVDS_DUAL
| LVDS_TTL_EN
| LVDS_CH0_EN
| LVDS_CH1_EN
| LVDS_PWRDN
;
182 ret
= regmap_write(lvds
->grf
, lvds
->soc_data
->grf_soc_con7
, val
);
184 DRM_DEV_ERROR(lvds
->dev
, "Could not write to GRF: %d\n", ret
);
186 pm_runtime_put(lvds
->dev
);
187 clk_disable(lvds
->pclk
);
190 static const struct drm_connector_funcs rockchip_lvds_connector_funcs
= {
191 .fill_modes
= drm_helper_probe_single_connector_modes
,
192 .destroy
= drm_connector_cleanup
,
193 .reset
= drm_atomic_helper_connector_reset
,
194 .atomic_duplicate_state
= drm_atomic_helper_connector_duplicate_state
,
195 .atomic_destroy_state
= drm_atomic_helper_connector_destroy_state
,
198 static int rockchip_lvds_connector_get_modes(struct drm_connector
*connector
)
200 struct rockchip_lvds
*lvds
= connector_to_lvds(connector
);
201 struct drm_panel
*panel
= lvds
->panel
;
203 return drm_panel_get_modes(panel
);
207 struct drm_connector_helper_funcs rockchip_lvds_connector_helper_funcs
= {
208 .get_modes
= rockchip_lvds_connector_get_modes
,
211 static void rockchip_lvds_grf_config(struct drm_encoder
*encoder
,
212 struct drm_display_mode
*mode
)
214 struct rockchip_lvds
*lvds
= encoder_to_lvds(encoder
);
215 u8 pin_hsync
= (mode
->flags
& DRM_MODE_FLAG_PHSYNC
) ? 1 : 0;
216 u8 pin_dclk
= (mode
->flags
& DRM_MODE_FLAG_PCSYNC
) ? 1 : 0;
220 /* iomux to LCD data/sync mode */
221 if (lvds
->output
== DISPLAY_OUTPUT_RGB
)
222 if (lvds
->pins
&& !IS_ERR(lvds
->pins
->default_state
))
223 pinctrl_select_state(lvds
->pins
->p
,
224 lvds
->pins
->default_state
);
225 val
= lvds
->format
| LVDS_CH0_EN
;
226 if (lvds
->output
== DISPLAY_OUTPUT_RGB
)
227 val
|= LVDS_TTL_EN
| LVDS_CH1_EN
;
228 else if (lvds
->output
== DISPLAY_OUTPUT_DUAL_LVDS
)
229 val
|= LVDS_DUAL
| LVDS_CH1_EN
;
231 if ((mode
->htotal
- mode
->hsync_start
) & 0x01)
232 val
|= LVDS_START_PHASE_RST_1
;
234 val
|= (pin_dclk
<< 8) | (pin_hsync
<< 9);
235 val
|= (0xffff << 16);
236 ret
= regmap_write(lvds
->grf
, lvds
->soc_data
->grf_soc_con7
, val
);
238 DRM_DEV_ERROR(lvds
->dev
, "Could not write to GRF: %d\n", ret
);
243 static int rockchip_lvds_set_vop_source(struct rockchip_lvds
*lvds
,
244 struct drm_encoder
*encoder
)
249 if (!lvds
->soc_data
->has_vop_sel
)
252 ret
= drm_of_encoder_active_endpoint_id(lvds
->dev
->of_node
, encoder
);
256 val
= RK3288_LVDS_SOC_CON6_SEL_VOP_LIT
<< 16;
258 val
|= RK3288_LVDS_SOC_CON6_SEL_VOP_LIT
;
260 ret
= regmap_write(lvds
->grf
, lvds
->soc_data
->grf_soc_con6
, val
);
268 rockchip_lvds_encoder_atomic_check(struct drm_encoder
*encoder
,
269 struct drm_crtc_state
*crtc_state
,
270 struct drm_connector_state
*conn_state
)
272 struct rockchip_crtc_state
*s
= to_rockchip_crtc_state(crtc_state
);
274 s
->output_mode
= ROCKCHIP_OUT_MODE_P888
;
275 s
->output_type
= DRM_MODE_CONNECTOR_LVDS
;
280 static void rockchip_lvds_encoder_enable(struct drm_encoder
*encoder
)
282 struct rockchip_lvds
*lvds
= encoder_to_lvds(encoder
);
283 struct drm_display_mode
*mode
= &encoder
->crtc
->state
->adjusted_mode
;
286 drm_panel_prepare(lvds
->panel
);
287 ret
= rockchip_lvds_poweron(lvds
);
289 DRM_DEV_ERROR(lvds
->dev
, "failed to power on lvds: %d\n", ret
);
290 drm_panel_unprepare(lvds
->panel
);
292 rockchip_lvds_grf_config(encoder
, mode
);
293 rockchip_lvds_set_vop_source(lvds
, encoder
);
294 drm_panel_enable(lvds
->panel
);
297 static void rockchip_lvds_encoder_disable(struct drm_encoder
*encoder
)
299 struct rockchip_lvds
*lvds
= encoder_to_lvds(encoder
);
301 drm_panel_disable(lvds
->panel
);
302 rockchip_lvds_poweroff(lvds
);
303 drm_panel_unprepare(lvds
->panel
);
307 struct drm_encoder_helper_funcs rockchip_lvds_encoder_helper_funcs
= {
308 .enable
= rockchip_lvds_encoder_enable
,
309 .disable
= rockchip_lvds_encoder_disable
,
310 .atomic_check
= rockchip_lvds_encoder_atomic_check
,
313 static const struct drm_encoder_funcs rockchip_lvds_encoder_funcs
= {
314 .destroy
= drm_encoder_cleanup
,
317 static const struct rockchip_lvds_soc_data rk3288_lvds_data
= {
319 .grf_soc_con6
= 0x025c,
320 .grf_soc_con7
= 0x0260,
324 static const struct of_device_id rockchip_lvds_dt_ids
[] = {
326 .compatible
= "rockchip,rk3288-lvds",
327 .data
= &rk3288_lvds_data
331 MODULE_DEVICE_TABLE(of
, rockchip_lvds_dt_ids
);
333 static int rockchip_lvds_bind(struct device
*dev
, struct device
*master
,
336 struct rockchip_lvds
*lvds
= dev_get_drvdata(dev
);
337 struct drm_device
*drm_dev
= data
;
338 struct drm_encoder
*encoder
;
339 struct drm_connector
*connector
;
340 struct device_node
*remote
= NULL
;
341 struct device_node
*port
, *endpoint
;
342 int ret
= 0, child_count
= 0;
346 lvds
->drm_dev
= drm_dev
;
347 port
= of_graph_get_port_by_id(dev
->of_node
, 1);
350 "can't found port point, please init lvds panel port!\n");
353 for_each_child_of_node(port
, endpoint
) {
355 of_property_read_u32(endpoint
, "reg", &endpoint_id
);
356 ret
= drm_of_find_panel_or_bridge(dev
->of_node
, 1, endpoint_id
,
357 &lvds
->panel
, &lvds
->bridge
);
359 of_node_put(endpoint
);
364 DRM_DEV_ERROR(dev
, "lvds port does not have any children\n");
368 DRM_DEV_ERROR(dev
, "failed to find panel and bridge node\n");
373 remote
= lvds
->panel
->dev
->of_node
;
375 remote
= lvds
->bridge
->of_node
;
376 if (of_property_read_string(dev
->of_node
, "rockchip,output", &name
))
377 /* default set it as output rgb */
378 lvds
->output
= DISPLAY_OUTPUT_RGB
;
380 lvds
->output
= lvds_name_to_output(name
);
382 if (lvds
->output
< 0) {
383 DRM_DEV_ERROR(dev
, "invalid output type [%s]\n", name
);
388 if (of_property_read_string(remote
, "data-mapping", &name
))
389 /* default set it as format vesa 18 */
390 lvds
->format
= LVDS_VESA_18
;
392 lvds
->format
= lvds_name_to_format(name
);
394 if (lvds
->format
< 0) {
395 DRM_DEV_ERROR(dev
, "invalid data-mapping format [%s]\n", name
);
400 encoder
= &lvds
->encoder
;
401 encoder
->possible_crtcs
= drm_of_find_possible_crtcs(drm_dev
,
404 ret
= drm_encoder_init(drm_dev
, encoder
, &rockchip_lvds_encoder_funcs
,
405 DRM_MODE_ENCODER_LVDS
, NULL
);
407 DRM_DEV_ERROR(drm_dev
->dev
,
408 "failed to initialize encoder: %d\n", ret
);
412 drm_encoder_helper_add(encoder
, &rockchip_lvds_encoder_helper_funcs
);
415 connector
= &lvds
->connector
;
416 connector
->dpms
= DRM_MODE_DPMS_OFF
;
417 ret
= drm_connector_init(drm_dev
, connector
,
418 &rockchip_lvds_connector_funcs
,
419 DRM_MODE_CONNECTOR_LVDS
);
421 DRM_DEV_ERROR(drm_dev
->dev
,
422 "failed to initialize connector: %d\n", ret
);
423 goto err_free_encoder
;
426 drm_connector_helper_add(connector
,
427 &rockchip_lvds_connector_helper_funcs
);
429 ret
= drm_connector_attach_encoder(connector
, encoder
);
431 DRM_DEV_ERROR(drm_dev
->dev
,
432 "failed to attach encoder: %d\n", ret
);
433 goto err_free_connector
;
436 ret
= drm_panel_attach(lvds
->panel
, connector
);
438 DRM_DEV_ERROR(drm_dev
->dev
,
439 "failed to attach panel: %d\n", ret
);
440 goto err_free_connector
;
443 ret
= drm_bridge_attach(encoder
, lvds
->bridge
, NULL
);
445 DRM_DEV_ERROR(drm_dev
->dev
,
446 "failed to attach bridge: %d\n", ret
);
447 goto err_free_encoder
;
451 pm_runtime_enable(dev
);
458 drm_connector_cleanup(connector
);
460 drm_encoder_cleanup(encoder
);
469 static void rockchip_lvds_unbind(struct device
*dev
, struct device
*master
,
472 struct rockchip_lvds
*lvds
= dev_get_drvdata(dev
);
474 rockchip_lvds_encoder_disable(&lvds
->encoder
);
476 drm_panel_detach(lvds
->panel
);
477 pm_runtime_disable(dev
);
478 drm_connector_cleanup(&lvds
->connector
);
479 drm_encoder_cleanup(&lvds
->encoder
);
482 static const struct component_ops rockchip_lvds_component_ops
= {
483 .bind
= rockchip_lvds_bind
,
484 .unbind
= rockchip_lvds_unbind
,
487 static int rockchip_lvds_probe(struct platform_device
*pdev
)
489 struct device
*dev
= &pdev
->dev
;
490 struct rockchip_lvds
*lvds
;
491 const struct of_device_id
*match
;
492 struct resource
*res
;
498 lvds
= devm_kzalloc(&pdev
->dev
, sizeof(*lvds
), GFP_KERNEL
);
503 match
= of_match_node(rockchip_lvds_dt_ids
, dev
->of_node
);
506 lvds
->soc_data
= match
->data
;
508 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
509 lvds
->regs
= devm_ioremap_resource(&pdev
->dev
, res
);
510 if (IS_ERR(lvds
->regs
))
511 return PTR_ERR(lvds
->regs
);
513 lvds
->pclk
= devm_clk_get(&pdev
->dev
, "pclk_lvds");
514 if (IS_ERR(lvds
->pclk
)) {
515 DRM_DEV_ERROR(dev
, "could not get pclk_lvds\n");
516 return PTR_ERR(lvds
->pclk
);
519 lvds
->pins
= devm_kzalloc(lvds
->dev
, sizeof(*lvds
->pins
),
524 lvds
->pins
->p
= devm_pinctrl_get(lvds
->dev
);
525 if (IS_ERR(lvds
->pins
->p
)) {
526 DRM_DEV_ERROR(dev
, "no pinctrl handle\n");
527 devm_kfree(lvds
->dev
, lvds
->pins
);
530 lvds
->pins
->default_state
=
531 pinctrl_lookup_state(lvds
->pins
->p
, "lcdc");
532 if (IS_ERR(lvds
->pins
->default_state
)) {
533 DRM_DEV_ERROR(dev
, "no default pinctrl state\n");
534 devm_kfree(lvds
->dev
, lvds
->pins
);
539 lvds
->grf
= syscon_regmap_lookup_by_phandle(dev
->of_node
,
541 if (IS_ERR(lvds
->grf
)) {
542 DRM_DEV_ERROR(dev
, "missing rockchip,grf property\n");
543 return PTR_ERR(lvds
->grf
);
546 dev_set_drvdata(dev
, lvds
);
548 ret
= clk_prepare(lvds
->pclk
);
550 DRM_DEV_ERROR(dev
, "failed to prepare pclk_lvds\n");
553 ret
= component_add(&pdev
->dev
, &rockchip_lvds_component_ops
);
555 DRM_DEV_ERROR(dev
, "failed to add component\n");
556 clk_unprepare(lvds
->pclk
);
562 static int rockchip_lvds_remove(struct platform_device
*pdev
)
564 struct rockchip_lvds
*lvds
= dev_get_drvdata(&pdev
->dev
);
566 component_del(&pdev
->dev
, &rockchip_lvds_component_ops
);
567 clk_unprepare(lvds
->pclk
);
572 struct platform_driver rockchip_lvds_driver
= {
573 .probe
= rockchip_lvds_probe
,
574 .remove
= rockchip_lvds_remove
,
576 .name
= "rockchip-lvds",
577 .of_match_table
= of_match_ptr(rockchip_lvds_dt_ids
),