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_atomic_helper.h>
17 #include <drm/drm_of.h>
18 #include <linux/kernel.h>
19 #include <linux/component.h>
20 #include <linux/platform_device.h>
22 #include <linux/of_device.h>
23 #include <linux/of_graph.h>
24 #include <linux/interrupt.h>
25 #include <linux/types.h>
26 #include <linux/clk.h>
27 #include <video/videomode.h>
29 #include "mtk_dpi_regs.h"
30 #include "mtk_drm_ddp_comp.h"
32 enum mtk_dpi_out_bit_num
{
33 MTK_DPI_OUT_BIT_NUM_8BITS
,
34 MTK_DPI_OUT_BIT_NUM_10BITS
,
35 MTK_DPI_OUT_BIT_NUM_12BITS
,
36 MTK_DPI_OUT_BIT_NUM_16BITS
39 enum mtk_dpi_out_yc_map
{
40 MTK_DPI_OUT_YC_MAP_RGB
,
41 MTK_DPI_OUT_YC_MAP_CYCY
,
42 MTK_DPI_OUT_YC_MAP_YCYC
,
43 MTK_DPI_OUT_YC_MAP_CY
,
47 enum mtk_dpi_out_channel_swap
{
48 MTK_DPI_OUT_CHANNEL_SWAP_RGB
,
49 MTK_DPI_OUT_CHANNEL_SWAP_GBR
,
50 MTK_DPI_OUT_CHANNEL_SWAP_BRG
,
51 MTK_DPI_OUT_CHANNEL_SWAP_RBG
,
52 MTK_DPI_OUT_CHANNEL_SWAP_GRB
,
53 MTK_DPI_OUT_CHANNEL_SWAP_BGR
56 enum mtk_dpi_out_color_format
{
57 MTK_DPI_COLOR_FORMAT_RGB
,
58 MTK_DPI_COLOR_FORMAT_RGB_FULL
,
59 MTK_DPI_COLOR_FORMAT_YCBCR_444
,
60 MTK_DPI_COLOR_FORMAT_YCBCR_422
,
61 MTK_DPI_COLOR_FORMAT_XV_YCC
,
62 MTK_DPI_COLOR_FORMAT_YCBCR_444_FULL
,
63 MTK_DPI_COLOR_FORMAT_YCBCR_422_FULL
67 struct mtk_ddp_comp ddp_comp
;
68 struct drm_encoder encoder
;
69 struct drm_bridge
*bridge
;
72 struct clk
*engine_clk
;
73 struct clk
*pixel_clk
;
76 struct drm_display_mode mode
;
77 const struct mtk_dpi_conf
*conf
;
78 enum mtk_dpi_out_color_format color_format
;
79 enum mtk_dpi_out_yc_map yc_map
;
80 enum mtk_dpi_out_bit_num bit_num
;
81 enum mtk_dpi_out_channel_swap channel_swap
;
85 static inline struct mtk_dpi
*mtk_dpi_from_encoder(struct drm_encoder
*e
)
87 return container_of(e
, struct mtk_dpi
, encoder
);
90 enum mtk_dpi_polarity
{
91 MTK_DPI_POLARITY_RISING
,
92 MTK_DPI_POLARITY_FALLING
,
95 struct mtk_dpi_polarities
{
96 enum mtk_dpi_polarity de_pol
;
97 enum mtk_dpi_polarity ck_pol
;
98 enum mtk_dpi_polarity hsync_pol
;
99 enum mtk_dpi_polarity vsync_pol
;
102 struct mtk_dpi_sync_param
{
106 bool shift_half_line
;
109 struct mtk_dpi_yc_limit
{
116 struct mtk_dpi_conf
{
117 unsigned int (*cal_factor
)(int clock
);
122 static void mtk_dpi_mask(struct mtk_dpi
*dpi
, u32 offset
, u32 val
, u32 mask
)
124 u32 tmp
= readl(dpi
->regs
+ offset
) & ~mask
;
127 writel(tmp
, dpi
->regs
+ offset
);
130 static void mtk_dpi_sw_reset(struct mtk_dpi
*dpi
, bool reset
)
132 mtk_dpi_mask(dpi
, DPI_RET
, reset
? RST
: 0, RST
);
135 static void mtk_dpi_enable(struct mtk_dpi
*dpi
)
137 mtk_dpi_mask(dpi
, DPI_EN
, EN
, EN
);
140 static void mtk_dpi_disable(struct mtk_dpi
*dpi
)
142 mtk_dpi_mask(dpi
, DPI_EN
, 0, EN
);
145 static void mtk_dpi_config_hsync(struct mtk_dpi
*dpi
,
146 struct mtk_dpi_sync_param
*sync
)
148 mtk_dpi_mask(dpi
, DPI_TGEN_HWIDTH
,
149 sync
->sync_width
<< HPW
, HPW_MASK
);
150 mtk_dpi_mask(dpi
, DPI_TGEN_HPORCH
,
151 sync
->back_porch
<< HBP
, HBP_MASK
);
152 mtk_dpi_mask(dpi
, DPI_TGEN_HPORCH
, sync
->front_porch
<< HFP
,
156 static void mtk_dpi_config_vsync(struct mtk_dpi
*dpi
,
157 struct mtk_dpi_sync_param
*sync
,
158 u32 width_addr
, u32 porch_addr
)
160 mtk_dpi_mask(dpi
, width_addr
,
161 sync
->sync_width
<< VSYNC_WIDTH_SHIFT
,
163 mtk_dpi_mask(dpi
, width_addr
,
164 sync
->shift_half_line
<< VSYNC_HALF_LINE_SHIFT
,
165 VSYNC_HALF_LINE_MASK
);
166 mtk_dpi_mask(dpi
, porch_addr
,
167 sync
->back_porch
<< VSYNC_BACK_PORCH_SHIFT
,
168 VSYNC_BACK_PORCH_MASK
);
169 mtk_dpi_mask(dpi
, porch_addr
,
170 sync
->front_porch
<< VSYNC_FRONT_PORCH_SHIFT
,
171 VSYNC_FRONT_PORCH_MASK
);
174 static void mtk_dpi_config_vsync_lodd(struct mtk_dpi
*dpi
,
175 struct mtk_dpi_sync_param
*sync
)
177 mtk_dpi_config_vsync(dpi
, sync
, DPI_TGEN_VWIDTH
, DPI_TGEN_VPORCH
);
180 static void mtk_dpi_config_vsync_leven(struct mtk_dpi
*dpi
,
181 struct mtk_dpi_sync_param
*sync
)
183 mtk_dpi_config_vsync(dpi
, sync
, DPI_TGEN_VWIDTH_LEVEN
,
184 DPI_TGEN_VPORCH_LEVEN
);
187 static void mtk_dpi_config_vsync_rodd(struct mtk_dpi
*dpi
,
188 struct mtk_dpi_sync_param
*sync
)
190 mtk_dpi_config_vsync(dpi
, sync
, DPI_TGEN_VWIDTH_RODD
,
191 DPI_TGEN_VPORCH_RODD
);
194 static void mtk_dpi_config_vsync_reven(struct mtk_dpi
*dpi
,
195 struct mtk_dpi_sync_param
*sync
)
197 mtk_dpi_config_vsync(dpi
, sync
, DPI_TGEN_VWIDTH_REVEN
,
198 DPI_TGEN_VPORCH_REVEN
);
201 static void mtk_dpi_config_pol(struct mtk_dpi
*dpi
,
202 struct mtk_dpi_polarities
*dpi_pol
)
206 pol
= (dpi_pol
->ck_pol
== MTK_DPI_POLARITY_RISING
? 0 : CK_POL
) |
207 (dpi_pol
->de_pol
== MTK_DPI_POLARITY_RISING
? 0 : DE_POL
) |
208 (dpi_pol
->hsync_pol
== MTK_DPI_POLARITY_RISING
? 0 : HSYNC_POL
) |
209 (dpi_pol
->vsync_pol
== MTK_DPI_POLARITY_RISING
? 0 : VSYNC_POL
);
210 mtk_dpi_mask(dpi
, DPI_OUTPUT_SETTING
, pol
,
211 CK_POL
| DE_POL
| HSYNC_POL
| VSYNC_POL
);
214 static void mtk_dpi_config_3d(struct mtk_dpi
*dpi
, bool en_3d
)
216 mtk_dpi_mask(dpi
, DPI_CON
, en_3d
? TDFP_EN
: 0, TDFP_EN
);
219 static void mtk_dpi_config_interface(struct mtk_dpi
*dpi
, bool inter
)
221 mtk_dpi_mask(dpi
, DPI_CON
, inter
? INTL_EN
: 0, INTL_EN
);
224 static void mtk_dpi_config_fb_size(struct mtk_dpi
*dpi
, u32 width
, u32 height
)
226 mtk_dpi_mask(dpi
, DPI_SIZE
, width
<< HSIZE
, HSIZE_MASK
);
227 mtk_dpi_mask(dpi
, DPI_SIZE
, height
<< VSIZE
, VSIZE_MASK
);
230 static void mtk_dpi_config_channel_limit(struct mtk_dpi
*dpi
,
231 struct mtk_dpi_yc_limit
*limit
)
233 mtk_dpi_mask(dpi
, DPI_Y_LIMIT
, limit
->y_bottom
<< Y_LIMINT_BOT
,
235 mtk_dpi_mask(dpi
, DPI_Y_LIMIT
, limit
->y_top
<< Y_LIMINT_TOP
,
237 mtk_dpi_mask(dpi
, DPI_C_LIMIT
, limit
->c_bottom
<< C_LIMIT_BOT
,
239 mtk_dpi_mask(dpi
, DPI_C_LIMIT
, limit
->c_top
<< C_LIMIT_TOP
,
243 static void mtk_dpi_config_bit_num(struct mtk_dpi
*dpi
,
244 enum mtk_dpi_out_bit_num num
)
249 case MTK_DPI_OUT_BIT_NUM_8BITS
:
252 case MTK_DPI_OUT_BIT_NUM_10BITS
:
255 case MTK_DPI_OUT_BIT_NUM_12BITS
:
258 case MTK_DPI_OUT_BIT_NUM_16BITS
:
265 mtk_dpi_mask(dpi
, DPI_OUTPUT_SETTING
, val
<< OUT_BIT
,
269 static void mtk_dpi_config_yc_map(struct mtk_dpi
*dpi
,
270 enum mtk_dpi_out_yc_map map
)
275 case MTK_DPI_OUT_YC_MAP_RGB
:
278 case MTK_DPI_OUT_YC_MAP_CYCY
:
281 case MTK_DPI_OUT_YC_MAP_YCYC
:
284 case MTK_DPI_OUT_YC_MAP_CY
:
287 case MTK_DPI_OUT_YC_MAP_YC
:
295 mtk_dpi_mask(dpi
, DPI_OUTPUT_SETTING
, val
<< YC_MAP
, YC_MAP_MASK
);
298 static void mtk_dpi_config_channel_swap(struct mtk_dpi
*dpi
,
299 enum mtk_dpi_out_channel_swap swap
)
304 case MTK_DPI_OUT_CHANNEL_SWAP_RGB
:
307 case MTK_DPI_OUT_CHANNEL_SWAP_GBR
:
310 case MTK_DPI_OUT_CHANNEL_SWAP_BRG
:
313 case MTK_DPI_OUT_CHANNEL_SWAP_RBG
:
316 case MTK_DPI_OUT_CHANNEL_SWAP_GRB
:
319 case MTK_DPI_OUT_CHANNEL_SWAP_BGR
:
327 mtk_dpi_mask(dpi
, DPI_OUTPUT_SETTING
, val
<< CH_SWAP
, CH_SWAP_MASK
);
330 static void mtk_dpi_config_yuv422_enable(struct mtk_dpi
*dpi
, bool enable
)
332 mtk_dpi_mask(dpi
, DPI_CON
, enable
? YUV422_EN
: 0, YUV422_EN
);
335 static void mtk_dpi_config_csc_enable(struct mtk_dpi
*dpi
, bool enable
)
337 mtk_dpi_mask(dpi
, DPI_CON
, enable
? CSC_ENABLE
: 0, CSC_ENABLE
);
340 static void mtk_dpi_config_swap_input(struct mtk_dpi
*dpi
, bool enable
)
342 mtk_dpi_mask(dpi
, DPI_CON
, enable
? IN_RB_SWAP
: 0, IN_RB_SWAP
);
345 static void mtk_dpi_config_2n_h_fre(struct mtk_dpi
*dpi
)
347 mtk_dpi_mask(dpi
, dpi
->conf
->reg_h_fre_con
, H_FRE_2N
, H_FRE_2N
);
350 static void mtk_dpi_config_disable_edge(struct mtk_dpi
*dpi
)
352 if (dpi
->conf
->edge_sel_en
)
353 mtk_dpi_mask(dpi
, dpi
->conf
->reg_h_fre_con
, 0, EDGE_SEL_EN
);
356 static void mtk_dpi_config_color_format(struct mtk_dpi
*dpi
,
357 enum mtk_dpi_out_color_format format
)
359 if ((format
== MTK_DPI_COLOR_FORMAT_YCBCR_444
) ||
360 (format
== MTK_DPI_COLOR_FORMAT_YCBCR_444_FULL
)) {
361 mtk_dpi_config_yuv422_enable(dpi
, false);
362 mtk_dpi_config_csc_enable(dpi
, true);
363 mtk_dpi_config_swap_input(dpi
, false);
364 mtk_dpi_config_channel_swap(dpi
, MTK_DPI_OUT_CHANNEL_SWAP_BGR
);
365 } else if ((format
== MTK_DPI_COLOR_FORMAT_YCBCR_422
) ||
366 (format
== MTK_DPI_COLOR_FORMAT_YCBCR_422_FULL
)) {
367 mtk_dpi_config_yuv422_enable(dpi
, true);
368 mtk_dpi_config_csc_enable(dpi
, true);
369 mtk_dpi_config_swap_input(dpi
, true);
370 mtk_dpi_config_channel_swap(dpi
, MTK_DPI_OUT_CHANNEL_SWAP_RGB
);
372 mtk_dpi_config_yuv422_enable(dpi
, false);
373 mtk_dpi_config_csc_enable(dpi
, false);
374 mtk_dpi_config_swap_input(dpi
, false);
375 mtk_dpi_config_channel_swap(dpi
, MTK_DPI_OUT_CHANNEL_SWAP_RGB
);
379 static void mtk_dpi_power_off(struct mtk_dpi
*dpi
)
381 if (WARN_ON(dpi
->refcount
== 0))
384 if (--dpi
->refcount
!= 0)
387 mtk_dpi_disable(dpi
);
388 clk_disable_unprepare(dpi
->pixel_clk
);
389 clk_disable_unprepare(dpi
->engine_clk
);
392 static int mtk_dpi_power_on(struct mtk_dpi
*dpi
)
396 if (++dpi
->refcount
!= 1)
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
);
415 clk_disable_unprepare(dpi
->engine_clk
);
421 static int mtk_dpi_set_display_mode(struct mtk_dpi
*dpi
,
422 struct drm_display_mode
*mode
)
424 struct mtk_dpi_yc_limit limit
;
425 struct mtk_dpi_polarities dpi_pol
;
426 struct mtk_dpi_sync_param hsync
;
427 struct mtk_dpi_sync_param vsync_lodd
= { 0 };
428 struct mtk_dpi_sync_param vsync_leven
= { 0 };
429 struct mtk_dpi_sync_param vsync_rodd
= { 0 };
430 struct mtk_dpi_sync_param vsync_reven
= { 0 };
431 struct videomode vm
= { 0 };
432 unsigned long pll_rate
;
435 /* let pll_rate can fix the valid range of tvdpll (1G~2GHz) */
436 factor
= dpi
->conf
->cal_factor(mode
->clock
);
437 drm_display_mode_to_videomode(mode
, &vm
);
438 pll_rate
= vm
.pixelclock
* factor
;
440 dev_dbg(dpi
->dev
, "Want PLL %lu Hz, pixel clock %lu Hz\n",
441 pll_rate
, vm
.pixelclock
);
443 clk_set_rate(dpi
->tvd_clk
, pll_rate
);
444 pll_rate
= clk_get_rate(dpi
->tvd_clk
);
446 vm
.pixelclock
= pll_rate
/ factor
;
447 clk_set_rate(dpi
->pixel_clk
, vm
.pixelclock
);
448 vm
.pixelclock
= clk_get_rate(dpi
->pixel_clk
);
450 dev_dbg(dpi
->dev
, "Got PLL %lu Hz, pixel clock %lu Hz\n",
451 pll_rate
, vm
.pixelclock
);
453 limit
.c_bottom
= 0x0010;
454 limit
.c_top
= 0x0FE0;
455 limit
.y_bottom
= 0x0010;
456 limit
.y_top
= 0x0FE0;
458 dpi_pol
.ck_pol
= MTK_DPI_POLARITY_FALLING
;
459 dpi_pol
.de_pol
= MTK_DPI_POLARITY_RISING
;
460 dpi_pol
.hsync_pol
= vm
.flags
& DISPLAY_FLAGS_HSYNC_HIGH
?
461 MTK_DPI_POLARITY_FALLING
: MTK_DPI_POLARITY_RISING
;
462 dpi_pol
.vsync_pol
= vm
.flags
& DISPLAY_FLAGS_VSYNC_HIGH
?
463 MTK_DPI_POLARITY_FALLING
: MTK_DPI_POLARITY_RISING
;
464 hsync
.sync_width
= vm
.hsync_len
;
465 hsync
.back_porch
= vm
.hback_porch
;
466 hsync
.front_porch
= vm
.hfront_porch
;
467 hsync
.shift_half_line
= false;
468 vsync_lodd
.sync_width
= vm
.vsync_len
;
469 vsync_lodd
.back_porch
= vm
.vback_porch
;
470 vsync_lodd
.front_porch
= vm
.vfront_porch
;
471 vsync_lodd
.shift_half_line
= false;
473 if (vm
.flags
& DISPLAY_FLAGS_INTERLACED
&&
474 mode
->flags
& DRM_MODE_FLAG_3D_MASK
) {
475 vsync_leven
= vsync_lodd
;
476 vsync_rodd
= vsync_lodd
;
477 vsync_reven
= vsync_lodd
;
478 vsync_leven
.shift_half_line
= true;
479 vsync_reven
.shift_half_line
= true;
480 } else if (vm
.flags
& DISPLAY_FLAGS_INTERLACED
&&
481 !(mode
->flags
& DRM_MODE_FLAG_3D_MASK
)) {
482 vsync_leven
= vsync_lodd
;
483 vsync_leven
.shift_half_line
= true;
484 } else if (!(vm
.flags
& DISPLAY_FLAGS_INTERLACED
) &&
485 mode
->flags
& DRM_MODE_FLAG_3D_MASK
) {
486 vsync_rodd
= vsync_lodd
;
488 mtk_dpi_sw_reset(dpi
, true);
489 mtk_dpi_config_pol(dpi
, &dpi_pol
);
491 mtk_dpi_config_hsync(dpi
, &hsync
);
492 mtk_dpi_config_vsync_lodd(dpi
, &vsync_lodd
);
493 mtk_dpi_config_vsync_rodd(dpi
, &vsync_rodd
);
494 mtk_dpi_config_vsync_leven(dpi
, &vsync_leven
);
495 mtk_dpi_config_vsync_reven(dpi
, &vsync_reven
);
497 mtk_dpi_config_3d(dpi
, !!(mode
->flags
& DRM_MODE_FLAG_3D_MASK
));
498 mtk_dpi_config_interface(dpi
, !!(vm
.flags
&
499 DISPLAY_FLAGS_INTERLACED
));
500 if (vm
.flags
& DISPLAY_FLAGS_INTERLACED
)
501 mtk_dpi_config_fb_size(dpi
, vm
.hactive
, vm
.vactive
>> 1);
503 mtk_dpi_config_fb_size(dpi
, vm
.hactive
, vm
.vactive
);
505 mtk_dpi_config_channel_limit(dpi
, &limit
);
506 mtk_dpi_config_bit_num(dpi
, dpi
->bit_num
);
507 mtk_dpi_config_channel_swap(dpi
, dpi
->channel_swap
);
508 mtk_dpi_config_yc_map(dpi
, dpi
->yc_map
);
509 mtk_dpi_config_color_format(dpi
, dpi
->color_format
);
510 mtk_dpi_config_2n_h_fre(dpi
);
511 mtk_dpi_config_disable_edge(dpi
);
512 mtk_dpi_sw_reset(dpi
, false);
517 static void mtk_dpi_encoder_destroy(struct drm_encoder
*encoder
)
519 drm_encoder_cleanup(encoder
);
522 static const struct drm_encoder_funcs mtk_dpi_encoder_funcs
= {
523 .destroy
= mtk_dpi_encoder_destroy
,
526 static bool mtk_dpi_encoder_mode_fixup(struct drm_encoder
*encoder
,
527 const struct drm_display_mode
*mode
,
528 struct drm_display_mode
*adjusted_mode
)
533 static void mtk_dpi_encoder_mode_set(struct drm_encoder
*encoder
,
534 struct drm_display_mode
*mode
,
535 struct drm_display_mode
*adjusted_mode
)
537 struct mtk_dpi
*dpi
= mtk_dpi_from_encoder(encoder
);
539 drm_mode_copy(&dpi
->mode
, adjusted_mode
);
542 static void mtk_dpi_encoder_disable(struct drm_encoder
*encoder
)
544 struct mtk_dpi
*dpi
= mtk_dpi_from_encoder(encoder
);
546 mtk_dpi_power_off(dpi
);
549 static void mtk_dpi_encoder_enable(struct drm_encoder
*encoder
)
551 struct mtk_dpi
*dpi
= mtk_dpi_from_encoder(encoder
);
553 mtk_dpi_power_on(dpi
);
554 mtk_dpi_set_display_mode(dpi
, &dpi
->mode
);
557 static int mtk_dpi_atomic_check(struct drm_encoder
*encoder
,
558 struct drm_crtc_state
*crtc_state
,
559 struct drm_connector_state
*conn_state
)
564 static const struct drm_encoder_helper_funcs mtk_dpi_encoder_helper_funcs
= {
565 .mode_fixup
= mtk_dpi_encoder_mode_fixup
,
566 .mode_set
= mtk_dpi_encoder_mode_set
,
567 .disable
= mtk_dpi_encoder_disable
,
568 .enable
= mtk_dpi_encoder_enable
,
569 .atomic_check
= mtk_dpi_atomic_check
,
572 static void mtk_dpi_start(struct mtk_ddp_comp
*comp
)
574 struct mtk_dpi
*dpi
= container_of(comp
, struct mtk_dpi
, ddp_comp
);
576 mtk_dpi_power_on(dpi
);
579 static void mtk_dpi_stop(struct mtk_ddp_comp
*comp
)
581 struct mtk_dpi
*dpi
= container_of(comp
, struct mtk_dpi
, ddp_comp
);
583 mtk_dpi_power_off(dpi
);
586 static const struct mtk_ddp_comp_funcs mtk_dpi_funcs
= {
587 .start
= mtk_dpi_start
,
588 .stop
= mtk_dpi_stop
,
591 static int mtk_dpi_bind(struct device
*dev
, struct device
*master
, void *data
)
593 struct mtk_dpi
*dpi
= dev_get_drvdata(dev
);
594 struct drm_device
*drm_dev
= data
;
597 ret
= mtk_ddp_comp_register(drm_dev
, &dpi
->ddp_comp
);
599 dev_err(dev
, "Failed to register component %pOF: %d\n",
604 ret
= drm_encoder_init(drm_dev
, &dpi
->encoder
, &mtk_dpi_encoder_funcs
,
605 DRM_MODE_ENCODER_TMDS
, NULL
);
607 dev_err(dev
, "Failed to initialize decoder: %d\n", ret
);
610 drm_encoder_helper_add(&dpi
->encoder
, &mtk_dpi_encoder_helper_funcs
);
612 /* Currently DPI0 is fixed to be driven by OVL1 */
613 dpi
->encoder
.possible_crtcs
= BIT(1);
615 ret
= drm_bridge_attach(&dpi
->encoder
, dpi
->bridge
, NULL
);
617 dev_err(dev
, "Failed to attach bridge: %d\n", ret
);
621 dpi
->bit_num
= MTK_DPI_OUT_BIT_NUM_8BITS
;
622 dpi
->channel_swap
= MTK_DPI_OUT_CHANNEL_SWAP_RGB
;
623 dpi
->yc_map
= MTK_DPI_OUT_YC_MAP_RGB
;
624 dpi
->color_format
= MTK_DPI_COLOR_FORMAT_RGB
;
629 drm_encoder_cleanup(&dpi
->encoder
);
631 mtk_ddp_comp_unregister(drm_dev
, &dpi
->ddp_comp
);
635 static void mtk_dpi_unbind(struct device
*dev
, struct device
*master
,
638 struct mtk_dpi
*dpi
= dev_get_drvdata(dev
);
639 struct drm_device
*drm_dev
= data
;
641 drm_encoder_cleanup(&dpi
->encoder
);
642 mtk_ddp_comp_unregister(drm_dev
, &dpi
->ddp_comp
);
645 static const struct component_ops mtk_dpi_component_ops
= {
646 .bind
= mtk_dpi_bind
,
647 .unbind
= mtk_dpi_unbind
,
650 static unsigned int mt8173_calculate_factor(int clock
)
654 else if (clock
<= 84000)
656 else if (clock
<= 167000)
662 static unsigned int mt2701_calculate_factor(int clock
)
666 else if (clock
<= 128000)
668 else if (clock
<= 256000)
674 static const struct mtk_dpi_conf mt8173_conf
= {
675 .cal_factor
= mt8173_calculate_factor
,
676 .reg_h_fre_con
= 0xe0,
679 static const struct mtk_dpi_conf mt2701_conf
= {
680 .cal_factor
= mt2701_calculate_factor
,
681 .reg_h_fre_con
= 0xb0,
685 static int mtk_dpi_probe(struct platform_device
*pdev
)
687 struct device
*dev
= &pdev
->dev
;
689 struct resource
*mem
;
693 dpi
= devm_kzalloc(dev
, sizeof(*dpi
), GFP_KERNEL
);
698 dpi
->conf
= (struct mtk_dpi_conf
*)of_device_get_match_data(dev
);
700 mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
701 dpi
->regs
= devm_ioremap_resource(dev
, mem
);
702 if (IS_ERR(dpi
->regs
)) {
703 ret
= PTR_ERR(dpi
->regs
);
704 dev_err(dev
, "Failed to ioremap mem resource: %d\n", ret
);
708 dpi
->engine_clk
= devm_clk_get(dev
, "engine");
709 if (IS_ERR(dpi
->engine_clk
)) {
710 ret
= PTR_ERR(dpi
->engine_clk
);
711 dev_err(dev
, "Failed to get engine clock: %d\n", ret
);
715 dpi
->pixel_clk
= devm_clk_get(dev
, "pixel");
716 if (IS_ERR(dpi
->pixel_clk
)) {
717 ret
= PTR_ERR(dpi
->pixel_clk
);
718 dev_err(dev
, "Failed to get pixel clock: %d\n", ret
);
722 dpi
->tvd_clk
= devm_clk_get(dev
, "pll");
723 if (IS_ERR(dpi
->tvd_clk
)) {
724 ret
= PTR_ERR(dpi
->tvd_clk
);
725 dev_err(dev
, "Failed to get tvdpll clock: %d\n", ret
);
729 dpi
->irq
= platform_get_irq(pdev
, 0);
731 dev_err(dev
, "Failed to get irq: %d\n", dpi
->irq
);
735 ret
= drm_of_find_panel_or_bridge(dev
->of_node
, 0, 0,
740 dev_info(dev
, "Found bridge node: %pOF\n", dpi
->bridge
->of_node
);
742 comp_id
= mtk_ddp_comp_get_id(dev
->of_node
, MTK_DPI
);
744 dev_err(dev
, "Failed to identify by alias: %d\n", comp_id
);
748 ret
= mtk_ddp_comp_init(dev
, dev
->of_node
, &dpi
->ddp_comp
, comp_id
,
751 dev_err(dev
, "Failed to initialize component: %d\n", ret
);
755 platform_set_drvdata(pdev
, dpi
);
757 ret
= component_add(dev
, &mtk_dpi_component_ops
);
759 dev_err(dev
, "Failed to add component: %d\n", ret
);
766 static int mtk_dpi_remove(struct platform_device
*pdev
)
768 component_del(&pdev
->dev
, &mtk_dpi_component_ops
);
773 static const struct of_device_id mtk_dpi_of_ids
[] = {
774 { .compatible
= "mediatek,mt2701-dpi",
775 .data
= &mt2701_conf
,
777 { .compatible
= "mediatek,mt8173-dpi",
778 .data
= &mt8173_conf
,
783 struct platform_driver mtk_dpi_driver
= {
784 .probe
= mtk_dpi_probe
,
785 .remove
= mtk_dpi_remove
,
787 .name
= "mediatek-dpi",
788 .of_match_table
= mtk_dpi_of_ids
,