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>
19 #include <drm/drm_atomic_helper.h>
20 #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>
27 #include "rockchip_drm_drv.h"
28 #include "rockchip_drm_vop.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
37 #define connector_to_lvds(c) \
38 container_of(c, struct rockchip_lvds, connector)
40 #define encoder_to_lvds(c) \
41 container_of(c, struct rockchip_lvds, encoder)
44 * rockchip_lvds_soc_data - rockchip lvds Soc private data
45 * @probe: LVDS platform probe function
46 * @helper_funcs: LVDS connector helper functions
48 struct rockchip_lvds_soc_data
{
49 int (*probe
)(struct platform_device
*pdev
, struct rockchip_lvds
*lvds
);
50 const struct drm_encoder_helper_funcs
*helper_funcs
;
53 struct rockchip_lvds
{
59 const struct rockchip_lvds_soc_data
*soc_data
;
60 int output
; /* rgb lvds or dual lvds output */
61 int format
; /* vesa or jeida format */
62 struct drm_device
*drm_dev
;
63 struct drm_panel
*panel
;
64 struct drm_bridge
*bridge
;
65 struct drm_connector connector
;
66 struct drm_encoder encoder
;
67 struct dev_pin_info
*pins
;
70 static inline void rk3288_writel(struct rockchip_lvds
*lvds
, u32 offset
,
73 writel_relaxed(val
, lvds
->regs
+ offset
);
74 if (lvds
->output
== DISPLAY_OUTPUT_LVDS
)
76 writel_relaxed(val
, lvds
->regs
+ offset
+ RK3288_LVDS_CH1_OFFSET
);
79 static inline int rockchip_lvds_name_to_format(const char *s
)
81 if (strncmp(s
, "jeida-18", 8) == 0)
83 else if (strncmp(s
, "jeida-24", 8) == 0)
85 else if (strncmp(s
, "vesa-24", 7) == 0)
91 static inline int rockchip_lvds_name_to_output(const char *s
)
93 if (strncmp(s
, "rgb", 3) == 0)
94 return DISPLAY_OUTPUT_RGB
;
95 else if (strncmp(s
, "lvds", 4) == 0)
96 return DISPLAY_OUTPUT_LVDS
;
97 else if (strncmp(s
, "duallvds", 8) == 0)
98 return DISPLAY_OUTPUT_DUAL_LVDS
;
103 static const struct drm_connector_funcs rockchip_lvds_connector_funcs
= {
104 .fill_modes
= drm_helper_probe_single_connector_modes
,
105 .destroy
= drm_connector_cleanup
,
106 .reset
= drm_atomic_helper_connector_reset
,
107 .atomic_duplicate_state
= drm_atomic_helper_connector_duplicate_state
,
108 .atomic_destroy_state
= drm_atomic_helper_connector_destroy_state
,
111 static int rockchip_lvds_connector_get_modes(struct drm_connector
*connector
)
113 struct rockchip_lvds
*lvds
= connector_to_lvds(connector
);
114 struct drm_panel
*panel
= lvds
->panel
;
116 return drm_panel_get_modes(panel
, connector
);
120 struct drm_connector_helper_funcs rockchip_lvds_connector_helper_funcs
= {
121 .get_modes
= rockchip_lvds_connector_get_modes
,
125 rockchip_lvds_encoder_atomic_check(struct drm_encoder
*encoder
,
126 struct drm_crtc_state
*crtc_state
,
127 struct drm_connector_state
*conn_state
)
129 struct rockchip_crtc_state
*s
= to_rockchip_crtc_state(crtc_state
);
131 s
->output_mode
= ROCKCHIP_OUT_MODE_P888
;
132 s
->output_type
= DRM_MODE_CONNECTOR_LVDS
;
137 static int rk3288_lvds_poweron(struct rockchip_lvds
*lvds
)
142 ret
= clk_enable(lvds
->pclk
);
144 DRM_DEV_ERROR(lvds
->dev
, "failed to enable lvds pclk %d\n", ret
);
147 ret
= pm_runtime_get_sync(lvds
->dev
);
149 DRM_DEV_ERROR(lvds
->dev
, "failed to get pm runtime: %d\n", ret
);
150 clk_disable(lvds
->pclk
);
153 val
= RK3288_LVDS_CH0_REG0_LANE4_EN
| RK3288_LVDS_CH0_REG0_LANE3_EN
|
154 RK3288_LVDS_CH0_REG0_LANE2_EN
| RK3288_LVDS_CH0_REG0_LANE1_EN
|
155 RK3288_LVDS_CH0_REG0_LANE0_EN
;
156 if (lvds
->output
== DISPLAY_OUTPUT_RGB
) {
157 val
|= RK3288_LVDS_CH0_REG0_TTL_EN
|
158 RK3288_LVDS_CH0_REG0_LANECK_EN
;
159 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG0
, val
);
160 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG2
,
161 RK3288_LVDS_PLL_FBDIV_REG2(0x46));
162 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG4
,
163 RK3288_LVDS_CH0_REG4_LANECK_TTL_MODE
|
164 RK3288_LVDS_CH0_REG4_LANE4_TTL_MODE
|
165 RK3288_LVDS_CH0_REG4_LANE3_TTL_MODE
|
166 RK3288_LVDS_CH0_REG4_LANE2_TTL_MODE
|
167 RK3288_LVDS_CH0_REG4_LANE1_TTL_MODE
|
168 RK3288_LVDS_CH0_REG4_LANE0_TTL_MODE
);
169 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG5
,
170 RK3288_LVDS_CH0_REG5_LANECK_TTL_DATA
|
171 RK3288_LVDS_CH0_REG5_LANE4_TTL_DATA
|
172 RK3288_LVDS_CH0_REG5_LANE3_TTL_DATA
|
173 RK3288_LVDS_CH0_REG5_LANE2_TTL_DATA
|
174 RK3288_LVDS_CH0_REG5_LANE1_TTL_DATA
|
175 RK3288_LVDS_CH0_REG5_LANE0_TTL_DATA
);
177 val
|= RK3288_LVDS_CH0_REG0_LVDS_EN
|
178 RK3288_LVDS_CH0_REG0_LANECK_EN
;
179 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG0
, val
);
180 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG1
,
181 RK3288_LVDS_CH0_REG1_LANECK_BIAS
|
182 RK3288_LVDS_CH0_REG1_LANE4_BIAS
|
183 RK3288_LVDS_CH0_REG1_LANE3_BIAS
|
184 RK3288_LVDS_CH0_REG1_LANE2_BIAS
|
185 RK3288_LVDS_CH0_REG1_LANE1_BIAS
|
186 RK3288_LVDS_CH0_REG1_LANE0_BIAS
);
187 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG2
,
188 RK3288_LVDS_CH0_REG2_RESERVE_ON
|
189 RK3288_LVDS_CH0_REG2_LANECK_LVDS_MODE
|
190 RK3288_LVDS_CH0_REG2_LANE4_LVDS_MODE
|
191 RK3288_LVDS_CH0_REG2_LANE3_LVDS_MODE
|
192 RK3288_LVDS_CH0_REG2_LANE2_LVDS_MODE
|
193 RK3288_LVDS_CH0_REG2_LANE1_LVDS_MODE
|
194 RK3288_LVDS_CH0_REG2_LANE0_LVDS_MODE
|
195 RK3288_LVDS_PLL_FBDIV_REG2(0x46));
196 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG4
, 0x00);
197 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG5
, 0x00);
199 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG3
,
200 RK3288_LVDS_PLL_FBDIV_REG3(0x46));
201 rk3288_writel(lvds
, RK3288_LVDS_CH0_REGD
,
202 RK3288_LVDS_PLL_PREDIV_REGD(0x0a));
203 rk3288_writel(lvds
, RK3288_LVDS_CH0_REG20
,
204 RK3288_LVDS_CH0_REG20_LSB
);
206 rk3288_writel(lvds
, RK3288_LVDS_CFG_REGC
,
207 RK3288_LVDS_CFG_REGC_PLL_ENABLE
);
208 rk3288_writel(lvds
, RK3288_LVDS_CFG_REG21
,
209 RK3288_LVDS_CFG_REG21_TX_ENABLE
);
214 static void rk3288_lvds_poweroff(struct rockchip_lvds
*lvds
)
219 rk3288_writel(lvds
, RK3288_LVDS_CFG_REG21
,
220 RK3288_LVDS_CFG_REG21_TX_ENABLE
);
221 rk3288_writel(lvds
, RK3288_LVDS_CFG_REGC
,
222 RK3288_LVDS_CFG_REGC_PLL_ENABLE
);
223 val
= LVDS_DUAL
| LVDS_TTL_EN
| LVDS_CH0_EN
| LVDS_CH1_EN
| LVDS_PWRDN
;
225 ret
= regmap_write(lvds
->grf
, RK3288_LVDS_GRF_SOC_CON7
, val
);
227 DRM_DEV_ERROR(lvds
->dev
, "Could not write to GRF: %d\n", ret
);
229 pm_runtime_put(lvds
->dev
);
230 clk_disable(lvds
->pclk
);
233 static int rk3288_lvds_grf_config(struct drm_encoder
*encoder
,
234 struct drm_display_mode
*mode
)
236 struct rockchip_lvds
*lvds
= encoder_to_lvds(encoder
);
237 u8 pin_hsync
= (mode
->flags
& DRM_MODE_FLAG_PHSYNC
) ? 1 : 0;
238 u8 pin_dclk
= (mode
->flags
& DRM_MODE_FLAG_PCSYNC
) ? 1 : 0;
242 /* iomux to LCD data/sync mode */
243 if (lvds
->output
== DISPLAY_OUTPUT_RGB
)
244 if (lvds
->pins
&& !IS_ERR(lvds
->pins
->default_state
))
245 pinctrl_select_state(lvds
->pins
->p
,
246 lvds
->pins
->default_state
);
247 val
= lvds
->format
| LVDS_CH0_EN
;
248 if (lvds
->output
== DISPLAY_OUTPUT_RGB
)
249 val
|= LVDS_TTL_EN
| LVDS_CH1_EN
;
250 else if (lvds
->output
== DISPLAY_OUTPUT_DUAL_LVDS
)
251 val
|= LVDS_DUAL
| LVDS_CH1_EN
;
253 if ((mode
->htotal
- mode
->hsync_start
) & 0x01)
254 val
|= LVDS_START_PHASE_RST_1
;
256 val
|= (pin_dclk
<< 8) | (pin_hsync
<< 9);
257 val
|= (0xffff << 16);
258 ret
= regmap_write(lvds
->grf
, RK3288_LVDS_GRF_SOC_CON7
, val
);
260 DRM_DEV_ERROR(lvds
->dev
, "Could not write to GRF: %d\n", ret
);
265 static int rk3288_lvds_set_vop_source(struct rockchip_lvds
*lvds
,
266 struct drm_encoder
*encoder
)
271 ret
= drm_of_encoder_active_endpoint_id(lvds
->dev
->of_node
, encoder
);
275 val
= RK3288_LVDS_SOC_CON6_SEL_VOP_LIT
<< 16;
277 val
|= RK3288_LVDS_SOC_CON6_SEL_VOP_LIT
;
279 ret
= regmap_write(lvds
->grf
, RK3288_LVDS_GRF_SOC_CON6
, val
);
286 static void rk3288_lvds_encoder_enable(struct drm_encoder
*encoder
)
288 struct rockchip_lvds
*lvds
= encoder_to_lvds(encoder
);
289 struct drm_display_mode
*mode
= &encoder
->crtc
->state
->adjusted_mode
;
292 drm_panel_prepare(lvds
->panel
);
294 ret
= rk3288_lvds_poweron(lvds
);
296 DRM_DEV_ERROR(lvds
->dev
, "failed to power on LVDS: %d\n", ret
);
297 drm_panel_unprepare(lvds
->panel
);
301 ret
= rk3288_lvds_grf_config(encoder
, mode
);
303 DRM_DEV_ERROR(lvds
->dev
, "failed to configure LVDS: %d\n", ret
);
304 drm_panel_unprepare(lvds
->panel
);
308 ret
= rk3288_lvds_set_vop_source(lvds
, encoder
);
310 DRM_DEV_ERROR(lvds
->dev
, "failed to set VOP source: %d\n", ret
);
311 drm_panel_unprepare(lvds
->panel
);
315 drm_panel_enable(lvds
->panel
);
318 static void rk3288_lvds_encoder_disable(struct drm_encoder
*encoder
)
320 struct rockchip_lvds
*lvds
= encoder_to_lvds(encoder
);
322 drm_panel_disable(lvds
->panel
);
323 rk3288_lvds_poweroff(lvds
);
324 drm_panel_unprepare(lvds
->panel
);
327 static int px30_lvds_poweron(struct rockchip_lvds
*lvds
)
331 ret
= pm_runtime_get_sync(lvds
->dev
);
333 DRM_DEV_ERROR(lvds
->dev
, "failed to get pm runtime: %d\n", ret
);
337 /* Enable LVDS mode */
338 return regmap_update_bits(lvds
->grf
, PX30_LVDS_GRF_PD_VO_CON1
,
339 PX30_LVDS_MODE_EN(1) | PX30_LVDS_P2S_EN(1),
340 PX30_LVDS_MODE_EN(1) | PX30_LVDS_P2S_EN(1));
343 static void px30_lvds_poweroff(struct rockchip_lvds
*lvds
)
345 regmap_update_bits(lvds
->grf
, PX30_LVDS_GRF_PD_VO_CON1
,
346 PX30_LVDS_MODE_EN(1) | PX30_LVDS_P2S_EN(1),
347 PX30_LVDS_MODE_EN(0) | PX30_LVDS_P2S_EN(0));
349 pm_runtime_put(lvds
->dev
);
352 static int px30_lvds_grf_config(struct drm_encoder
*encoder
,
353 struct drm_display_mode
*mode
)
355 struct rockchip_lvds
*lvds
= encoder_to_lvds(encoder
);
357 if (lvds
->output
!= DISPLAY_OUTPUT_LVDS
) {
358 DRM_DEV_ERROR(lvds
->dev
, "Unsupported display output %d\n",
364 return regmap_update_bits(lvds
->grf
, PX30_LVDS_GRF_PD_VO_CON1
,
365 PX30_LVDS_FORMAT(lvds
->format
),
366 PX30_LVDS_FORMAT(lvds
->format
));
369 static int px30_lvds_set_vop_source(struct rockchip_lvds
*lvds
,
370 struct drm_encoder
*encoder
)
374 vop
= drm_of_encoder_active_endpoint_id(lvds
->dev
->of_node
, encoder
);
378 return regmap_update_bits(lvds
->grf
, PX30_LVDS_GRF_PD_VO_CON1
,
379 PX30_LVDS_VOP_SEL(1),
380 PX30_LVDS_VOP_SEL(vop
));
383 static void px30_lvds_encoder_enable(struct drm_encoder
*encoder
)
385 struct rockchip_lvds
*lvds
= encoder_to_lvds(encoder
);
386 struct drm_display_mode
*mode
= &encoder
->crtc
->state
->adjusted_mode
;
389 drm_panel_prepare(lvds
->panel
);
391 ret
= px30_lvds_poweron(lvds
);
393 DRM_DEV_ERROR(lvds
->dev
, "failed to power on LVDS: %d\n", ret
);
394 drm_panel_unprepare(lvds
->panel
);
398 ret
= px30_lvds_grf_config(encoder
, mode
);
400 DRM_DEV_ERROR(lvds
->dev
, "failed to configure LVDS: %d\n", ret
);
401 drm_panel_unprepare(lvds
->panel
);
405 ret
= px30_lvds_set_vop_source(lvds
, encoder
);
407 DRM_DEV_ERROR(lvds
->dev
, "failed to set VOP source: %d\n", ret
);
408 drm_panel_unprepare(lvds
->panel
);
412 drm_panel_enable(lvds
->panel
);
415 static void px30_lvds_encoder_disable(struct drm_encoder
*encoder
)
417 struct rockchip_lvds
*lvds
= encoder_to_lvds(encoder
);
419 drm_panel_disable(lvds
->panel
);
420 px30_lvds_poweroff(lvds
);
421 drm_panel_unprepare(lvds
->panel
);
425 struct drm_encoder_helper_funcs rk3288_lvds_encoder_helper_funcs
= {
426 .enable
= rk3288_lvds_encoder_enable
,
427 .disable
= rk3288_lvds_encoder_disable
,
428 .atomic_check
= rockchip_lvds_encoder_atomic_check
,
432 struct drm_encoder_helper_funcs px30_lvds_encoder_helper_funcs
= {
433 .enable
= px30_lvds_encoder_enable
,
434 .disable
= px30_lvds_encoder_disable
,
435 .atomic_check
= rockchip_lvds_encoder_atomic_check
,
438 static const struct drm_encoder_funcs rockchip_lvds_encoder_funcs
= {
439 .destroy
= drm_encoder_cleanup
,
442 static int rk3288_lvds_probe(struct platform_device
*pdev
,
443 struct rockchip_lvds
*lvds
)
445 struct resource
*res
;
448 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
449 lvds
->regs
= devm_ioremap_resource(lvds
->dev
, res
);
450 if (IS_ERR(lvds
->regs
))
451 return PTR_ERR(lvds
->regs
);
453 lvds
->pclk
= devm_clk_get(lvds
->dev
, "pclk_lvds");
454 if (IS_ERR(lvds
->pclk
)) {
455 DRM_DEV_ERROR(lvds
->dev
, "could not get pclk_lvds\n");
456 return PTR_ERR(lvds
->pclk
);
459 lvds
->pins
= devm_kzalloc(lvds
->dev
, sizeof(*lvds
->pins
),
464 lvds
->pins
->p
= devm_pinctrl_get(lvds
->dev
);
465 if (IS_ERR(lvds
->pins
->p
)) {
466 DRM_DEV_ERROR(lvds
->dev
, "no pinctrl handle\n");
467 devm_kfree(lvds
->dev
, lvds
->pins
);
470 lvds
->pins
->default_state
=
471 pinctrl_lookup_state(lvds
->pins
->p
, "lcdc");
472 if (IS_ERR(lvds
->pins
->default_state
)) {
473 DRM_DEV_ERROR(lvds
->dev
, "no default pinctrl state\n");
474 devm_kfree(lvds
->dev
, lvds
->pins
);
479 ret
= clk_prepare(lvds
->pclk
);
481 DRM_DEV_ERROR(lvds
->dev
, "failed to prepare pclk_lvds\n");
488 static int px30_lvds_probe(struct platform_device
*pdev
,
489 struct rockchip_lvds
*lvds
)
494 ret
= regmap_update_bits(lvds
->grf
, PX30_LVDS_GRF_PD_VO_CON1
,
496 PX30_LVDS_MSBSEL(1));
501 lvds
->dphy
= devm_phy_get(&pdev
->dev
, "dphy");
502 if (IS_ERR(lvds
->dphy
))
503 return PTR_ERR(lvds
->dphy
);
505 phy_init(lvds
->dphy
);
509 phy_set_mode(lvds
->dphy
, PHY_MODE_LVDS
);
513 return phy_power_on(lvds
->dphy
);
516 static const struct rockchip_lvds_soc_data rk3288_lvds_data
= {
517 .probe
= rk3288_lvds_probe
,
518 .helper_funcs
= &rk3288_lvds_encoder_helper_funcs
,
521 static const struct rockchip_lvds_soc_data px30_lvds_data
= {
522 .probe
= px30_lvds_probe
,
523 .helper_funcs
= &px30_lvds_encoder_helper_funcs
,
526 static const struct of_device_id rockchip_lvds_dt_ids
[] = {
528 .compatible
= "rockchip,rk3288-lvds",
529 .data
= &rk3288_lvds_data
532 .compatible
= "rockchip,px30-lvds",
533 .data
= &px30_lvds_data
537 MODULE_DEVICE_TABLE(of
, rockchip_lvds_dt_ids
);
539 static int rockchip_lvds_bind(struct device
*dev
, struct device
*master
,
542 struct rockchip_lvds
*lvds
= dev_get_drvdata(dev
);
543 struct drm_device
*drm_dev
= data
;
544 struct drm_encoder
*encoder
;
545 struct drm_connector
*connector
;
546 struct device_node
*remote
= NULL
;
547 struct device_node
*port
, *endpoint
;
548 int ret
= 0, child_count
= 0;
552 lvds
->drm_dev
= drm_dev
;
553 port
= of_graph_get_port_by_id(dev
->of_node
, 1);
556 "can't found port point, please init lvds panel port!\n");
559 for_each_child_of_node(port
, endpoint
) {
561 of_property_read_u32(endpoint
, "reg", &endpoint_id
);
562 ret
= drm_of_find_panel_or_bridge(dev
->of_node
, 1, endpoint_id
,
563 &lvds
->panel
, &lvds
->bridge
);
565 of_node_put(endpoint
);
570 DRM_DEV_ERROR(dev
, "lvds port does not have any children\n");
574 DRM_DEV_ERROR(dev
, "failed to find panel and bridge node\n");
579 remote
= lvds
->panel
->dev
->of_node
;
581 remote
= lvds
->bridge
->of_node
;
582 if (of_property_read_string(dev
->of_node
, "rockchip,output", &name
))
583 /* default set it as output rgb */
584 lvds
->output
= DISPLAY_OUTPUT_RGB
;
586 lvds
->output
= rockchip_lvds_name_to_output(name
);
588 if (lvds
->output
< 0) {
589 DRM_DEV_ERROR(dev
, "invalid output type [%s]\n", name
);
594 if (of_property_read_string(remote
, "data-mapping", &name
))
595 /* default set it as format vesa 18 */
596 lvds
->format
= LVDS_VESA_18
;
598 lvds
->format
= rockchip_lvds_name_to_format(name
);
600 if (lvds
->format
< 0) {
601 DRM_DEV_ERROR(dev
, "invalid data-mapping format [%s]\n", name
);
606 encoder
= &lvds
->encoder
;
607 encoder
->possible_crtcs
= drm_of_find_possible_crtcs(drm_dev
,
610 ret
= drm_encoder_init(drm_dev
, encoder
, &rockchip_lvds_encoder_funcs
,
611 DRM_MODE_ENCODER_LVDS
, NULL
);
613 DRM_DEV_ERROR(drm_dev
->dev
,
614 "failed to initialize encoder: %d\n", ret
);
618 drm_encoder_helper_add(encoder
, lvds
->soc_data
->helper_funcs
);
621 connector
= &lvds
->connector
;
622 connector
->dpms
= DRM_MODE_DPMS_OFF
;
623 ret
= drm_connector_init(drm_dev
, connector
,
624 &rockchip_lvds_connector_funcs
,
625 DRM_MODE_CONNECTOR_LVDS
);
627 DRM_DEV_ERROR(drm_dev
->dev
,
628 "failed to initialize connector: %d\n", ret
);
629 goto err_free_encoder
;
632 drm_connector_helper_add(connector
,
633 &rockchip_lvds_connector_helper_funcs
);
635 ret
= drm_connector_attach_encoder(connector
, encoder
);
637 DRM_DEV_ERROR(drm_dev
->dev
,
638 "failed to attach encoder: %d\n", ret
);
639 goto err_free_connector
;
642 ret
= drm_panel_attach(lvds
->panel
, connector
);
644 DRM_DEV_ERROR(drm_dev
->dev
,
645 "failed to attach panel: %d\n", ret
);
646 goto err_free_connector
;
649 ret
= drm_bridge_attach(encoder
, lvds
->bridge
, NULL
);
651 DRM_DEV_ERROR(drm_dev
->dev
,
652 "failed to attach bridge: %d\n", ret
);
653 goto err_free_encoder
;
657 pm_runtime_enable(dev
);
664 drm_connector_cleanup(connector
);
666 drm_encoder_cleanup(encoder
);
675 static void rockchip_lvds_unbind(struct device
*dev
, struct device
*master
,
678 struct rockchip_lvds
*lvds
= dev_get_drvdata(dev
);
679 const struct drm_encoder_helper_funcs
*encoder_funcs
;
681 encoder_funcs
= lvds
->soc_data
->helper_funcs
;
682 encoder_funcs
->disable(&lvds
->encoder
);
684 drm_panel_detach(lvds
->panel
);
685 pm_runtime_disable(dev
);
686 drm_connector_cleanup(&lvds
->connector
);
687 drm_encoder_cleanup(&lvds
->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 int rockchip_lvds_remove(struct platform_device
*pdev
)
741 struct rockchip_lvds
*lvds
= dev_get_drvdata(&pdev
->dev
);
743 component_del(&pdev
->dev
, &rockchip_lvds_component_ops
);
744 clk_unprepare(lvds
->pclk
);
749 struct platform_driver rockchip_lvds_driver
= {
750 .probe
= rockchip_lvds_probe
,
751 .remove
= rockchip_lvds_remove
,
753 .name
= "rockchip-lvds",
754 .of_match_table
= of_match_ptr(rockchip_lvds_dt_ids
),