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 <linux/component.h>
11 #include <linux/mfd/syscon.h>
12 #include <linux/of_graph.h>
13 #include <linux/phy/phy.h>
14 #include <linux/pinctrl/devinfo.h>
15 #include <linux/platform_device.h>
16 #include <linux/pm_runtime.h>
17 #include <linux/regmap.h>
18 #include <linux/reset.h>
20 #include <drm/drm_atomic_helper.h>
21 #include <drm/drm_bridge.h>
22 #include <drm/drm_bridge_connector.h>
23 #include <drm/drm_of.h>
24 #include <drm/drm_panel.h>
25 #include <drm/drm_probe_helper.h>
26 #include <drm/drm_simple_kms_helper.h>
28 #include "rockchip_drm_drv.h"
29 #include "rockchip_lvds.h"
31 #define DISPLAY_OUTPUT_RGB 0
32 #define DISPLAY_OUTPUT_LVDS 1
33 #define DISPLAY_OUTPUT_DUAL_LVDS 2
38 * struct rockchip_lvds_soc_data - rockchip lvds Soc private data
39 * @probe: LVDS platform probe function
40 * @helper_funcs: LVDS connector helper functions
42 struct rockchip_lvds_soc_data
{
43 int (*probe
)(struct platform_device
*pdev
, struct rockchip_lvds
*lvds
);
44 const struct drm_encoder_helper_funcs
*helper_funcs
;
47 struct rockchip_lvds
{
53 const struct rockchip_lvds_soc_data
*soc_data
;
54 int output
; /* rgb lvds or dual lvds output */
55 int format
; /* vesa or jeida format */
56 struct drm_device
*drm_dev
;
57 struct drm_panel
*panel
;
58 struct drm_bridge
*bridge
;
59 struct drm_connector connector
;
60 struct rockchip_encoder encoder
;
61 struct dev_pin_info
*pins
;
64 static inline struct rockchip_lvds
*connector_to_lvds(struct drm_connector
*connector
)
66 return container_of(connector
, struct rockchip_lvds
, connector
);
69 static inline struct rockchip_lvds
*encoder_to_lvds(struct drm_encoder
*encoder
)
71 struct rockchip_encoder
*rkencoder
= to_rockchip_encoder(encoder
);
73 return container_of(rkencoder
, struct rockchip_lvds
, encoder
);
76 static inline void rk3288_writel(struct rockchip_lvds
*lvds
, u32 offset
,
79 writel_relaxed(val
, lvds
->regs
+ offset
);
80 if (lvds
->output
== DISPLAY_OUTPUT_LVDS
)
82 writel_relaxed(val
, lvds
->regs
+ offset
+ RK3288_LVDS_CH1_OFFSET
);
85 static inline int rockchip_lvds_name_to_format(const char *s
)
87 if (strncmp(s
, "jeida-18", 8) == 0)
89 else if (strncmp(s
, "jeida-24", 8) == 0)
91 else if (strncmp(s
, "vesa-24", 7) == 0)
97 static inline int rockchip_lvds_name_to_output(const char *s
)
99 if (strncmp(s
, "rgb", 3) == 0)
100 return DISPLAY_OUTPUT_RGB
;
101 else if (strncmp(s
, "lvds", 4) == 0)
102 return DISPLAY_OUTPUT_LVDS
;
103 else if (strncmp(s
, "duallvds", 8) == 0)
104 return DISPLAY_OUTPUT_DUAL_LVDS
;
109 static const struct drm_connector_funcs rockchip_lvds_connector_funcs
= {
110 .fill_modes
= drm_helper_probe_single_connector_modes
,
111 .destroy
= drm_connector_cleanup
,
112 .reset
= drm_atomic_helper_connector_reset
,
113 .atomic_duplicate_state
= drm_atomic_helper_connector_duplicate_state
,
114 .atomic_destroy_state
= drm_atomic_helper_connector_destroy_state
,
117 static int rockchip_lvds_connector_get_modes(struct drm_connector
*connector
)
119 struct rockchip_lvds
*lvds
= connector_to_lvds(connector
);
120 struct drm_panel
*panel
= lvds
->panel
;
122 return drm_panel_get_modes(panel
, connector
);
126 struct drm_connector_helper_funcs rockchip_lvds_connector_helper_funcs
= {
127 .get_modes
= rockchip_lvds_connector_get_modes
,
131 rockchip_lvds_encoder_atomic_check(struct drm_encoder
*encoder
,
132 struct drm_crtc_state
*crtc_state
,
133 struct drm_connector_state
*conn_state
)
135 struct rockchip_crtc_state
*s
= to_rockchip_crtc_state(crtc_state
);
137 s
->output_mode
= ROCKCHIP_OUT_MODE_P888
;
138 s
->output_type
= DRM_MODE_CONNECTOR_LVDS
;
143 static int rk3288_lvds_poweron(struct rockchip_lvds
*lvds
)
148 ret
= clk_enable(lvds
->pclk
);
150 DRM_DEV_ERROR(lvds
->dev
, "failed to enable lvds pclk %d\n", ret
);
153 ret
= pm_runtime_resume_and_get(lvds
->dev
);
155 DRM_DEV_ERROR(lvds
->dev
, "failed to get pm runtime: %d\n", ret
);
156 clk_disable(lvds
->pclk
);
159 val
= RK3288_LVDS_CH0_REG0_LANE4_EN
| RK3288_LVDS_CH0_REG0_LANE3_EN
|
160 RK3288_LVDS_CH0_REG0_LANE2_EN
| RK3288_LVDS_CH0_REG0_LANE1_EN
|
161 RK3288_LVDS_CH0_REG0_LANE0_EN
;
162 if (lvds
->output
== DISPLAY_OUTPUT_RGB
) {
163 val
|= RK3288_LVDS_CH0_REG0_TTL_EN
|
164 RK3288_LVDS_CH0_REG0_LANECK_EN
;
165 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG0
, val
);
166 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG2
,
167 RK3288_LVDS_PLL_FBDIV_REG2(0x46));
168 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG4
,
169 RK3288_LVDS_CH0_REG4_LANECK_TTL_MODE
|
170 RK3288_LVDS_CH0_REG4_LANE4_TTL_MODE
|
171 RK3288_LVDS_CH0_REG4_LANE3_TTL_MODE
|
172 RK3288_LVDS_CH0_REG4_LANE2_TTL_MODE
|
173 RK3288_LVDS_CH0_REG4_LANE1_TTL_MODE
|
174 RK3288_LVDS_CH0_REG4_LANE0_TTL_MODE
);
175 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG5
,
176 RK3288_LVDS_CH0_REG5_LANECK_TTL_DATA
|
177 RK3288_LVDS_CH0_REG5_LANE4_TTL_DATA
|
178 RK3288_LVDS_CH0_REG5_LANE3_TTL_DATA
|
179 RK3288_LVDS_CH0_REG5_LANE2_TTL_DATA
|
180 RK3288_LVDS_CH0_REG5_LANE1_TTL_DATA
|
181 RK3288_LVDS_CH0_REG5_LANE0_TTL_DATA
);
183 val
|= RK3288_LVDS_CH0_REG0_LVDS_EN
|
184 RK3288_LVDS_CH0_REG0_LANECK_EN
;
185 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG0
, val
);
186 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG1
,
187 RK3288_LVDS_CH0_REG1_LANECK_BIAS
|
188 RK3288_LVDS_CH0_REG1_LANE4_BIAS
|
189 RK3288_LVDS_CH0_REG1_LANE3_BIAS
|
190 RK3288_LVDS_CH0_REG1_LANE2_BIAS
|
191 RK3288_LVDS_CH0_REG1_LANE1_BIAS
|
192 RK3288_LVDS_CH0_REG1_LANE0_BIAS
);
193 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG2
,
194 RK3288_LVDS_CH0_REG2_RESERVE_ON
|
195 RK3288_LVDS_CH0_REG2_LANECK_LVDS_MODE
|
196 RK3288_LVDS_CH0_REG2_LANE4_LVDS_MODE
|
197 RK3288_LVDS_CH0_REG2_LANE3_LVDS_MODE
|
198 RK3288_LVDS_CH0_REG2_LANE2_LVDS_MODE
|
199 RK3288_LVDS_CH0_REG2_LANE1_LVDS_MODE
|
200 RK3288_LVDS_CH0_REG2_LANE0_LVDS_MODE
|
201 RK3288_LVDS_PLL_FBDIV_REG2(0x46));
202 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG4
, 0x00);
203 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG5
, 0x00);
205 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG3
,
206 RK3288_LVDS_PLL_FBDIV_REG3(0x46));
207 rk3288_writel(lvds
, RK3288_LVDS_CH0_REGD
,
208 RK3288_LVDS_PLL_PREDIV_REGD(0x0a));
209 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG20
,
210 RK3288_LVDS_CH0_REG20_LSB
);
212 rk3288_writel(lvds
, RK3288_LVDS_CFG_REGC
,
213 RK3288_LVDS_CFG_REGC_PLL_ENABLE
);
214 rk3288_writel(lvds
, RK3288_LVDS_CFG_REG21
,
215 RK3288_LVDS_CFG_REG21_TX_ENABLE
);
220 static void rk3288_lvds_poweroff(struct rockchip_lvds
*lvds
)
225 rk3288_writel(lvds
, RK3288_LVDS_CFG_REG21
,
226 RK3288_LVDS_CFG_REG21_TX_ENABLE
);
227 rk3288_writel(lvds
, RK3288_LVDS_CFG_REGC
,
228 RK3288_LVDS_CFG_REGC_PLL_ENABLE
);
229 val
= LVDS_DUAL
| LVDS_TTL_EN
| LVDS_CH0_EN
| LVDS_CH1_EN
| LVDS_PWRDN
;
231 ret
= regmap_write(lvds
->grf
, RK3288_LVDS_GRF_SOC_CON7
, val
);
233 DRM_DEV_ERROR(lvds
->dev
, "Could not write to GRF: %d\n", ret
);
235 pm_runtime_put(lvds
->dev
);
236 clk_disable(lvds
->pclk
);
239 static int rk3288_lvds_grf_config(struct drm_encoder
*encoder
,
240 struct drm_display_mode
*mode
)
242 struct rockchip_lvds
*lvds
= encoder_to_lvds(encoder
);
243 u8 pin_hsync
= (mode
->flags
& DRM_MODE_FLAG_PHSYNC
) ? 1 : 0;
244 u8 pin_dclk
= (mode
->flags
& DRM_MODE_FLAG_PCSYNC
) ? 1 : 0;
248 /* iomux to LCD data/sync mode */
249 if (lvds
->output
== DISPLAY_OUTPUT_RGB
)
250 if (lvds
->pins
&& !IS_ERR(lvds
->pins
->default_state
))
251 pinctrl_select_state(lvds
->pins
->p
,
252 lvds
->pins
->default_state
);
253 val
= lvds
->format
| LVDS_CH0_EN
;
254 if (lvds
->output
== DISPLAY_OUTPUT_RGB
)
255 val
|= LVDS_TTL_EN
| LVDS_CH1_EN
;
256 else if (lvds
->output
== DISPLAY_OUTPUT_DUAL_LVDS
)
257 val
|= LVDS_DUAL
| LVDS_CH1_EN
;
259 if ((mode
->htotal
- mode
->hsync_start
) & 0x01)
260 val
|= LVDS_START_PHASE_RST_1
;
262 val
|= (pin_dclk
<< 8) | (pin_hsync
<< 9);
263 val
|= (0xffff << 16);
264 ret
= regmap_write(lvds
->grf
, RK3288_LVDS_GRF_SOC_CON7
, val
);
266 DRM_DEV_ERROR(lvds
->dev
, "Could not write to GRF: %d\n", ret
);
271 static int rk3288_lvds_set_vop_source(struct rockchip_lvds
*lvds
,
272 struct drm_encoder
*encoder
)
277 ret
= drm_of_encoder_active_endpoint_id(lvds
->dev
->of_node
, encoder
);
281 val
= RK3288_LVDS_SOC_CON6_SEL_VOP_LIT
<< 16;
283 val
|= RK3288_LVDS_SOC_CON6_SEL_VOP_LIT
;
285 ret
= regmap_write(lvds
->grf
, RK3288_LVDS_GRF_SOC_CON6
, val
);
292 static void rk3288_lvds_encoder_enable(struct drm_encoder
*encoder
)
294 struct rockchip_lvds
*lvds
= encoder_to_lvds(encoder
);
295 struct drm_display_mode
*mode
= &encoder
->crtc
->state
->adjusted_mode
;
298 drm_panel_prepare(lvds
->panel
);
300 ret
= rk3288_lvds_poweron(lvds
);
302 DRM_DEV_ERROR(lvds
->dev
, "failed to power on LVDS: %d\n", ret
);
303 drm_panel_unprepare(lvds
->panel
);
307 ret
= rk3288_lvds_grf_config(encoder
, mode
);
309 DRM_DEV_ERROR(lvds
->dev
, "failed to configure LVDS: %d\n", ret
);
310 drm_panel_unprepare(lvds
->panel
);
314 ret
= rk3288_lvds_set_vop_source(lvds
, encoder
);
316 DRM_DEV_ERROR(lvds
->dev
, "failed to set VOP source: %d\n", ret
);
317 drm_panel_unprepare(lvds
->panel
);
321 drm_panel_enable(lvds
->panel
);
324 static void rk3288_lvds_encoder_disable(struct drm_encoder
*encoder
)
326 struct rockchip_lvds
*lvds
= encoder_to_lvds(encoder
);
328 drm_panel_disable(lvds
->panel
);
329 rk3288_lvds_poweroff(lvds
);
330 drm_panel_unprepare(lvds
->panel
);
333 static int px30_lvds_poweron(struct rockchip_lvds
*lvds
)
337 ret
= pm_runtime_resume_and_get(lvds
->dev
);
339 DRM_DEV_ERROR(lvds
->dev
, "failed to get pm runtime: %d\n", ret
);
343 /* Enable LVDS mode */
344 ret
= regmap_update_bits(lvds
->grf
, PX30_LVDS_GRF_PD_VO_CON1
,
345 PX30_LVDS_MODE_EN(1) | PX30_LVDS_P2S_EN(1),
346 PX30_LVDS_MODE_EN(1) | PX30_LVDS_P2S_EN(1));
348 pm_runtime_put(lvds
->dev
);
353 static void px30_lvds_poweroff(struct rockchip_lvds
*lvds
)
355 regmap_update_bits(lvds
->grf
, PX30_LVDS_GRF_PD_VO_CON1
,
356 PX30_LVDS_MODE_EN(1) | PX30_LVDS_P2S_EN(1),
357 PX30_LVDS_MODE_EN(0) | PX30_LVDS_P2S_EN(0));
359 pm_runtime_put(lvds
->dev
);
362 static int px30_lvds_grf_config(struct drm_encoder
*encoder
,
363 struct drm_display_mode
*mode
)
365 struct rockchip_lvds
*lvds
= encoder_to_lvds(encoder
);
367 if (lvds
->output
!= DISPLAY_OUTPUT_LVDS
) {
368 DRM_DEV_ERROR(lvds
->dev
, "Unsupported display output %d\n",
374 return regmap_update_bits(lvds
->grf
, PX30_LVDS_GRF_PD_VO_CON1
,
375 PX30_LVDS_FORMAT(lvds
->format
),
376 PX30_LVDS_FORMAT(lvds
->format
));
379 static int px30_lvds_set_vop_source(struct rockchip_lvds
*lvds
,
380 struct drm_encoder
*encoder
)
384 vop
= drm_of_encoder_active_endpoint_id(lvds
->dev
->of_node
, encoder
);
388 return regmap_update_bits(lvds
->grf
, PX30_LVDS_GRF_PD_VO_CON1
,
389 PX30_LVDS_VOP_SEL(1),
390 PX30_LVDS_VOP_SEL(vop
));
393 static void px30_lvds_encoder_enable(struct drm_encoder
*encoder
)
395 struct rockchip_lvds
*lvds
= encoder_to_lvds(encoder
);
396 struct drm_display_mode
*mode
= &encoder
->crtc
->state
->adjusted_mode
;
399 drm_panel_prepare(lvds
->panel
);
401 ret
= px30_lvds_poweron(lvds
);
403 DRM_DEV_ERROR(lvds
->dev
, "failed to power on LVDS: %d\n", ret
);
404 drm_panel_unprepare(lvds
->panel
);
408 ret
= px30_lvds_grf_config(encoder
, mode
);
410 DRM_DEV_ERROR(lvds
->dev
, "failed to configure LVDS: %d\n", ret
);
411 drm_panel_unprepare(lvds
->panel
);
415 ret
= px30_lvds_set_vop_source(lvds
, encoder
);
417 DRM_DEV_ERROR(lvds
->dev
, "failed to set VOP source: %d\n", ret
);
418 drm_panel_unprepare(lvds
->panel
);
422 drm_panel_enable(lvds
->panel
);
425 static void px30_lvds_encoder_disable(struct drm_encoder
*encoder
)
427 struct rockchip_lvds
*lvds
= encoder_to_lvds(encoder
);
429 drm_panel_disable(lvds
->panel
);
430 px30_lvds_poweroff(lvds
);
431 drm_panel_unprepare(lvds
->panel
);
435 struct drm_encoder_helper_funcs rk3288_lvds_encoder_helper_funcs
= {
436 .enable
= rk3288_lvds_encoder_enable
,
437 .disable
= rk3288_lvds_encoder_disable
,
438 .atomic_check
= rockchip_lvds_encoder_atomic_check
,
442 struct drm_encoder_helper_funcs px30_lvds_encoder_helper_funcs
= {
443 .enable
= px30_lvds_encoder_enable
,
444 .disable
= px30_lvds_encoder_disable
,
445 .atomic_check
= rockchip_lvds_encoder_atomic_check
,
448 static int rk3288_lvds_probe(struct platform_device
*pdev
,
449 struct rockchip_lvds
*lvds
)
453 lvds
->regs
= devm_platform_ioremap_resource(pdev
, 0);
454 if (IS_ERR(lvds
->regs
))
455 return PTR_ERR(lvds
->regs
);
457 lvds
->pclk
= devm_clk_get(lvds
->dev
, "pclk_lvds");
458 if (IS_ERR(lvds
->pclk
)) {
459 DRM_DEV_ERROR(lvds
->dev
, "could not get pclk_lvds\n");
460 return PTR_ERR(lvds
->pclk
);
463 lvds
->pins
= devm_kzalloc(lvds
->dev
, sizeof(*lvds
->pins
),
468 lvds
->pins
->p
= devm_pinctrl_get(lvds
->dev
);
469 if (IS_ERR(lvds
->pins
->p
)) {
470 DRM_DEV_ERROR(lvds
->dev
, "no pinctrl handle\n");
471 devm_kfree(lvds
->dev
, lvds
->pins
);
474 lvds
->pins
->default_state
=
475 pinctrl_lookup_state(lvds
->pins
->p
, "lcdc");
476 if (IS_ERR(lvds
->pins
->default_state
)) {
477 DRM_DEV_ERROR(lvds
->dev
, "no default pinctrl state\n");
478 devm_kfree(lvds
->dev
, lvds
->pins
);
483 ret
= clk_prepare(lvds
->pclk
);
485 DRM_DEV_ERROR(lvds
->dev
, "failed to prepare pclk_lvds\n");
492 static int px30_lvds_probe(struct platform_device
*pdev
,
493 struct rockchip_lvds
*lvds
)
498 ret
= regmap_update_bits(lvds
->grf
, PX30_LVDS_GRF_PD_VO_CON1
,
500 PX30_LVDS_MSBSEL(1));
505 lvds
->dphy
= devm_phy_get(&pdev
->dev
, "dphy");
506 if (IS_ERR(lvds
->dphy
))
507 return PTR_ERR(lvds
->dphy
);
509 ret
= phy_init(lvds
->dphy
);
513 ret
= phy_set_mode(lvds
->dphy
, PHY_MODE_LVDS
);
517 return phy_power_on(lvds
->dphy
);
520 static const struct rockchip_lvds_soc_data rk3288_lvds_data
= {
521 .probe
= rk3288_lvds_probe
,
522 .helper_funcs
= &rk3288_lvds_encoder_helper_funcs
,
525 static const struct rockchip_lvds_soc_data px30_lvds_data
= {
526 .probe
= px30_lvds_probe
,
527 .helper_funcs
= &px30_lvds_encoder_helper_funcs
,
530 static const struct of_device_id rockchip_lvds_dt_ids
[] = {
532 .compatible
= "rockchip,rk3288-lvds",
533 .data
= &rk3288_lvds_data
536 .compatible
= "rockchip,px30-lvds",
537 .data
= &px30_lvds_data
541 MODULE_DEVICE_TABLE(of
, rockchip_lvds_dt_ids
);
543 static int rockchip_lvds_bind(struct device
*dev
, struct device
*master
,
546 struct rockchip_lvds
*lvds
= dev_get_drvdata(dev
);
547 struct drm_device
*drm_dev
= data
;
548 struct drm_encoder
*encoder
;
549 struct drm_connector
*connector
;
550 struct device_node
*remote
= NULL
;
551 struct device_node
*port
, *endpoint
;
552 int ret
= 0, child_count
= 0;
556 lvds
->drm_dev
= drm_dev
;
557 port
= of_graph_get_port_by_id(dev
->of_node
, 1);
560 "can't found port point, please init lvds panel port!\n");
563 for_each_child_of_node(port
, endpoint
) {
565 of_property_read_u32(endpoint
, "reg", &endpoint_id
);
566 ret
= drm_of_find_panel_or_bridge(dev
->of_node
, 1, endpoint_id
,
567 &lvds
->panel
, &lvds
->bridge
);
569 of_node_put(endpoint
);
574 DRM_DEV_ERROR(dev
, "lvds port does not have any children\n");
578 dev_err_probe(dev
, ret
, "failed to find panel and bridge node\n");
582 remote
= lvds
->panel
->dev
->of_node
;
584 remote
= lvds
->bridge
->of_node
;
585 if (of_property_read_string(dev
->of_node
, "rockchip,output", &name
))
586 /* default set it as output rgb */
587 lvds
->output
= DISPLAY_OUTPUT_RGB
;
589 lvds
->output
= rockchip_lvds_name_to_output(name
);
591 if (lvds
->output
< 0) {
592 DRM_DEV_ERROR(dev
, "invalid output type [%s]\n", name
);
597 if (of_property_read_string(remote
, "data-mapping", &name
))
598 /* default set it as format vesa 18 */
599 lvds
->format
= LVDS_VESA_18
;
601 lvds
->format
= rockchip_lvds_name_to_format(name
);
603 if (lvds
->format
< 0) {
604 DRM_DEV_ERROR(dev
, "invalid data-mapping format [%s]\n", name
);
609 encoder
= &lvds
->encoder
.encoder
;
610 encoder
->possible_crtcs
= drm_of_find_possible_crtcs(drm_dev
,
613 ret
= drm_simple_encoder_init(drm_dev
, encoder
, DRM_MODE_ENCODER_LVDS
);
615 DRM_DEV_ERROR(drm_dev
->dev
,
616 "failed to initialize encoder: %d\n", ret
);
620 drm_encoder_helper_add(encoder
, lvds
->soc_data
->helper_funcs
);
621 connector
= &lvds
->connector
;
624 connector
->dpms
= DRM_MODE_DPMS_OFF
;
625 ret
= drm_connector_init(drm_dev
, connector
,
626 &rockchip_lvds_connector_funcs
,
627 DRM_MODE_CONNECTOR_LVDS
);
629 DRM_DEV_ERROR(drm_dev
->dev
,
630 "failed to initialize connector: %d\n", ret
);
631 goto err_free_encoder
;
634 drm_connector_helper_add(connector
,
635 &rockchip_lvds_connector_helper_funcs
);
637 ret
= drm_bridge_attach(encoder
, lvds
->bridge
, NULL
,
638 DRM_BRIDGE_ATTACH_NO_CONNECTOR
);
640 goto err_free_encoder
;
642 connector
= drm_bridge_connector_init(lvds
->drm_dev
, encoder
);
643 if (IS_ERR(connector
)) {
644 DRM_DEV_ERROR(drm_dev
->dev
,
645 "failed to initialize bridge connector: %pe\n",
647 ret
= PTR_ERR(connector
);
648 goto err_free_encoder
;
652 ret
= drm_connector_attach_encoder(connector
, encoder
);
654 DRM_DEV_ERROR(drm_dev
->dev
,
655 "failed to attach encoder: %d\n", ret
);
656 goto err_free_connector
;
659 pm_runtime_enable(dev
);
666 drm_connector_cleanup(connector
);
668 drm_encoder_cleanup(encoder
);
677 static void rockchip_lvds_unbind(struct device
*dev
, struct device
*master
,
680 struct rockchip_lvds
*lvds
= dev_get_drvdata(dev
);
681 const struct drm_encoder_helper_funcs
*encoder_funcs
;
683 encoder_funcs
= lvds
->soc_data
->helper_funcs
;
684 encoder_funcs
->disable(&lvds
->encoder
.encoder
);
685 pm_runtime_disable(dev
);
686 drm_connector_cleanup(&lvds
->connector
);
687 drm_encoder_cleanup(&lvds
->encoder
.encoder
);
690 static const struct component_ops rockchip_lvds_component_ops
= {
691 .bind
= rockchip_lvds_bind
,
692 .unbind
= rockchip_lvds_unbind
,
695 static int rockchip_lvds_probe(struct platform_device
*pdev
)
697 struct device
*dev
= &pdev
->dev
;
698 struct rockchip_lvds
*lvds
;
699 const struct of_device_id
*match
;
705 lvds
= devm_kzalloc(&pdev
->dev
, sizeof(*lvds
), GFP_KERNEL
);
710 match
= of_match_node(rockchip_lvds_dt_ids
, dev
->of_node
);
713 lvds
->soc_data
= match
->data
;
715 lvds
->grf
= syscon_regmap_lookup_by_phandle(dev
->of_node
,
717 if (IS_ERR(lvds
->grf
)) {
718 DRM_DEV_ERROR(dev
, "missing rockchip,grf property\n");
719 return PTR_ERR(lvds
->grf
);
722 ret
= lvds
->soc_data
->probe(pdev
, lvds
);
724 DRM_DEV_ERROR(dev
, "Platform initialization failed\n");
728 dev_set_drvdata(dev
, lvds
);
730 ret
= component_add(&pdev
->dev
, &rockchip_lvds_component_ops
);
732 DRM_DEV_ERROR(dev
, "failed to add component\n");
733 clk_unprepare(lvds
->pclk
);
739 static void rockchip_lvds_remove(struct platform_device
*pdev
)
741 struct rockchip_lvds
*lvds
= platform_get_drvdata(pdev
);
743 component_del(&pdev
->dev
, &rockchip_lvds_component_ops
);
744 clk_unprepare(lvds
->pclk
);
747 struct platform_driver rockchip_lvds_driver
= {
748 .probe
= rockchip_lvds_probe
,
749 .remove
= rockchip_lvds_remove
,
751 .name
= "rockchip-lvds",
752 .of_match_table
= rockchip_lvds_dt_ids
,