1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2014 MediaTek Inc.
4 * Author: Jie Qiu <jie.qiu@mediatek.com>
8 #include <linux/component.h>
9 #include <linux/interrupt.h>
10 #include <linux/kernel.h>
12 #include <linux/of_device.h>
13 #include <linux/of_graph.h>
14 #include <linux/platform_device.h>
15 #include <linux/types.h>
17 #include <video/videomode.h>
19 #include <drm/drm_atomic_helper.h>
20 #include <drm/drm_bridge.h>
21 #include <drm/drm_crtc.h>
22 #include <drm/drm_of.h>
24 #include "mtk_dpi_regs.h"
25 #include "mtk_drm_ddp_comp.h"
27 enum mtk_dpi_out_bit_num
{
28 MTK_DPI_OUT_BIT_NUM_8BITS
,
29 MTK_DPI_OUT_BIT_NUM_10BITS
,
30 MTK_DPI_OUT_BIT_NUM_12BITS
,
31 MTK_DPI_OUT_BIT_NUM_16BITS
34 enum mtk_dpi_out_yc_map
{
35 MTK_DPI_OUT_YC_MAP_RGB
,
36 MTK_DPI_OUT_YC_MAP_CYCY
,
37 MTK_DPI_OUT_YC_MAP_YCYC
,
38 MTK_DPI_OUT_YC_MAP_CY
,
42 enum mtk_dpi_out_channel_swap
{
43 MTK_DPI_OUT_CHANNEL_SWAP_RGB
,
44 MTK_DPI_OUT_CHANNEL_SWAP_GBR
,
45 MTK_DPI_OUT_CHANNEL_SWAP_BRG
,
46 MTK_DPI_OUT_CHANNEL_SWAP_RBG
,
47 MTK_DPI_OUT_CHANNEL_SWAP_GRB
,
48 MTK_DPI_OUT_CHANNEL_SWAP_BGR
51 enum mtk_dpi_out_color_format
{
52 MTK_DPI_COLOR_FORMAT_RGB
,
53 MTK_DPI_COLOR_FORMAT_RGB_FULL
,
54 MTK_DPI_COLOR_FORMAT_YCBCR_444
,
55 MTK_DPI_COLOR_FORMAT_YCBCR_422
,
56 MTK_DPI_COLOR_FORMAT_XV_YCC
,
57 MTK_DPI_COLOR_FORMAT_YCBCR_444_FULL
,
58 MTK_DPI_COLOR_FORMAT_YCBCR_422_FULL
62 struct mtk_ddp_comp ddp_comp
;
63 struct drm_encoder encoder
;
64 struct drm_bridge
*bridge
;
67 struct clk
*engine_clk
;
68 struct clk
*pixel_clk
;
71 struct drm_display_mode mode
;
72 const struct mtk_dpi_conf
*conf
;
73 enum mtk_dpi_out_color_format color_format
;
74 enum mtk_dpi_out_yc_map yc_map
;
75 enum mtk_dpi_out_bit_num bit_num
;
76 enum mtk_dpi_out_channel_swap channel_swap
;
80 static inline struct mtk_dpi
*mtk_dpi_from_encoder(struct drm_encoder
*e
)
82 return container_of(e
, struct mtk_dpi
, encoder
);
85 enum mtk_dpi_polarity
{
86 MTK_DPI_POLARITY_RISING
,
87 MTK_DPI_POLARITY_FALLING
,
90 struct mtk_dpi_polarities
{
91 enum mtk_dpi_polarity de_pol
;
92 enum mtk_dpi_polarity ck_pol
;
93 enum mtk_dpi_polarity hsync_pol
;
94 enum mtk_dpi_polarity vsync_pol
;
97 struct mtk_dpi_sync_param
{
101 bool shift_half_line
;
104 struct mtk_dpi_yc_limit
{
111 struct mtk_dpi_conf
{
112 unsigned int (*cal_factor
)(int clock
);
117 static void mtk_dpi_mask(struct mtk_dpi
*dpi
, u32 offset
, u32 val
, u32 mask
)
119 u32 tmp
= readl(dpi
->regs
+ offset
) & ~mask
;
122 writel(tmp
, dpi
->regs
+ offset
);
125 static void mtk_dpi_sw_reset(struct mtk_dpi
*dpi
, bool reset
)
127 mtk_dpi_mask(dpi
, DPI_RET
, reset
? RST
: 0, RST
);
130 static void mtk_dpi_enable(struct mtk_dpi
*dpi
)
132 mtk_dpi_mask(dpi
, DPI_EN
, EN
, EN
);
135 static void mtk_dpi_disable(struct mtk_dpi
*dpi
)
137 mtk_dpi_mask(dpi
, DPI_EN
, 0, EN
);
140 static void mtk_dpi_config_hsync(struct mtk_dpi
*dpi
,
141 struct mtk_dpi_sync_param
*sync
)
143 mtk_dpi_mask(dpi
, DPI_TGEN_HWIDTH
,
144 sync
->sync_width
<< HPW
, HPW_MASK
);
145 mtk_dpi_mask(dpi
, DPI_TGEN_HPORCH
,
146 sync
->back_porch
<< HBP
, HBP_MASK
);
147 mtk_dpi_mask(dpi
, DPI_TGEN_HPORCH
, sync
->front_porch
<< HFP
,
151 static void mtk_dpi_config_vsync(struct mtk_dpi
*dpi
,
152 struct mtk_dpi_sync_param
*sync
,
153 u32 width_addr
, u32 porch_addr
)
155 mtk_dpi_mask(dpi
, width_addr
,
156 sync
->sync_width
<< VSYNC_WIDTH_SHIFT
,
158 mtk_dpi_mask(dpi
, width_addr
,
159 sync
->shift_half_line
<< VSYNC_HALF_LINE_SHIFT
,
160 VSYNC_HALF_LINE_MASK
);
161 mtk_dpi_mask(dpi
, porch_addr
,
162 sync
->back_porch
<< VSYNC_BACK_PORCH_SHIFT
,
163 VSYNC_BACK_PORCH_MASK
);
164 mtk_dpi_mask(dpi
, porch_addr
,
165 sync
->front_porch
<< VSYNC_FRONT_PORCH_SHIFT
,
166 VSYNC_FRONT_PORCH_MASK
);
169 static void mtk_dpi_config_vsync_lodd(struct mtk_dpi
*dpi
,
170 struct mtk_dpi_sync_param
*sync
)
172 mtk_dpi_config_vsync(dpi
, sync
, DPI_TGEN_VWIDTH
, DPI_TGEN_VPORCH
);
175 static void mtk_dpi_config_vsync_leven(struct mtk_dpi
*dpi
,
176 struct mtk_dpi_sync_param
*sync
)
178 mtk_dpi_config_vsync(dpi
, sync
, DPI_TGEN_VWIDTH_LEVEN
,
179 DPI_TGEN_VPORCH_LEVEN
);
182 static void mtk_dpi_config_vsync_rodd(struct mtk_dpi
*dpi
,
183 struct mtk_dpi_sync_param
*sync
)
185 mtk_dpi_config_vsync(dpi
, sync
, DPI_TGEN_VWIDTH_RODD
,
186 DPI_TGEN_VPORCH_RODD
);
189 static void mtk_dpi_config_vsync_reven(struct mtk_dpi
*dpi
,
190 struct mtk_dpi_sync_param
*sync
)
192 mtk_dpi_config_vsync(dpi
, sync
, DPI_TGEN_VWIDTH_REVEN
,
193 DPI_TGEN_VPORCH_REVEN
);
196 static void mtk_dpi_config_pol(struct mtk_dpi
*dpi
,
197 struct mtk_dpi_polarities
*dpi_pol
)
201 pol
= (dpi_pol
->ck_pol
== MTK_DPI_POLARITY_RISING
? 0 : CK_POL
) |
202 (dpi_pol
->de_pol
== MTK_DPI_POLARITY_RISING
? 0 : DE_POL
) |
203 (dpi_pol
->hsync_pol
== MTK_DPI_POLARITY_RISING
? 0 : HSYNC_POL
) |
204 (dpi_pol
->vsync_pol
== MTK_DPI_POLARITY_RISING
? 0 : VSYNC_POL
);
205 mtk_dpi_mask(dpi
, DPI_OUTPUT_SETTING
, pol
,
206 CK_POL
| DE_POL
| HSYNC_POL
| VSYNC_POL
);
209 static void mtk_dpi_config_3d(struct mtk_dpi
*dpi
, bool en_3d
)
211 mtk_dpi_mask(dpi
, DPI_CON
, en_3d
? TDFP_EN
: 0, TDFP_EN
);
214 static void mtk_dpi_config_interface(struct mtk_dpi
*dpi
, bool inter
)
216 mtk_dpi_mask(dpi
, DPI_CON
, inter
? INTL_EN
: 0, INTL_EN
);
219 static void mtk_dpi_config_fb_size(struct mtk_dpi
*dpi
, u32 width
, u32 height
)
221 mtk_dpi_mask(dpi
, DPI_SIZE
, width
<< HSIZE
, HSIZE_MASK
);
222 mtk_dpi_mask(dpi
, DPI_SIZE
, height
<< VSIZE
, VSIZE_MASK
);
225 static void mtk_dpi_config_channel_limit(struct mtk_dpi
*dpi
,
226 struct mtk_dpi_yc_limit
*limit
)
228 mtk_dpi_mask(dpi
, DPI_Y_LIMIT
, limit
->y_bottom
<< Y_LIMINT_BOT
,
230 mtk_dpi_mask(dpi
, DPI_Y_LIMIT
, limit
->y_top
<< Y_LIMINT_TOP
,
232 mtk_dpi_mask(dpi
, DPI_C_LIMIT
, limit
->c_bottom
<< C_LIMIT_BOT
,
234 mtk_dpi_mask(dpi
, DPI_C_LIMIT
, limit
->c_top
<< C_LIMIT_TOP
,
238 static void mtk_dpi_config_bit_num(struct mtk_dpi
*dpi
,
239 enum mtk_dpi_out_bit_num num
)
244 case MTK_DPI_OUT_BIT_NUM_8BITS
:
247 case MTK_DPI_OUT_BIT_NUM_10BITS
:
250 case MTK_DPI_OUT_BIT_NUM_12BITS
:
253 case MTK_DPI_OUT_BIT_NUM_16BITS
:
260 mtk_dpi_mask(dpi
, DPI_OUTPUT_SETTING
, val
<< OUT_BIT
,
264 static void mtk_dpi_config_yc_map(struct mtk_dpi
*dpi
,
265 enum mtk_dpi_out_yc_map map
)
270 case MTK_DPI_OUT_YC_MAP_RGB
:
273 case MTK_DPI_OUT_YC_MAP_CYCY
:
276 case MTK_DPI_OUT_YC_MAP_YCYC
:
279 case MTK_DPI_OUT_YC_MAP_CY
:
282 case MTK_DPI_OUT_YC_MAP_YC
:
290 mtk_dpi_mask(dpi
, DPI_OUTPUT_SETTING
, val
<< YC_MAP
, YC_MAP_MASK
);
293 static void mtk_dpi_config_channel_swap(struct mtk_dpi
*dpi
,
294 enum mtk_dpi_out_channel_swap swap
)
299 case MTK_DPI_OUT_CHANNEL_SWAP_RGB
:
302 case MTK_DPI_OUT_CHANNEL_SWAP_GBR
:
305 case MTK_DPI_OUT_CHANNEL_SWAP_BRG
:
308 case MTK_DPI_OUT_CHANNEL_SWAP_RBG
:
311 case MTK_DPI_OUT_CHANNEL_SWAP_GRB
:
314 case MTK_DPI_OUT_CHANNEL_SWAP_BGR
:
322 mtk_dpi_mask(dpi
, DPI_OUTPUT_SETTING
, val
<< CH_SWAP
, CH_SWAP_MASK
);
325 static void mtk_dpi_config_yuv422_enable(struct mtk_dpi
*dpi
, bool enable
)
327 mtk_dpi_mask(dpi
, DPI_CON
, enable
? YUV422_EN
: 0, YUV422_EN
);
330 static void mtk_dpi_config_csc_enable(struct mtk_dpi
*dpi
, bool enable
)
332 mtk_dpi_mask(dpi
, DPI_CON
, enable
? CSC_ENABLE
: 0, CSC_ENABLE
);
335 static void mtk_dpi_config_swap_input(struct mtk_dpi
*dpi
, bool enable
)
337 mtk_dpi_mask(dpi
, DPI_CON
, enable
? IN_RB_SWAP
: 0, IN_RB_SWAP
);
340 static void mtk_dpi_config_2n_h_fre(struct mtk_dpi
*dpi
)
342 mtk_dpi_mask(dpi
, dpi
->conf
->reg_h_fre_con
, H_FRE_2N
, H_FRE_2N
);
345 static void mtk_dpi_config_disable_edge(struct mtk_dpi
*dpi
)
347 if (dpi
->conf
->edge_sel_en
)
348 mtk_dpi_mask(dpi
, dpi
->conf
->reg_h_fre_con
, 0, EDGE_SEL_EN
);
351 static void mtk_dpi_config_color_format(struct mtk_dpi
*dpi
,
352 enum mtk_dpi_out_color_format format
)
354 if ((format
== MTK_DPI_COLOR_FORMAT_YCBCR_444
) ||
355 (format
== MTK_DPI_COLOR_FORMAT_YCBCR_444_FULL
)) {
356 mtk_dpi_config_yuv422_enable(dpi
, false);
357 mtk_dpi_config_csc_enable(dpi
, true);
358 mtk_dpi_config_swap_input(dpi
, false);
359 mtk_dpi_config_channel_swap(dpi
, MTK_DPI_OUT_CHANNEL_SWAP_BGR
);
360 } else if ((format
== MTK_DPI_COLOR_FORMAT_YCBCR_422
) ||
361 (format
== MTK_DPI_COLOR_FORMAT_YCBCR_422_FULL
)) {
362 mtk_dpi_config_yuv422_enable(dpi
, true);
363 mtk_dpi_config_csc_enable(dpi
, true);
364 mtk_dpi_config_swap_input(dpi
, true);
365 mtk_dpi_config_channel_swap(dpi
, MTK_DPI_OUT_CHANNEL_SWAP_RGB
);
367 mtk_dpi_config_yuv422_enable(dpi
, false);
368 mtk_dpi_config_csc_enable(dpi
, false);
369 mtk_dpi_config_swap_input(dpi
, false);
370 mtk_dpi_config_channel_swap(dpi
, MTK_DPI_OUT_CHANNEL_SWAP_RGB
);
374 static void mtk_dpi_power_off(struct mtk_dpi
*dpi
)
376 if (WARN_ON(dpi
->refcount
== 0))
379 if (--dpi
->refcount
!= 0)
382 mtk_dpi_disable(dpi
);
383 clk_disable_unprepare(dpi
->pixel_clk
);
384 clk_disable_unprepare(dpi
->engine_clk
);
387 static int mtk_dpi_power_on(struct mtk_dpi
*dpi
)
391 if (++dpi
->refcount
!= 1)
394 ret
= clk_prepare_enable(dpi
->engine_clk
);
396 dev_err(dpi
->dev
, "Failed to enable engine clock: %d\n", ret
);
400 ret
= clk_prepare_enable(dpi
->pixel_clk
);
402 dev_err(dpi
->dev
, "Failed to enable pixel clock: %d\n", ret
);
410 clk_disable_unprepare(dpi
->engine_clk
);
416 static int mtk_dpi_set_display_mode(struct mtk_dpi
*dpi
,
417 struct drm_display_mode
*mode
)
419 struct mtk_dpi_yc_limit limit
;
420 struct mtk_dpi_polarities dpi_pol
;
421 struct mtk_dpi_sync_param hsync
;
422 struct mtk_dpi_sync_param vsync_lodd
= { 0 };
423 struct mtk_dpi_sync_param vsync_leven
= { 0 };
424 struct mtk_dpi_sync_param vsync_rodd
= { 0 };
425 struct mtk_dpi_sync_param vsync_reven
= { 0 };
426 struct videomode vm
= { 0 };
427 unsigned long pll_rate
;
430 /* let pll_rate can fix the valid range of tvdpll (1G~2GHz) */
431 factor
= dpi
->conf
->cal_factor(mode
->clock
);
432 drm_display_mode_to_videomode(mode
, &vm
);
433 pll_rate
= vm
.pixelclock
* factor
;
435 dev_dbg(dpi
->dev
, "Want PLL %lu Hz, pixel clock %lu Hz\n",
436 pll_rate
, vm
.pixelclock
);
438 clk_set_rate(dpi
->tvd_clk
, pll_rate
);
439 pll_rate
= clk_get_rate(dpi
->tvd_clk
);
441 vm
.pixelclock
= pll_rate
/ factor
;
442 clk_set_rate(dpi
->pixel_clk
, vm
.pixelclock
);
443 vm
.pixelclock
= clk_get_rate(dpi
->pixel_clk
);
445 dev_dbg(dpi
->dev
, "Got PLL %lu Hz, pixel clock %lu Hz\n",
446 pll_rate
, vm
.pixelclock
);
448 limit
.c_bottom
= 0x0010;
449 limit
.c_top
= 0x0FE0;
450 limit
.y_bottom
= 0x0010;
451 limit
.y_top
= 0x0FE0;
453 dpi_pol
.ck_pol
= MTK_DPI_POLARITY_FALLING
;
454 dpi_pol
.de_pol
= MTK_DPI_POLARITY_RISING
;
455 dpi_pol
.hsync_pol
= vm
.flags
& DISPLAY_FLAGS_HSYNC_HIGH
?
456 MTK_DPI_POLARITY_FALLING
: MTK_DPI_POLARITY_RISING
;
457 dpi_pol
.vsync_pol
= vm
.flags
& DISPLAY_FLAGS_VSYNC_HIGH
?
458 MTK_DPI_POLARITY_FALLING
: MTK_DPI_POLARITY_RISING
;
459 hsync
.sync_width
= vm
.hsync_len
;
460 hsync
.back_porch
= vm
.hback_porch
;
461 hsync
.front_porch
= vm
.hfront_porch
;
462 hsync
.shift_half_line
= false;
463 vsync_lodd
.sync_width
= vm
.vsync_len
;
464 vsync_lodd
.back_porch
= vm
.vback_porch
;
465 vsync_lodd
.front_porch
= vm
.vfront_porch
;
466 vsync_lodd
.shift_half_line
= false;
468 if (vm
.flags
& DISPLAY_FLAGS_INTERLACED
&&
469 mode
->flags
& DRM_MODE_FLAG_3D_MASK
) {
470 vsync_leven
= vsync_lodd
;
471 vsync_rodd
= vsync_lodd
;
472 vsync_reven
= vsync_lodd
;
473 vsync_leven
.shift_half_line
= true;
474 vsync_reven
.shift_half_line
= true;
475 } else if (vm
.flags
& DISPLAY_FLAGS_INTERLACED
&&
476 !(mode
->flags
& DRM_MODE_FLAG_3D_MASK
)) {
477 vsync_leven
= vsync_lodd
;
478 vsync_leven
.shift_half_line
= true;
479 } else if (!(vm
.flags
& DISPLAY_FLAGS_INTERLACED
) &&
480 mode
->flags
& DRM_MODE_FLAG_3D_MASK
) {
481 vsync_rodd
= vsync_lodd
;
483 mtk_dpi_sw_reset(dpi
, true);
484 mtk_dpi_config_pol(dpi
, &dpi_pol
);
486 mtk_dpi_config_hsync(dpi
, &hsync
);
487 mtk_dpi_config_vsync_lodd(dpi
, &vsync_lodd
);
488 mtk_dpi_config_vsync_rodd(dpi
, &vsync_rodd
);
489 mtk_dpi_config_vsync_leven(dpi
, &vsync_leven
);
490 mtk_dpi_config_vsync_reven(dpi
, &vsync_reven
);
492 mtk_dpi_config_3d(dpi
, !!(mode
->flags
& DRM_MODE_FLAG_3D_MASK
));
493 mtk_dpi_config_interface(dpi
, !!(vm
.flags
&
494 DISPLAY_FLAGS_INTERLACED
));
495 if (vm
.flags
& DISPLAY_FLAGS_INTERLACED
)
496 mtk_dpi_config_fb_size(dpi
, vm
.hactive
, vm
.vactive
>> 1);
498 mtk_dpi_config_fb_size(dpi
, vm
.hactive
, vm
.vactive
);
500 mtk_dpi_config_channel_limit(dpi
, &limit
);
501 mtk_dpi_config_bit_num(dpi
, dpi
->bit_num
);
502 mtk_dpi_config_channel_swap(dpi
, dpi
->channel_swap
);
503 mtk_dpi_config_yc_map(dpi
, dpi
->yc_map
);
504 mtk_dpi_config_color_format(dpi
, dpi
->color_format
);
505 mtk_dpi_config_2n_h_fre(dpi
);
506 mtk_dpi_config_disable_edge(dpi
);
507 mtk_dpi_sw_reset(dpi
, false);
512 static void mtk_dpi_encoder_destroy(struct drm_encoder
*encoder
)
514 drm_encoder_cleanup(encoder
);
517 static const struct drm_encoder_funcs mtk_dpi_encoder_funcs
= {
518 .destroy
= mtk_dpi_encoder_destroy
,
521 static bool mtk_dpi_encoder_mode_fixup(struct drm_encoder
*encoder
,
522 const struct drm_display_mode
*mode
,
523 struct drm_display_mode
*adjusted_mode
)
528 static void mtk_dpi_encoder_mode_set(struct drm_encoder
*encoder
,
529 struct drm_display_mode
*mode
,
530 struct drm_display_mode
*adjusted_mode
)
532 struct mtk_dpi
*dpi
= mtk_dpi_from_encoder(encoder
);
534 drm_mode_copy(&dpi
->mode
, adjusted_mode
);
537 static void mtk_dpi_encoder_disable(struct drm_encoder
*encoder
)
539 struct mtk_dpi
*dpi
= mtk_dpi_from_encoder(encoder
);
541 mtk_dpi_power_off(dpi
);
544 static void mtk_dpi_encoder_enable(struct drm_encoder
*encoder
)
546 struct mtk_dpi
*dpi
= mtk_dpi_from_encoder(encoder
);
548 mtk_dpi_power_on(dpi
);
549 mtk_dpi_set_display_mode(dpi
, &dpi
->mode
);
552 static int mtk_dpi_atomic_check(struct drm_encoder
*encoder
,
553 struct drm_crtc_state
*crtc_state
,
554 struct drm_connector_state
*conn_state
)
559 static const struct drm_encoder_helper_funcs mtk_dpi_encoder_helper_funcs
= {
560 .mode_fixup
= mtk_dpi_encoder_mode_fixup
,
561 .mode_set
= mtk_dpi_encoder_mode_set
,
562 .disable
= mtk_dpi_encoder_disable
,
563 .enable
= mtk_dpi_encoder_enable
,
564 .atomic_check
= mtk_dpi_atomic_check
,
567 static void mtk_dpi_start(struct mtk_ddp_comp
*comp
)
569 struct mtk_dpi
*dpi
= container_of(comp
, struct mtk_dpi
, ddp_comp
);
571 mtk_dpi_power_on(dpi
);
574 static void mtk_dpi_stop(struct mtk_ddp_comp
*comp
)
576 struct mtk_dpi
*dpi
= container_of(comp
, struct mtk_dpi
, ddp_comp
);
578 mtk_dpi_power_off(dpi
);
581 static const struct mtk_ddp_comp_funcs mtk_dpi_funcs
= {
582 .start
= mtk_dpi_start
,
583 .stop
= mtk_dpi_stop
,
586 static int mtk_dpi_bind(struct device
*dev
, struct device
*master
, void *data
)
588 struct mtk_dpi
*dpi
= dev_get_drvdata(dev
);
589 struct drm_device
*drm_dev
= data
;
592 ret
= mtk_ddp_comp_register(drm_dev
, &dpi
->ddp_comp
);
594 dev_err(dev
, "Failed to register component %pOF: %d\n",
599 ret
= drm_encoder_init(drm_dev
, &dpi
->encoder
, &mtk_dpi_encoder_funcs
,
600 DRM_MODE_ENCODER_TMDS
, NULL
);
602 dev_err(dev
, "Failed to initialize decoder: %d\n", ret
);
605 drm_encoder_helper_add(&dpi
->encoder
, &mtk_dpi_encoder_helper_funcs
);
607 /* Currently DPI0 is fixed to be driven by OVL1 */
608 dpi
->encoder
.possible_crtcs
= BIT(1);
610 ret
= drm_bridge_attach(&dpi
->encoder
, dpi
->bridge
, NULL
);
612 dev_err(dev
, "Failed to attach bridge: %d\n", ret
);
616 dpi
->bit_num
= MTK_DPI_OUT_BIT_NUM_8BITS
;
617 dpi
->channel_swap
= MTK_DPI_OUT_CHANNEL_SWAP_RGB
;
618 dpi
->yc_map
= MTK_DPI_OUT_YC_MAP_RGB
;
619 dpi
->color_format
= MTK_DPI_COLOR_FORMAT_RGB
;
624 drm_encoder_cleanup(&dpi
->encoder
);
626 mtk_ddp_comp_unregister(drm_dev
, &dpi
->ddp_comp
);
630 static void mtk_dpi_unbind(struct device
*dev
, struct device
*master
,
633 struct mtk_dpi
*dpi
= dev_get_drvdata(dev
);
634 struct drm_device
*drm_dev
= data
;
636 drm_encoder_cleanup(&dpi
->encoder
);
637 mtk_ddp_comp_unregister(drm_dev
, &dpi
->ddp_comp
);
640 static const struct component_ops mtk_dpi_component_ops
= {
641 .bind
= mtk_dpi_bind
,
642 .unbind
= mtk_dpi_unbind
,
645 static unsigned int mt8173_calculate_factor(int clock
)
649 else if (clock
<= 84000)
651 else if (clock
<= 167000)
657 static unsigned int mt2701_calculate_factor(int clock
)
661 else if (clock
<= 128000)
667 static const struct mtk_dpi_conf mt8173_conf
= {
668 .cal_factor
= mt8173_calculate_factor
,
669 .reg_h_fre_con
= 0xe0,
672 static const struct mtk_dpi_conf mt2701_conf
= {
673 .cal_factor
= mt2701_calculate_factor
,
674 .reg_h_fre_con
= 0xb0,
678 static int mtk_dpi_probe(struct platform_device
*pdev
)
680 struct device
*dev
= &pdev
->dev
;
682 struct resource
*mem
;
686 dpi
= devm_kzalloc(dev
, sizeof(*dpi
), GFP_KERNEL
);
691 dpi
->conf
= (struct mtk_dpi_conf
*)of_device_get_match_data(dev
);
693 mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
694 dpi
->regs
= devm_ioremap_resource(dev
, mem
);
695 if (IS_ERR(dpi
->regs
)) {
696 ret
= PTR_ERR(dpi
->regs
);
697 dev_err(dev
, "Failed to ioremap mem resource: %d\n", ret
);
701 dpi
->engine_clk
= devm_clk_get(dev
, "engine");
702 if (IS_ERR(dpi
->engine_clk
)) {
703 ret
= PTR_ERR(dpi
->engine_clk
);
704 dev_err(dev
, "Failed to get engine clock: %d\n", ret
);
708 dpi
->pixel_clk
= devm_clk_get(dev
, "pixel");
709 if (IS_ERR(dpi
->pixel_clk
)) {
710 ret
= PTR_ERR(dpi
->pixel_clk
);
711 dev_err(dev
, "Failed to get pixel clock: %d\n", ret
);
715 dpi
->tvd_clk
= devm_clk_get(dev
, "pll");
716 if (IS_ERR(dpi
->tvd_clk
)) {
717 ret
= PTR_ERR(dpi
->tvd_clk
);
718 dev_err(dev
, "Failed to get tvdpll clock: %d\n", ret
);
722 dpi
->irq
= platform_get_irq(pdev
, 0);
724 dev_err(dev
, "Failed to get irq: %d\n", dpi
->irq
);
728 ret
= drm_of_find_panel_or_bridge(dev
->of_node
, 0, 0,
733 dev_info(dev
, "Found bridge node: %pOF\n", dpi
->bridge
->of_node
);
735 comp_id
= mtk_ddp_comp_get_id(dev
->of_node
, MTK_DPI
);
737 dev_err(dev
, "Failed to identify by alias: %d\n", comp_id
);
741 ret
= mtk_ddp_comp_init(dev
, dev
->of_node
, &dpi
->ddp_comp
, comp_id
,
744 dev_err(dev
, "Failed to initialize component: %d\n", ret
);
748 platform_set_drvdata(pdev
, dpi
);
750 ret
= component_add(dev
, &mtk_dpi_component_ops
);
752 dev_err(dev
, "Failed to add component: %d\n", ret
);
759 static int mtk_dpi_remove(struct platform_device
*pdev
)
761 component_del(&pdev
->dev
, &mtk_dpi_component_ops
);
766 static const struct of_device_id mtk_dpi_of_ids
[] = {
767 { .compatible
= "mediatek,mt2701-dpi",
768 .data
= &mt2701_conf
,
770 { .compatible
= "mediatek,mt8173-dpi",
771 .data
= &mt8173_conf
,
776 struct platform_driver mtk_dpi_driver
= {
777 .probe
= mtk_dpi_probe
,
778 .remove
= mtk_dpi_remove
,
780 .name
= "mediatek-dpi",
781 .of_match_table
= mtk_dpi_of_ids
,