2 * Copyright (c) 2014 MediaTek Inc.
3 * Author: Jie Qiu <jie.qiu@mediatek.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #include <drm/drm_crtc.h>
16 #include <drm/drm_crtc_helper.h>
17 #include <linux/kernel.h>
18 #include <linux/component.h>
19 #include <linux/platform_device.h>
21 #include <linux/of_graph.h>
22 #include <linux/interrupt.h>
23 #include <linux/types.h>
24 #include <linux/clk.h>
26 #include "mtk_dpi_regs.h"
27 #include "mtk_drm_ddp_comp.h"
29 enum mtk_dpi_out_bit_num
{
30 MTK_DPI_OUT_BIT_NUM_8BITS
,
31 MTK_DPI_OUT_BIT_NUM_10BITS
,
32 MTK_DPI_OUT_BIT_NUM_12BITS
,
33 MTK_DPI_OUT_BIT_NUM_16BITS
36 enum mtk_dpi_out_yc_map
{
37 MTK_DPI_OUT_YC_MAP_RGB
,
38 MTK_DPI_OUT_YC_MAP_CYCY
,
39 MTK_DPI_OUT_YC_MAP_YCYC
,
40 MTK_DPI_OUT_YC_MAP_CY
,
44 enum mtk_dpi_out_channel_swap
{
45 MTK_DPI_OUT_CHANNEL_SWAP_RGB
,
46 MTK_DPI_OUT_CHANNEL_SWAP_GBR
,
47 MTK_DPI_OUT_CHANNEL_SWAP_BRG
,
48 MTK_DPI_OUT_CHANNEL_SWAP_RBG
,
49 MTK_DPI_OUT_CHANNEL_SWAP_GRB
,
50 MTK_DPI_OUT_CHANNEL_SWAP_BGR
53 enum mtk_dpi_out_color_format
{
54 MTK_DPI_COLOR_FORMAT_RGB
,
55 MTK_DPI_COLOR_FORMAT_RGB_FULL
,
56 MTK_DPI_COLOR_FORMAT_YCBCR_444
,
57 MTK_DPI_COLOR_FORMAT_YCBCR_422
,
58 MTK_DPI_COLOR_FORMAT_XV_YCC
,
59 MTK_DPI_COLOR_FORMAT_YCBCR_444_FULL
,
60 MTK_DPI_COLOR_FORMAT_YCBCR_422_FULL
64 struct mtk_ddp_comp ddp_comp
;
65 struct drm_encoder encoder
;
66 struct drm_bridge
*bridge
;
69 struct clk
*engine_clk
;
70 struct clk
*pixel_clk
;
73 struct drm_display_mode mode
;
74 enum mtk_dpi_out_color_format color_format
;
75 enum mtk_dpi_out_yc_map yc_map
;
76 enum mtk_dpi_out_bit_num bit_num
;
77 enum mtk_dpi_out_channel_swap channel_swap
;
82 static inline struct mtk_dpi
*mtk_dpi_from_encoder(struct drm_encoder
*e
)
84 return container_of(e
, struct mtk_dpi
, encoder
);
87 enum mtk_dpi_polarity
{
88 MTK_DPI_POLARITY_RISING
,
89 MTK_DPI_POLARITY_FALLING
,
92 enum mtk_dpi_power_ctl
{
93 DPI_POWER_START
= BIT(0),
94 DPI_POWER_ENABLE
= BIT(1),
97 struct mtk_dpi_polarities
{
98 enum mtk_dpi_polarity de_pol
;
99 enum mtk_dpi_polarity ck_pol
;
100 enum mtk_dpi_polarity hsync_pol
;
101 enum mtk_dpi_polarity vsync_pol
;
104 struct mtk_dpi_sync_param
{
108 bool shift_half_line
;
111 struct mtk_dpi_yc_limit
{
118 static void mtk_dpi_mask(struct mtk_dpi
*dpi
, u32 offset
, u32 val
, u32 mask
)
120 u32 tmp
= readl(dpi
->regs
+ offset
) & ~mask
;
123 writel(tmp
, dpi
->regs
+ offset
);
126 static void mtk_dpi_sw_reset(struct mtk_dpi
*dpi
, bool reset
)
128 mtk_dpi_mask(dpi
, DPI_RET
, reset
? RST
: 0, RST
);
131 static void mtk_dpi_enable(struct mtk_dpi
*dpi
)
133 mtk_dpi_mask(dpi
, DPI_EN
, EN
, EN
);
136 static void mtk_dpi_disable(struct mtk_dpi
*dpi
)
138 mtk_dpi_mask(dpi
, DPI_EN
, 0, EN
);
141 static void mtk_dpi_config_hsync(struct mtk_dpi
*dpi
,
142 struct mtk_dpi_sync_param
*sync
)
144 mtk_dpi_mask(dpi
, DPI_TGEN_HWIDTH
,
145 sync
->sync_width
<< HPW
, HPW_MASK
);
146 mtk_dpi_mask(dpi
, DPI_TGEN_HPORCH
,
147 sync
->back_porch
<< HBP
, HBP_MASK
);
148 mtk_dpi_mask(dpi
, DPI_TGEN_HPORCH
, sync
->front_porch
<< HFP
,
152 static void mtk_dpi_config_vsync(struct mtk_dpi
*dpi
,
153 struct mtk_dpi_sync_param
*sync
,
154 u32 width_addr
, u32 porch_addr
)
156 mtk_dpi_mask(dpi
, width_addr
,
157 sync
->sync_width
<< VSYNC_WIDTH_SHIFT
,
159 mtk_dpi_mask(dpi
, width_addr
,
160 sync
->shift_half_line
<< VSYNC_HALF_LINE_SHIFT
,
161 VSYNC_HALF_LINE_MASK
);
162 mtk_dpi_mask(dpi
, porch_addr
,
163 sync
->back_porch
<< VSYNC_BACK_PORCH_SHIFT
,
164 VSYNC_BACK_PORCH_MASK
);
165 mtk_dpi_mask(dpi
, porch_addr
,
166 sync
->front_porch
<< VSYNC_FRONT_PORCH_SHIFT
,
167 VSYNC_FRONT_PORCH_MASK
);
170 static void mtk_dpi_config_vsync_lodd(struct mtk_dpi
*dpi
,
171 struct mtk_dpi_sync_param
*sync
)
173 mtk_dpi_config_vsync(dpi
, sync
, DPI_TGEN_VWIDTH
, DPI_TGEN_VPORCH
);
176 static void mtk_dpi_config_vsync_leven(struct mtk_dpi
*dpi
,
177 struct mtk_dpi_sync_param
*sync
)
179 mtk_dpi_config_vsync(dpi
, sync
, DPI_TGEN_VWIDTH_LEVEN
,
180 DPI_TGEN_VPORCH_LEVEN
);
183 static void mtk_dpi_config_vsync_rodd(struct mtk_dpi
*dpi
,
184 struct mtk_dpi_sync_param
*sync
)
186 mtk_dpi_config_vsync(dpi
, sync
, DPI_TGEN_VWIDTH_RODD
,
187 DPI_TGEN_VPORCH_RODD
);
190 static void mtk_dpi_config_vsync_reven(struct mtk_dpi
*dpi
,
191 struct mtk_dpi_sync_param
*sync
)
193 mtk_dpi_config_vsync(dpi
, sync
, DPI_TGEN_VWIDTH_REVEN
,
194 DPI_TGEN_VPORCH_REVEN
);
197 static void mtk_dpi_config_pol(struct mtk_dpi
*dpi
,
198 struct mtk_dpi_polarities
*dpi_pol
)
202 pol
= (dpi_pol
->ck_pol
== MTK_DPI_POLARITY_RISING
? 0 : CK_POL
) |
203 (dpi_pol
->de_pol
== MTK_DPI_POLARITY_RISING
? 0 : DE_POL
) |
204 (dpi_pol
->hsync_pol
== MTK_DPI_POLARITY_RISING
? 0 : HSYNC_POL
) |
205 (dpi_pol
->vsync_pol
== MTK_DPI_POLARITY_RISING
? 0 : VSYNC_POL
);
206 mtk_dpi_mask(dpi
, DPI_OUTPUT_SETTING
, pol
,
207 CK_POL
| DE_POL
| HSYNC_POL
| VSYNC_POL
);
210 static void mtk_dpi_config_3d(struct mtk_dpi
*dpi
, bool en_3d
)
212 mtk_dpi_mask(dpi
, DPI_CON
, en_3d
? TDFP_EN
: 0, TDFP_EN
);
215 static void mtk_dpi_config_interface(struct mtk_dpi
*dpi
, bool inter
)
217 mtk_dpi_mask(dpi
, DPI_CON
, inter
? INTL_EN
: 0, INTL_EN
);
220 static void mtk_dpi_config_fb_size(struct mtk_dpi
*dpi
, u32 width
, u32 height
)
222 mtk_dpi_mask(dpi
, DPI_SIZE
, width
<< HSIZE
, HSIZE_MASK
);
223 mtk_dpi_mask(dpi
, DPI_SIZE
, height
<< VSIZE
, VSIZE_MASK
);
226 static void mtk_dpi_config_channel_limit(struct mtk_dpi
*dpi
,
227 struct mtk_dpi_yc_limit
*limit
)
229 mtk_dpi_mask(dpi
, DPI_Y_LIMIT
, limit
->y_bottom
<< Y_LIMINT_BOT
,
231 mtk_dpi_mask(dpi
, DPI_Y_LIMIT
, limit
->y_top
<< Y_LIMINT_TOP
,
233 mtk_dpi_mask(dpi
, DPI_C_LIMIT
, limit
->c_bottom
<< C_LIMIT_BOT
,
235 mtk_dpi_mask(dpi
, DPI_C_LIMIT
, limit
->c_top
<< C_LIMIT_TOP
,
239 static void mtk_dpi_config_bit_num(struct mtk_dpi
*dpi
,
240 enum mtk_dpi_out_bit_num num
)
245 case MTK_DPI_OUT_BIT_NUM_8BITS
:
248 case MTK_DPI_OUT_BIT_NUM_10BITS
:
251 case MTK_DPI_OUT_BIT_NUM_12BITS
:
254 case MTK_DPI_OUT_BIT_NUM_16BITS
:
261 mtk_dpi_mask(dpi
, DPI_OUTPUT_SETTING
, val
<< OUT_BIT
,
265 static void mtk_dpi_config_yc_map(struct mtk_dpi
*dpi
,
266 enum mtk_dpi_out_yc_map map
)
271 case MTK_DPI_OUT_YC_MAP_RGB
:
274 case MTK_DPI_OUT_YC_MAP_CYCY
:
277 case MTK_DPI_OUT_YC_MAP_YCYC
:
280 case MTK_DPI_OUT_YC_MAP_CY
:
283 case MTK_DPI_OUT_YC_MAP_YC
:
291 mtk_dpi_mask(dpi
, DPI_OUTPUT_SETTING
, val
<< YC_MAP
, YC_MAP_MASK
);
294 static void mtk_dpi_config_channel_swap(struct mtk_dpi
*dpi
,
295 enum mtk_dpi_out_channel_swap swap
)
300 case MTK_DPI_OUT_CHANNEL_SWAP_RGB
:
303 case MTK_DPI_OUT_CHANNEL_SWAP_GBR
:
306 case MTK_DPI_OUT_CHANNEL_SWAP_BRG
:
309 case MTK_DPI_OUT_CHANNEL_SWAP_RBG
:
312 case MTK_DPI_OUT_CHANNEL_SWAP_GRB
:
315 case MTK_DPI_OUT_CHANNEL_SWAP_BGR
:
323 mtk_dpi_mask(dpi
, DPI_OUTPUT_SETTING
, val
<< CH_SWAP
, CH_SWAP_MASK
);
326 static void mtk_dpi_config_yuv422_enable(struct mtk_dpi
*dpi
, bool enable
)
328 mtk_dpi_mask(dpi
, DPI_CON
, enable
? YUV422_EN
: 0, YUV422_EN
);
331 static void mtk_dpi_config_csc_enable(struct mtk_dpi
*dpi
, bool enable
)
333 mtk_dpi_mask(dpi
, DPI_CON
, enable
? CSC_ENABLE
: 0, CSC_ENABLE
);
336 static void mtk_dpi_config_swap_input(struct mtk_dpi
*dpi
, bool enable
)
338 mtk_dpi_mask(dpi
, DPI_CON
, enable
? IN_RB_SWAP
: 0, IN_RB_SWAP
);
341 static void mtk_dpi_config_2n_h_fre(struct mtk_dpi
*dpi
)
343 mtk_dpi_mask(dpi
, DPI_H_FRE_CON
, H_FRE_2N
, H_FRE_2N
);
346 static void mtk_dpi_config_color_format(struct mtk_dpi
*dpi
,
347 enum mtk_dpi_out_color_format format
)
349 if ((format
== MTK_DPI_COLOR_FORMAT_YCBCR_444
) ||
350 (format
== MTK_DPI_COLOR_FORMAT_YCBCR_444_FULL
)) {
351 mtk_dpi_config_yuv422_enable(dpi
, false);
352 mtk_dpi_config_csc_enable(dpi
, true);
353 mtk_dpi_config_swap_input(dpi
, false);
354 mtk_dpi_config_channel_swap(dpi
, MTK_DPI_OUT_CHANNEL_SWAP_BGR
);
355 } else if ((format
== MTK_DPI_COLOR_FORMAT_YCBCR_422
) ||
356 (format
== MTK_DPI_COLOR_FORMAT_YCBCR_422_FULL
)) {
357 mtk_dpi_config_yuv422_enable(dpi
, true);
358 mtk_dpi_config_csc_enable(dpi
, true);
359 mtk_dpi_config_swap_input(dpi
, true);
360 mtk_dpi_config_channel_swap(dpi
, MTK_DPI_OUT_CHANNEL_SWAP_RGB
);
362 mtk_dpi_config_yuv422_enable(dpi
, false);
363 mtk_dpi_config_csc_enable(dpi
, false);
364 mtk_dpi_config_swap_input(dpi
, false);
365 mtk_dpi_config_channel_swap(dpi
, MTK_DPI_OUT_CHANNEL_SWAP_RGB
);
369 static void mtk_dpi_power_off(struct mtk_dpi
*dpi
, enum mtk_dpi_power_ctl pctl
)
371 dpi
->power_ctl
&= ~pctl
;
373 if ((dpi
->power_ctl
& DPI_POWER_START
) ||
374 (dpi
->power_ctl
& DPI_POWER_ENABLE
))
380 mtk_dpi_disable(dpi
);
381 clk_disable_unprepare(dpi
->pixel_clk
);
382 clk_disable_unprepare(dpi
->engine_clk
);
383 dpi
->power_sta
= false;
386 static int mtk_dpi_power_on(struct mtk_dpi
*dpi
, enum mtk_dpi_power_ctl pctl
)
390 dpi
->power_ctl
|= pctl
;
392 if (!(dpi
->power_ctl
& DPI_POWER_START
) &&
393 !(dpi
->power_ctl
& DPI_POWER_ENABLE
))
399 ret
= clk_prepare_enable(dpi
->engine_clk
);
401 dev_err(dpi
->dev
, "Failed to enable engine clock: %d\n", ret
);
405 ret
= clk_prepare_enable(dpi
->pixel_clk
);
407 dev_err(dpi
->dev
, "Failed to enable pixel clock: %d\n", ret
);
412 dpi
->power_sta
= true;
416 clk_disable_unprepare(dpi
->engine_clk
);
418 dpi
->power_ctl
&= ~pctl
;
422 static int mtk_dpi_set_display_mode(struct mtk_dpi
*dpi
,
423 struct drm_display_mode
*mode
)
425 struct mtk_dpi_yc_limit limit
;
426 struct mtk_dpi_polarities dpi_pol
;
427 struct mtk_dpi_sync_param hsync
;
428 struct mtk_dpi_sync_param vsync_lodd
= { 0 };
429 struct mtk_dpi_sync_param vsync_leven
= { 0 };
430 struct mtk_dpi_sync_param vsync_rodd
= { 0 };
431 struct mtk_dpi_sync_param vsync_reven
= { 0 };
432 unsigned long pix_rate
;
433 unsigned long pll_rate
;
436 /* let pll_rate can fix the valid range of tvdpll (1G~2GHz) */
437 pix_rate
= 1000UL * mode
->clock
;
438 if (mode
->clock
<= 27000)
440 else if (mode
->clock
<= 84000)
442 else if (mode
->clock
<= 167000)
446 pll_rate
= pix_rate
* factor
;
448 dev_dbg(dpi
->dev
, "Want PLL %lu Hz, pixel clock %lu Hz\n",
451 clk_set_rate(dpi
->tvd_clk
, pll_rate
);
452 pll_rate
= clk_get_rate(dpi
->tvd_clk
);
454 pix_rate
= pll_rate
/ factor
;
455 clk_set_rate(dpi
->pixel_clk
, pix_rate
);
456 pix_rate
= clk_get_rate(dpi
->pixel_clk
);
458 dev_dbg(dpi
->dev
, "Got PLL %lu Hz, pixel clock %lu Hz\n",
461 limit
.c_bottom
= 0x0010;
462 limit
.c_top
= 0x0FE0;
463 limit
.y_bottom
= 0x0010;
464 limit
.y_top
= 0x0FE0;
466 dpi_pol
.ck_pol
= MTK_DPI_POLARITY_FALLING
;
467 dpi_pol
.de_pol
= MTK_DPI_POLARITY_RISING
;
468 dpi_pol
.hsync_pol
= mode
->flags
& DRM_MODE_FLAG_PHSYNC
?
469 MTK_DPI_POLARITY_FALLING
: MTK_DPI_POLARITY_RISING
;
470 dpi_pol
.vsync_pol
= mode
->flags
& DRM_MODE_FLAG_PVSYNC
?
471 MTK_DPI_POLARITY_FALLING
: MTK_DPI_POLARITY_RISING
;
473 hsync
.sync_width
= mode
->hsync_end
- mode
->hsync_start
;
474 hsync
.back_porch
= mode
->htotal
- mode
->hsync_end
;
475 hsync
.front_porch
= mode
->hsync_start
- mode
->hdisplay
;
476 hsync
.shift_half_line
= false;
478 vsync_lodd
.sync_width
= mode
->vsync_end
- mode
->vsync_start
;
479 vsync_lodd
.back_porch
= mode
->vtotal
- mode
->vsync_end
;
480 vsync_lodd
.front_porch
= mode
->vsync_start
- mode
->vdisplay
;
481 vsync_lodd
.shift_half_line
= false;
483 if (mode
->flags
& DRM_MODE_FLAG_INTERLACE
&&
484 mode
->flags
& DRM_MODE_FLAG_3D_MASK
) {
485 vsync_leven
= vsync_lodd
;
486 vsync_rodd
= vsync_lodd
;
487 vsync_reven
= vsync_lodd
;
488 vsync_leven
.shift_half_line
= true;
489 vsync_reven
.shift_half_line
= true;
490 } else if (mode
->flags
& DRM_MODE_FLAG_INTERLACE
&&
491 !(mode
->flags
& DRM_MODE_FLAG_3D_MASK
)) {
492 vsync_leven
= vsync_lodd
;
493 vsync_leven
.shift_half_line
= true;
494 } else if (!(mode
->flags
& DRM_MODE_FLAG_INTERLACE
) &&
495 mode
->flags
& DRM_MODE_FLAG_3D_MASK
) {
496 vsync_rodd
= vsync_lodd
;
498 mtk_dpi_sw_reset(dpi
, true);
499 mtk_dpi_config_pol(dpi
, &dpi_pol
);
501 mtk_dpi_config_hsync(dpi
, &hsync
);
502 mtk_dpi_config_vsync_lodd(dpi
, &vsync_lodd
);
503 mtk_dpi_config_vsync_rodd(dpi
, &vsync_rodd
);
504 mtk_dpi_config_vsync_leven(dpi
, &vsync_leven
);
505 mtk_dpi_config_vsync_reven(dpi
, &vsync_reven
);
507 mtk_dpi_config_3d(dpi
, !!(mode
->flags
& DRM_MODE_FLAG_3D_MASK
));
508 mtk_dpi_config_interface(dpi
, !!(mode
->flags
&
509 DRM_MODE_FLAG_INTERLACE
));
510 if (mode
->flags
& DRM_MODE_FLAG_INTERLACE
)
511 mtk_dpi_config_fb_size(dpi
, mode
->hdisplay
, mode
->vdisplay
/ 2);
513 mtk_dpi_config_fb_size(dpi
, mode
->hdisplay
, mode
->vdisplay
);
515 mtk_dpi_config_channel_limit(dpi
, &limit
);
516 mtk_dpi_config_bit_num(dpi
, dpi
->bit_num
);
517 mtk_dpi_config_channel_swap(dpi
, dpi
->channel_swap
);
518 mtk_dpi_config_yc_map(dpi
, dpi
->yc_map
);
519 mtk_dpi_config_color_format(dpi
, dpi
->color_format
);
520 mtk_dpi_config_2n_h_fre(dpi
);
521 mtk_dpi_sw_reset(dpi
, false);
526 static void mtk_dpi_encoder_destroy(struct drm_encoder
*encoder
)
528 drm_encoder_cleanup(encoder
);
531 static const struct drm_encoder_funcs mtk_dpi_encoder_funcs
= {
532 .destroy
= mtk_dpi_encoder_destroy
,
535 static bool mtk_dpi_encoder_mode_fixup(struct drm_encoder
*encoder
,
536 const struct drm_display_mode
*mode
,
537 struct drm_display_mode
*adjusted_mode
)
542 static void mtk_dpi_encoder_mode_set(struct drm_encoder
*encoder
,
543 struct drm_display_mode
*mode
,
544 struct drm_display_mode
*adjusted_mode
)
546 struct mtk_dpi
*dpi
= mtk_dpi_from_encoder(encoder
);
548 drm_mode_copy(&dpi
->mode
, adjusted_mode
);
551 static void mtk_dpi_encoder_disable(struct drm_encoder
*encoder
)
553 struct mtk_dpi
*dpi
= mtk_dpi_from_encoder(encoder
);
555 mtk_dpi_power_off(dpi
, DPI_POWER_ENABLE
);
558 static void mtk_dpi_encoder_enable(struct drm_encoder
*encoder
)
560 struct mtk_dpi
*dpi
= mtk_dpi_from_encoder(encoder
);
562 mtk_dpi_power_on(dpi
, DPI_POWER_ENABLE
);
563 mtk_dpi_set_display_mode(dpi
, &dpi
->mode
);
566 static int mtk_dpi_atomic_check(struct drm_encoder
*encoder
,
567 struct drm_crtc_state
*crtc_state
,
568 struct drm_connector_state
*conn_state
)
573 static const struct drm_encoder_helper_funcs mtk_dpi_encoder_helper_funcs
= {
574 .mode_fixup
= mtk_dpi_encoder_mode_fixup
,
575 .mode_set
= mtk_dpi_encoder_mode_set
,
576 .disable
= mtk_dpi_encoder_disable
,
577 .enable
= mtk_dpi_encoder_enable
,
578 .atomic_check
= mtk_dpi_atomic_check
,
581 static void mtk_dpi_start(struct mtk_ddp_comp
*comp
)
583 struct mtk_dpi
*dpi
= container_of(comp
, struct mtk_dpi
, ddp_comp
);
585 mtk_dpi_power_on(dpi
, DPI_POWER_START
);
588 static void mtk_dpi_stop(struct mtk_ddp_comp
*comp
)
590 struct mtk_dpi
*dpi
= container_of(comp
, struct mtk_dpi
, ddp_comp
);
592 mtk_dpi_power_off(dpi
, DPI_POWER_START
);
595 static const struct mtk_ddp_comp_funcs mtk_dpi_funcs
= {
596 .start
= mtk_dpi_start
,
597 .stop
= mtk_dpi_stop
,
600 static int mtk_dpi_bind(struct device
*dev
, struct device
*master
, void *data
)
602 struct mtk_dpi
*dpi
= dev_get_drvdata(dev
);
603 struct drm_device
*drm_dev
= data
;
606 ret
= mtk_ddp_comp_register(drm_dev
, &dpi
->ddp_comp
);
608 dev_err(dev
, "Failed to register component %s: %d\n",
609 dev
->of_node
->full_name
, ret
);
613 ret
= drm_encoder_init(drm_dev
, &dpi
->encoder
, &mtk_dpi_encoder_funcs
,
614 DRM_MODE_ENCODER_TMDS
, NULL
);
616 dev_err(dev
, "Failed to initialize decoder: %d\n", ret
);
619 drm_encoder_helper_add(&dpi
->encoder
, &mtk_dpi_encoder_helper_funcs
);
621 /* Currently DPI0 is fixed to be driven by OVL1 */
622 dpi
->encoder
.possible_crtcs
= BIT(1);
624 ret
= drm_bridge_attach(&dpi
->encoder
, dpi
->bridge
, NULL
);
626 dev_err(dev
, "Failed to attach bridge: %d\n", ret
);
630 dpi
->bit_num
= MTK_DPI_OUT_BIT_NUM_8BITS
;
631 dpi
->channel_swap
= MTK_DPI_OUT_CHANNEL_SWAP_RGB
;
632 dpi
->yc_map
= MTK_DPI_OUT_YC_MAP_RGB
;
633 dpi
->color_format
= MTK_DPI_COLOR_FORMAT_RGB
;
638 drm_encoder_cleanup(&dpi
->encoder
);
640 mtk_ddp_comp_unregister(drm_dev
, &dpi
->ddp_comp
);
644 static void mtk_dpi_unbind(struct device
*dev
, struct device
*master
,
647 struct mtk_dpi
*dpi
= dev_get_drvdata(dev
);
648 struct drm_device
*drm_dev
= data
;
650 drm_encoder_cleanup(&dpi
->encoder
);
651 mtk_ddp_comp_unregister(drm_dev
, &dpi
->ddp_comp
);
654 static const struct component_ops mtk_dpi_component_ops
= {
655 .bind
= mtk_dpi_bind
,
656 .unbind
= mtk_dpi_unbind
,
659 static int mtk_dpi_probe(struct platform_device
*pdev
)
661 struct device
*dev
= &pdev
->dev
;
663 struct resource
*mem
;
664 struct device_node
*bridge_node
;
668 dpi
= devm_kzalloc(dev
, sizeof(*dpi
), GFP_KERNEL
);
674 mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
675 dpi
->regs
= devm_ioremap_resource(dev
, mem
);
676 if (IS_ERR(dpi
->regs
)) {
677 ret
= PTR_ERR(dpi
->regs
);
678 dev_err(dev
, "Failed to ioremap mem resource: %d\n", ret
);
682 dpi
->engine_clk
= devm_clk_get(dev
, "engine");
683 if (IS_ERR(dpi
->engine_clk
)) {
684 ret
= PTR_ERR(dpi
->engine_clk
);
685 dev_err(dev
, "Failed to get engine clock: %d\n", ret
);
689 dpi
->pixel_clk
= devm_clk_get(dev
, "pixel");
690 if (IS_ERR(dpi
->pixel_clk
)) {
691 ret
= PTR_ERR(dpi
->pixel_clk
);
692 dev_err(dev
, "Failed to get pixel clock: %d\n", ret
);
696 dpi
->tvd_clk
= devm_clk_get(dev
, "pll");
697 if (IS_ERR(dpi
->tvd_clk
)) {
698 ret
= PTR_ERR(dpi
->tvd_clk
);
699 dev_err(dev
, "Failed to get tvdpll clock: %d\n", ret
);
703 dpi
->irq
= platform_get_irq(pdev
, 0);
705 dev_err(dev
, "Failed to get irq: %d\n", dpi
->irq
);
709 bridge_node
= of_graph_get_remote_node(dev
->of_node
, 0, 0);
713 dev_info(dev
, "Found bridge node: %s\n", bridge_node
->full_name
);
715 dpi
->bridge
= of_drm_find_bridge(bridge_node
);
716 of_node_put(bridge_node
);
718 return -EPROBE_DEFER
;
720 comp_id
= mtk_ddp_comp_get_id(dev
->of_node
, MTK_DPI
);
722 dev_err(dev
, "Failed to identify by alias: %d\n", comp_id
);
726 ret
= mtk_ddp_comp_init(dev
, dev
->of_node
, &dpi
->ddp_comp
, comp_id
,
729 dev_err(dev
, "Failed to initialize component: %d\n", ret
);
733 platform_set_drvdata(pdev
, dpi
);
735 ret
= component_add(dev
, &mtk_dpi_component_ops
);
737 dev_err(dev
, "Failed to add component: %d\n", ret
);
744 static int mtk_dpi_remove(struct platform_device
*pdev
)
746 component_del(&pdev
->dev
, &mtk_dpi_component_ops
);
751 static const struct of_device_id mtk_dpi_of_ids
[] = {
752 { .compatible
= "mediatek,mt8173-dpi", },
756 struct platform_driver mtk_dpi_driver
= {
757 .probe
= mtk_dpi_probe
,
758 .remove
= mtk_dpi_remove
,
760 .name
= "mediatek-dpi",
761 .of_match_table
= mtk_dpi_of_ids
,