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_dp_helper.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_drm_vop.h"
30 #include "rockchip_lvds.h"
32 #define DISPLAY_OUTPUT_RGB 0
33 #define DISPLAY_OUTPUT_LVDS 1
34 #define DISPLAY_OUTPUT_DUAL_LVDS 2
38 #define connector_to_lvds(c) \
39 container_of(c, struct rockchip_lvds, connector)
41 #define encoder_to_lvds(c) \
42 container_of(c, struct rockchip_lvds, encoder)
45 * struct rockchip_lvds_soc_data - rockchip lvds Soc private data
46 * @probe: LVDS platform probe function
47 * @helper_funcs: LVDS connector helper functions
49 struct rockchip_lvds_soc_data
{
50 int (*probe
)(struct platform_device
*pdev
, struct rockchip_lvds
*lvds
);
51 const struct drm_encoder_helper_funcs
*helper_funcs
;
54 struct rockchip_lvds
{
60 const struct rockchip_lvds_soc_data
*soc_data
;
61 int output
; /* rgb lvds or dual lvds output */
62 int format
; /* vesa or jeida format */
63 struct drm_device
*drm_dev
;
64 struct drm_panel
*panel
;
65 struct drm_bridge
*bridge
;
66 struct drm_connector connector
;
67 struct drm_encoder encoder
;
68 struct dev_pin_info
*pins
;
71 static inline void rk3288_writel(struct rockchip_lvds
*lvds
, u32 offset
,
74 writel_relaxed(val
, lvds
->regs
+ offset
);
75 if (lvds
->output
== DISPLAY_OUTPUT_LVDS
)
77 writel_relaxed(val
, lvds
->regs
+ offset
+ RK3288_LVDS_CH1_OFFSET
);
80 static inline int rockchip_lvds_name_to_format(const char *s
)
82 if (strncmp(s
, "jeida-18", 8) == 0)
84 else if (strncmp(s
, "jeida-24", 8) == 0)
86 else if (strncmp(s
, "vesa-24", 7) == 0)
92 static inline int rockchip_lvds_name_to_output(const char *s
)
94 if (strncmp(s
, "rgb", 3) == 0)
95 return DISPLAY_OUTPUT_RGB
;
96 else if (strncmp(s
, "lvds", 4) == 0)
97 return DISPLAY_OUTPUT_LVDS
;
98 else if (strncmp(s
, "duallvds", 8) == 0)
99 return DISPLAY_OUTPUT_DUAL_LVDS
;
104 static const struct drm_connector_funcs rockchip_lvds_connector_funcs
= {
105 .fill_modes
= drm_helper_probe_single_connector_modes
,
106 .destroy
= drm_connector_cleanup
,
107 .reset
= drm_atomic_helper_connector_reset
,
108 .atomic_duplicate_state
= drm_atomic_helper_connector_duplicate_state
,
109 .atomic_destroy_state
= drm_atomic_helper_connector_destroy_state
,
112 static int rockchip_lvds_connector_get_modes(struct drm_connector
*connector
)
114 struct rockchip_lvds
*lvds
= connector_to_lvds(connector
);
115 struct drm_panel
*panel
= lvds
->panel
;
117 return drm_panel_get_modes(panel
, connector
);
121 struct drm_connector_helper_funcs rockchip_lvds_connector_helper_funcs
= {
122 .get_modes
= rockchip_lvds_connector_get_modes
,
126 rockchip_lvds_encoder_atomic_check(struct drm_encoder
*encoder
,
127 struct drm_crtc_state
*crtc_state
,
128 struct drm_connector_state
*conn_state
)
130 struct rockchip_crtc_state
*s
= to_rockchip_crtc_state(crtc_state
);
132 s
->output_mode
= ROCKCHIP_OUT_MODE_P888
;
133 s
->output_type
= DRM_MODE_CONNECTOR_LVDS
;
138 static int rk3288_lvds_poweron(struct rockchip_lvds
*lvds
)
143 ret
= clk_enable(lvds
->pclk
);
145 DRM_DEV_ERROR(lvds
->dev
, "failed to enable lvds pclk %d\n", ret
);
148 ret
= pm_runtime_get_sync(lvds
->dev
);
150 DRM_DEV_ERROR(lvds
->dev
, "failed to get pm runtime: %d\n", ret
);
151 clk_disable(lvds
->pclk
);
154 val
= RK3288_LVDS_CH0_REG0_LANE4_EN
| RK3288_LVDS_CH0_REG0_LANE3_EN
|
155 RK3288_LVDS_CH0_REG0_LANE2_EN
| RK3288_LVDS_CH0_REG0_LANE1_EN
|
156 RK3288_LVDS_CH0_REG0_LANE0_EN
;
157 if (lvds
->output
== DISPLAY_OUTPUT_RGB
) {
158 val
|= RK3288_LVDS_CH0_REG0_TTL_EN
|
159 RK3288_LVDS_CH0_REG0_LANECK_EN
;
160 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG0
, val
);
161 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG2
,
162 RK3288_LVDS_PLL_FBDIV_REG2(0x46));
163 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG4
,
164 RK3288_LVDS_CH0_REG4_LANECK_TTL_MODE
|
165 RK3288_LVDS_CH0_REG4_LANE4_TTL_MODE
|
166 RK3288_LVDS_CH0_REG4_LANE3_TTL_MODE
|
167 RK3288_LVDS_CH0_REG4_LANE2_TTL_MODE
|
168 RK3288_LVDS_CH0_REG4_LANE1_TTL_MODE
|
169 RK3288_LVDS_CH0_REG4_LANE0_TTL_MODE
);
170 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG5
,
171 RK3288_LVDS_CH0_REG5_LANECK_TTL_DATA
|
172 RK3288_LVDS_CH0_REG5_LANE4_TTL_DATA
|
173 RK3288_LVDS_CH0_REG5_LANE3_TTL_DATA
|
174 RK3288_LVDS_CH0_REG5_LANE2_TTL_DATA
|
175 RK3288_LVDS_CH0_REG5_LANE1_TTL_DATA
|
176 RK3288_LVDS_CH0_REG5_LANE0_TTL_DATA
);
178 val
|= RK3288_LVDS_CH0_REG0_LVDS_EN
|
179 RK3288_LVDS_CH0_REG0_LANECK_EN
;
180 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG0
, val
);
181 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG1
,
182 RK3288_LVDS_CH0_REG1_LANECK_BIAS
|
183 RK3288_LVDS_CH0_REG1_LANE4_BIAS
|
184 RK3288_LVDS_CH0_REG1_LANE3_BIAS
|
185 RK3288_LVDS_CH0_REG1_LANE2_BIAS
|
186 RK3288_LVDS_CH0_REG1_LANE1_BIAS
|
187 RK3288_LVDS_CH0_REG1_LANE0_BIAS
);
188 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG2
,
189 RK3288_LVDS_CH0_REG2_RESERVE_ON
|
190 RK3288_LVDS_CH0_REG2_LANECK_LVDS_MODE
|
191 RK3288_LVDS_CH0_REG2_LANE4_LVDS_MODE
|
192 RK3288_LVDS_CH0_REG2_LANE3_LVDS_MODE
|
193 RK3288_LVDS_CH0_REG2_LANE2_LVDS_MODE
|
194 RK3288_LVDS_CH0_REG2_LANE1_LVDS_MODE
|
195 RK3288_LVDS_CH0_REG2_LANE0_LVDS_MODE
|
196 RK3288_LVDS_PLL_FBDIV_REG2(0x46));
197 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG4
, 0x00);
198 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG5
, 0x00);
200 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG3
,
201 RK3288_LVDS_PLL_FBDIV_REG3(0x46));
202 rk3288_writel(lvds
, RK3288_LVDS_CH0_REGD
,
203 RK3288_LVDS_PLL_PREDIV_REGD(0x0a));
204 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG20
,
205 RK3288_LVDS_CH0_REG20_LSB
);
207 rk3288_writel(lvds
, RK3288_LVDS_CFG_REGC
,
208 RK3288_LVDS_CFG_REGC_PLL_ENABLE
);
209 rk3288_writel(lvds
, RK3288_LVDS_CFG_REG21
,
210 RK3288_LVDS_CFG_REG21_TX_ENABLE
);
215 static void rk3288_lvds_poweroff(struct rockchip_lvds
*lvds
)
220 rk3288_writel(lvds
, RK3288_LVDS_CFG_REG21
,
221 RK3288_LVDS_CFG_REG21_TX_ENABLE
);
222 rk3288_writel(lvds
, RK3288_LVDS_CFG_REGC
,
223 RK3288_LVDS_CFG_REGC_PLL_ENABLE
);
224 val
= LVDS_DUAL
| LVDS_TTL_EN
| LVDS_CH0_EN
| LVDS_CH1_EN
| LVDS_PWRDN
;
226 ret
= regmap_write(lvds
->grf
, RK3288_LVDS_GRF_SOC_CON7
, val
);
228 DRM_DEV_ERROR(lvds
->dev
, "Could not write to GRF: %d\n", ret
);
230 pm_runtime_put(lvds
->dev
);
231 clk_disable(lvds
->pclk
);
234 static int rk3288_lvds_grf_config(struct drm_encoder
*encoder
,
235 struct drm_display_mode
*mode
)
237 struct rockchip_lvds
*lvds
= encoder_to_lvds(encoder
);
238 u8 pin_hsync
= (mode
->flags
& DRM_MODE_FLAG_PHSYNC
) ? 1 : 0;
239 u8 pin_dclk
= (mode
->flags
& DRM_MODE_FLAG_PCSYNC
) ? 1 : 0;
243 /* iomux to LCD data/sync mode */
244 if (lvds
->output
== DISPLAY_OUTPUT_RGB
)
245 if (lvds
->pins
&& !IS_ERR(lvds
->pins
->default_state
))
246 pinctrl_select_state(lvds
->pins
->p
,
247 lvds
->pins
->default_state
);
248 val
= lvds
->format
| LVDS_CH0_EN
;
249 if (lvds
->output
== DISPLAY_OUTPUT_RGB
)
250 val
|= LVDS_TTL_EN
| LVDS_CH1_EN
;
251 else if (lvds
->output
== DISPLAY_OUTPUT_DUAL_LVDS
)
252 val
|= LVDS_DUAL
| LVDS_CH1_EN
;
254 if ((mode
->htotal
- mode
->hsync_start
) & 0x01)
255 val
|= LVDS_START_PHASE_RST_1
;
257 val
|= (pin_dclk
<< 8) | (pin_hsync
<< 9);
258 val
|= (0xffff << 16);
259 ret
= regmap_write(lvds
->grf
, RK3288_LVDS_GRF_SOC_CON7
, val
);
261 DRM_DEV_ERROR(lvds
->dev
, "Could not write to GRF: %d\n", ret
);
266 static int rk3288_lvds_set_vop_source(struct rockchip_lvds
*lvds
,
267 struct drm_encoder
*encoder
)
272 ret
= drm_of_encoder_active_endpoint_id(lvds
->dev
->of_node
, encoder
);
276 val
= RK3288_LVDS_SOC_CON6_SEL_VOP_LIT
<< 16;
278 val
|= RK3288_LVDS_SOC_CON6_SEL_VOP_LIT
;
280 ret
= regmap_write(lvds
->grf
, RK3288_LVDS_GRF_SOC_CON6
, val
);
287 static void rk3288_lvds_encoder_enable(struct drm_encoder
*encoder
)
289 struct rockchip_lvds
*lvds
= encoder_to_lvds(encoder
);
290 struct drm_display_mode
*mode
= &encoder
->crtc
->state
->adjusted_mode
;
293 drm_panel_prepare(lvds
->panel
);
295 ret
= rk3288_lvds_poweron(lvds
);
297 DRM_DEV_ERROR(lvds
->dev
, "failed to power on LVDS: %d\n", ret
);
298 drm_panel_unprepare(lvds
->panel
);
302 ret
= rk3288_lvds_grf_config(encoder
, mode
);
304 DRM_DEV_ERROR(lvds
->dev
, "failed to configure LVDS: %d\n", ret
);
305 drm_panel_unprepare(lvds
->panel
);
309 ret
= rk3288_lvds_set_vop_source(lvds
, encoder
);
311 DRM_DEV_ERROR(lvds
->dev
, "failed to set VOP source: %d\n", ret
);
312 drm_panel_unprepare(lvds
->panel
);
316 drm_panel_enable(lvds
->panel
);
319 static void rk3288_lvds_encoder_disable(struct drm_encoder
*encoder
)
321 struct rockchip_lvds
*lvds
= encoder_to_lvds(encoder
);
323 drm_panel_disable(lvds
->panel
);
324 rk3288_lvds_poweroff(lvds
);
325 drm_panel_unprepare(lvds
->panel
);
328 static int px30_lvds_poweron(struct rockchip_lvds
*lvds
)
332 ret
= pm_runtime_get_sync(lvds
->dev
);
334 DRM_DEV_ERROR(lvds
->dev
, "failed to get pm runtime: %d\n", ret
);
338 /* Enable LVDS mode */
339 return regmap_update_bits(lvds
->grf
, PX30_LVDS_GRF_PD_VO_CON1
,
340 PX30_LVDS_MODE_EN(1) | PX30_LVDS_P2S_EN(1),
341 PX30_LVDS_MODE_EN(1) | PX30_LVDS_P2S_EN(1));
344 static void px30_lvds_poweroff(struct rockchip_lvds
*lvds
)
346 regmap_update_bits(lvds
->grf
, PX30_LVDS_GRF_PD_VO_CON1
,
347 PX30_LVDS_MODE_EN(1) | PX30_LVDS_P2S_EN(1),
348 PX30_LVDS_MODE_EN(0) | PX30_LVDS_P2S_EN(0));
350 pm_runtime_put(lvds
->dev
);
353 static int px30_lvds_grf_config(struct drm_encoder
*encoder
,
354 struct drm_display_mode
*mode
)
356 struct rockchip_lvds
*lvds
= encoder_to_lvds(encoder
);
358 if (lvds
->output
!= DISPLAY_OUTPUT_LVDS
) {
359 DRM_DEV_ERROR(lvds
->dev
, "Unsupported display output %d\n",
365 return regmap_update_bits(lvds
->grf
, PX30_LVDS_GRF_PD_VO_CON1
,
366 PX30_LVDS_FORMAT(lvds
->format
),
367 PX30_LVDS_FORMAT(lvds
->format
));
370 static int px30_lvds_set_vop_source(struct rockchip_lvds
*lvds
,
371 struct drm_encoder
*encoder
)
375 vop
= drm_of_encoder_active_endpoint_id(lvds
->dev
->of_node
, encoder
);
379 return regmap_update_bits(lvds
->grf
, PX30_LVDS_GRF_PD_VO_CON1
,
380 PX30_LVDS_VOP_SEL(1),
381 PX30_LVDS_VOP_SEL(vop
));
384 static void px30_lvds_encoder_enable(struct drm_encoder
*encoder
)
386 struct rockchip_lvds
*lvds
= encoder_to_lvds(encoder
);
387 struct drm_display_mode
*mode
= &encoder
->crtc
->state
->adjusted_mode
;
390 drm_panel_prepare(lvds
->panel
);
392 ret
= px30_lvds_poweron(lvds
);
394 DRM_DEV_ERROR(lvds
->dev
, "failed to power on LVDS: %d\n", ret
);
395 drm_panel_unprepare(lvds
->panel
);
399 ret
= px30_lvds_grf_config(encoder
, mode
);
401 DRM_DEV_ERROR(lvds
->dev
, "failed to configure LVDS: %d\n", ret
);
402 drm_panel_unprepare(lvds
->panel
);
406 ret
= px30_lvds_set_vop_source(lvds
, encoder
);
408 DRM_DEV_ERROR(lvds
->dev
, "failed to set VOP source: %d\n", ret
);
409 drm_panel_unprepare(lvds
->panel
);
413 drm_panel_enable(lvds
->panel
);
416 static void px30_lvds_encoder_disable(struct drm_encoder
*encoder
)
418 struct rockchip_lvds
*lvds
= encoder_to_lvds(encoder
);
420 drm_panel_disable(lvds
->panel
);
421 px30_lvds_poweroff(lvds
);
422 drm_panel_unprepare(lvds
->panel
);
426 struct drm_encoder_helper_funcs rk3288_lvds_encoder_helper_funcs
= {
427 .enable
= rk3288_lvds_encoder_enable
,
428 .disable
= rk3288_lvds_encoder_disable
,
429 .atomic_check
= rockchip_lvds_encoder_atomic_check
,
433 struct drm_encoder_helper_funcs px30_lvds_encoder_helper_funcs
= {
434 .enable
= px30_lvds_encoder_enable
,
435 .disable
= px30_lvds_encoder_disable
,
436 .atomic_check
= rockchip_lvds_encoder_atomic_check
,
439 static int rk3288_lvds_probe(struct platform_device
*pdev
,
440 struct rockchip_lvds
*lvds
)
442 struct resource
*res
;
445 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
446 lvds
->regs
= devm_ioremap_resource(lvds
->dev
, res
);
447 if (IS_ERR(lvds
->regs
))
448 return PTR_ERR(lvds
->regs
);
450 lvds
->pclk
= devm_clk_get(lvds
->dev
, "pclk_lvds");
451 if (IS_ERR(lvds
->pclk
)) {
452 DRM_DEV_ERROR(lvds
->dev
, "could not get pclk_lvds\n");
453 return PTR_ERR(lvds
->pclk
);
456 lvds
->pins
= devm_kzalloc(lvds
->dev
, sizeof(*lvds
->pins
),
461 lvds
->pins
->p
= devm_pinctrl_get(lvds
->dev
);
462 if (IS_ERR(lvds
->pins
->p
)) {
463 DRM_DEV_ERROR(lvds
->dev
, "no pinctrl handle\n");
464 devm_kfree(lvds
->dev
, lvds
->pins
);
467 lvds
->pins
->default_state
=
468 pinctrl_lookup_state(lvds
->pins
->p
, "lcdc");
469 if (IS_ERR(lvds
->pins
->default_state
)) {
470 DRM_DEV_ERROR(lvds
->dev
, "no default pinctrl state\n");
471 devm_kfree(lvds
->dev
, lvds
->pins
);
476 ret
= clk_prepare(lvds
->pclk
);
478 DRM_DEV_ERROR(lvds
->dev
, "failed to prepare pclk_lvds\n");
485 static int px30_lvds_probe(struct platform_device
*pdev
,
486 struct rockchip_lvds
*lvds
)
491 ret
= regmap_update_bits(lvds
->grf
, PX30_LVDS_GRF_PD_VO_CON1
,
493 PX30_LVDS_MSBSEL(1));
498 lvds
->dphy
= devm_phy_get(&pdev
->dev
, "dphy");
499 if (IS_ERR(lvds
->dphy
))
500 return PTR_ERR(lvds
->dphy
);
502 phy_init(lvds
->dphy
);
506 phy_set_mode(lvds
->dphy
, PHY_MODE_LVDS
);
510 return phy_power_on(lvds
->dphy
);
513 static const struct rockchip_lvds_soc_data rk3288_lvds_data
= {
514 .probe
= rk3288_lvds_probe
,
515 .helper_funcs
= &rk3288_lvds_encoder_helper_funcs
,
518 static const struct rockchip_lvds_soc_data px30_lvds_data
= {
519 .probe
= px30_lvds_probe
,
520 .helper_funcs
= &px30_lvds_encoder_helper_funcs
,
523 static const struct of_device_id rockchip_lvds_dt_ids
[] = {
525 .compatible
= "rockchip,rk3288-lvds",
526 .data
= &rk3288_lvds_data
529 .compatible
= "rockchip,px30-lvds",
530 .data
= &px30_lvds_data
534 MODULE_DEVICE_TABLE(of
, rockchip_lvds_dt_ids
);
536 static int rockchip_lvds_bind(struct device
*dev
, struct device
*master
,
539 struct rockchip_lvds
*lvds
= dev_get_drvdata(dev
);
540 struct drm_device
*drm_dev
= data
;
541 struct drm_encoder
*encoder
;
542 struct drm_connector
*connector
;
543 struct device_node
*remote
= NULL
;
544 struct device_node
*port
, *endpoint
;
545 int ret
= 0, child_count
= 0;
549 lvds
->drm_dev
= drm_dev
;
550 port
= of_graph_get_port_by_id(dev
->of_node
, 1);
553 "can't found port point, please init lvds panel port!\n");
556 for_each_child_of_node(port
, endpoint
) {
558 of_property_read_u32(endpoint
, "reg", &endpoint_id
);
559 ret
= drm_of_find_panel_or_bridge(dev
->of_node
, 1, endpoint_id
,
560 &lvds
->panel
, &lvds
->bridge
);
562 of_node_put(endpoint
);
567 DRM_DEV_ERROR(dev
, "lvds port does not have any children\n");
571 DRM_DEV_ERROR(dev
, "failed to find panel and bridge node\n");
576 remote
= lvds
->panel
->dev
->of_node
;
578 remote
= lvds
->bridge
->of_node
;
579 if (of_property_read_string(dev
->of_node
, "rockchip,output", &name
))
580 /* default set it as output rgb */
581 lvds
->output
= DISPLAY_OUTPUT_RGB
;
583 lvds
->output
= rockchip_lvds_name_to_output(name
);
585 if (lvds
->output
< 0) {
586 DRM_DEV_ERROR(dev
, "invalid output type [%s]\n", name
);
591 if (of_property_read_string(remote
, "data-mapping", &name
))
592 /* default set it as format vesa 18 */
593 lvds
->format
= LVDS_VESA_18
;
595 lvds
->format
= rockchip_lvds_name_to_format(name
);
597 if (lvds
->format
< 0) {
598 DRM_DEV_ERROR(dev
, "invalid data-mapping format [%s]\n", name
);
603 encoder
= &lvds
->encoder
;
604 encoder
->possible_crtcs
= drm_of_find_possible_crtcs(drm_dev
,
607 ret
= drm_simple_encoder_init(drm_dev
, encoder
, DRM_MODE_ENCODER_LVDS
);
609 DRM_DEV_ERROR(drm_dev
->dev
,
610 "failed to initialize encoder: %d\n", ret
);
614 drm_encoder_helper_add(encoder
, lvds
->soc_data
->helper_funcs
);
617 connector
= &lvds
->connector
;
618 connector
->dpms
= DRM_MODE_DPMS_OFF
;
619 ret
= drm_connector_init(drm_dev
, connector
,
620 &rockchip_lvds_connector_funcs
,
621 DRM_MODE_CONNECTOR_LVDS
);
623 DRM_DEV_ERROR(drm_dev
->dev
,
624 "failed to initialize connector: %d\n", ret
);
625 goto err_free_encoder
;
628 drm_connector_helper_add(connector
,
629 &rockchip_lvds_connector_helper_funcs
);
631 ret
= drm_connector_attach_encoder(connector
, encoder
);
633 DRM_DEV_ERROR(drm_dev
->dev
,
634 "failed to attach encoder: %d\n", ret
);
635 goto err_free_connector
;
638 ret
= drm_bridge_attach(encoder
, lvds
->bridge
, NULL
, 0);
640 DRM_DEV_ERROR(drm_dev
->dev
,
641 "failed to attach bridge: %d\n", ret
);
642 goto err_free_encoder
;
646 pm_runtime_enable(dev
);
653 drm_connector_cleanup(connector
);
655 drm_encoder_cleanup(encoder
);
664 static void rockchip_lvds_unbind(struct device
*dev
, struct device
*master
,
667 struct rockchip_lvds
*lvds
= dev_get_drvdata(dev
);
668 const struct drm_encoder_helper_funcs
*encoder_funcs
;
670 encoder_funcs
= lvds
->soc_data
->helper_funcs
;
671 encoder_funcs
->disable(&lvds
->encoder
);
672 pm_runtime_disable(dev
);
673 drm_connector_cleanup(&lvds
->connector
);
674 drm_encoder_cleanup(&lvds
->encoder
);
677 static const struct component_ops rockchip_lvds_component_ops
= {
678 .bind
= rockchip_lvds_bind
,
679 .unbind
= rockchip_lvds_unbind
,
682 static int rockchip_lvds_probe(struct platform_device
*pdev
)
684 struct device
*dev
= &pdev
->dev
;
685 struct rockchip_lvds
*lvds
;
686 const struct of_device_id
*match
;
692 lvds
= devm_kzalloc(&pdev
->dev
, sizeof(*lvds
), GFP_KERNEL
);
697 match
= of_match_node(rockchip_lvds_dt_ids
, dev
->of_node
);
700 lvds
->soc_data
= match
->data
;
702 lvds
->grf
= syscon_regmap_lookup_by_phandle(dev
->of_node
,
704 if (IS_ERR(lvds
->grf
)) {
705 DRM_DEV_ERROR(dev
, "missing rockchip,grf property\n");
706 return PTR_ERR(lvds
->grf
);
709 ret
= lvds
->soc_data
->probe(pdev
, lvds
);
711 DRM_DEV_ERROR(dev
, "Platform initialization failed\n");
715 dev_set_drvdata(dev
, lvds
);
717 ret
= component_add(&pdev
->dev
, &rockchip_lvds_component_ops
);
719 DRM_DEV_ERROR(dev
, "failed to add component\n");
720 clk_unprepare(lvds
->pclk
);
726 static int rockchip_lvds_remove(struct platform_device
*pdev
)
728 struct rockchip_lvds
*lvds
= dev_get_drvdata(&pdev
->dev
);
730 component_del(&pdev
->dev
, &rockchip_lvds_component_ops
);
731 clk_unprepare(lvds
->pclk
);
736 struct platform_driver rockchip_lvds_driver
= {
737 .probe
= rockchip_lvds_probe
,
738 .remove
= rockchip_lvds_remove
,
740 .name
= "rockchip-lvds",
741 .of_match_table
= of_match_ptr(rockchip_lvds_dt_ids
),