1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2015 MediaTek Inc.
4 * Author: YT SHEN <yt.shen@mediatek.com>
7 #include <linux/component.h>
8 #include <linux/iommu.h>
9 #include <linux/module.h>
11 #include <linux/of_platform.h>
12 #include <linux/platform_device.h>
13 #include <linux/pm_runtime.h>
14 #include <linux/dma-mapping.h>
16 #include <drm/drm_atomic.h>
17 #include <drm/drm_atomic_helper.h>
18 #include <drm/drm_drv.h>
19 #include <drm/drm_fbdev_generic.h>
20 #include <drm/drm_fourcc.h>
21 #include <drm/drm_gem.h>
22 #include <drm/drm_gem_framebuffer_helper.h>
23 #include <drm/drm_ioctl.h>
24 #include <drm/drm_of.h>
25 #include <drm/drm_probe_helper.h>
26 #include <drm/drm_vblank.h>
28 #include "mtk_drm_crtc.h"
29 #include "mtk_drm_ddp_comp.h"
30 #include "mtk_drm_drv.h"
31 #include "mtk_drm_gem.h"
33 #define DRIVER_NAME "mediatek"
34 #define DRIVER_DESC "Mediatek SoC DRM"
35 #define DRIVER_DATE "20150513"
36 #define DRIVER_MAJOR 1
37 #define DRIVER_MINOR 0
39 static const struct drm_mode_config_helper_funcs mtk_drm_mode_config_helpers
= {
40 .atomic_commit_tail
= drm_atomic_helper_commit_tail_rpm
,
43 static struct drm_framebuffer
*
44 mtk_drm_mode_fb_create(struct drm_device
*dev
,
45 struct drm_file
*file
,
46 const struct drm_mode_fb_cmd2
*cmd
)
48 const struct drm_format_info
*info
= drm_get_format_info(dev
, cmd
);
50 if (info
->num_planes
!= 1)
51 return ERR_PTR(-EINVAL
);
53 return drm_gem_fb_create(dev
, file
, cmd
);
56 static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs
= {
57 .fb_create
= mtk_drm_mode_fb_create
,
58 .atomic_check
= drm_atomic_helper_check
,
59 .atomic_commit
= drm_atomic_helper_commit
,
62 static const unsigned int mt2701_mtk_ddp_main
[] = {
70 static const unsigned int mt2701_mtk_ddp_ext
[] = {
75 static const unsigned int mt7623_mtk_ddp_main
[] = {
83 static const unsigned int mt7623_mtk_ddp_ext
[] = {
88 static const unsigned int mt2712_mtk_ddp_main
[] = {
98 static const unsigned int mt2712_mtk_ddp_ext
[] = {
100 DDP_COMPONENT_COLOR1
,
108 static const unsigned int mt2712_mtk_ddp_third
[] = {
114 static unsigned int mt8167_mtk_ddp_main
[] = {
116 DDP_COMPONENT_COLOR0
,
120 DDP_COMPONENT_DITHER0
,
125 static const unsigned int mt8173_mtk_ddp_main
[] = {
127 DDP_COMPONENT_COLOR0
,
136 static const unsigned int mt8173_mtk_ddp_ext
[] = {
138 DDP_COMPONENT_COLOR1
,
144 static const unsigned int mt8183_mtk_ddp_main
[] = {
146 DDP_COMPONENT_OVL_2L0
,
148 DDP_COMPONENT_COLOR0
,
152 DDP_COMPONENT_DITHER0
,
156 static const unsigned int mt8183_mtk_ddp_ext
[] = {
157 DDP_COMPONENT_OVL_2L1
,
162 static const unsigned int mt8186_mtk_ddp_main
[] = {
165 DDP_COMPONENT_COLOR0
,
169 DDP_COMPONENT_POSTMASK0
,
170 DDP_COMPONENT_DITHER0
,
174 static const unsigned int mt8186_mtk_ddp_ext
[] = {
175 DDP_COMPONENT_OVL_2L0
,
180 static const unsigned int mt8188_mtk_ddp_main
[] = {
183 DDP_COMPONENT_COLOR0
,
187 DDP_COMPONENT_POSTMASK0
,
188 DDP_COMPONENT_DITHER0
,
191 static const struct mtk_drm_route mt8188_mtk_ddp_main_routes
[] = {
192 {0, DDP_COMPONENT_DP_INTF0
},
193 {0, DDP_COMPONENT_DSI0
},
196 static const unsigned int mt8192_mtk_ddp_main
[] = {
198 DDP_COMPONENT_OVL_2L0
,
200 DDP_COMPONENT_COLOR0
,
204 DDP_COMPONENT_POSTMASK0
,
205 DDP_COMPONENT_DITHER0
,
209 static const unsigned int mt8192_mtk_ddp_ext
[] = {
210 DDP_COMPONENT_OVL_2L2
,
215 static const unsigned int mt8195_mtk_ddp_main
[] = {
218 DDP_COMPONENT_COLOR0
,
222 DDP_COMPONENT_DITHER0
,
224 DDP_COMPONENT_MERGE0
,
225 DDP_COMPONENT_DP_INTF0
,
228 static const unsigned int mt8195_mtk_ddp_ext
[] = {
229 DDP_COMPONENT_DRM_OVL_ADAPTOR
,
230 DDP_COMPONENT_MERGE5
,
231 DDP_COMPONENT_DP_INTF1
,
234 static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data
= {
235 .main_path
= mt2701_mtk_ddp_main
,
236 .main_len
= ARRAY_SIZE(mt2701_mtk_ddp_main
),
237 .ext_path
= mt2701_mtk_ddp_ext
,
238 .ext_len
= ARRAY_SIZE(mt2701_mtk_ddp_ext
),
239 .shadow_register
= true,
243 static const struct mtk_mmsys_driver_data mt7623_mmsys_driver_data
= {
244 .main_path
= mt7623_mtk_ddp_main
,
245 .main_len
= ARRAY_SIZE(mt7623_mtk_ddp_main
),
246 .ext_path
= mt7623_mtk_ddp_ext
,
247 .ext_len
= ARRAY_SIZE(mt7623_mtk_ddp_ext
),
248 .shadow_register
= true,
252 static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data
= {
253 .main_path
= mt2712_mtk_ddp_main
,
254 .main_len
= ARRAY_SIZE(mt2712_mtk_ddp_main
),
255 .ext_path
= mt2712_mtk_ddp_ext
,
256 .ext_len
= ARRAY_SIZE(mt2712_mtk_ddp_ext
),
257 .third_path
= mt2712_mtk_ddp_third
,
258 .third_len
= ARRAY_SIZE(mt2712_mtk_ddp_third
),
262 static const struct mtk_mmsys_driver_data mt8167_mmsys_driver_data
= {
263 .main_path
= mt8167_mtk_ddp_main
,
264 .main_len
= ARRAY_SIZE(mt8167_mtk_ddp_main
),
268 static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data
= {
269 .main_path
= mt8173_mtk_ddp_main
,
270 .main_len
= ARRAY_SIZE(mt8173_mtk_ddp_main
),
271 .ext_path
= mt8173_mtk_ddp_ext
,
272 .ext_len
= ARRAY_SIZE(mt8173_mtk_ddp_ext
),
276 static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data
= {
277 .main_path
= mt8183_mtk_ddp_main
,
278 .main_len
= ARRAY_SIZE(mt8183_mtk_ddp_main
),
279 .ext_path
= mt8183_mtk_ddp_ext
,
280 .ext_len
= ARRAY_SIZE(mt8183_mtk_ddp_ext
),
284 static const struct mtk_mmsys_driver_data mt8186_mmsys_driver_data
= {
285 .main_path
= mt8186_mtk_ddp_main
,
286 .main_len
= ARRAY_SIZE(mt8186_mtk_ddp_main
),
287 .ext_path
= mt8186_mtk_ddp_ext
,
288 .ext_len
= ARRAY_SIZE(mt8186_mtk_ddp_ext
),
292 static const struct mtk_mmsys_driver_data mt8188_vdosys0_driver_data
= {
293 .main_path
= mt8188_mtk_ddp_main
,
294 .main_len
= ARRAY_SIZE(mt8188_mtk_ddp_main
),
295 .conn_routes
= mt8188_mtk_ddp_main_routes
,
296 .num_conn_routes
= ARRAY_SIZE(mt8188_mtk_ddp_main_routes
),
300 static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data
= {
301 .main_path
= mt8192_mtk_ddp_main
,
302 .main_len
= ARRAY_SIZE(mt8192_mtk_ddp_main
),
303 .ext_path
= mt8192_mtk_ddp_ext
,
304 .ext_len
= ARRAY_SIZE(mt8192_mtk_ddp_ext
),
308 static const struct mtk_mmsys_driver_data mt8195_vdosys0_driver_data
= {
309 .main_path
= mt8195_mtk_ddp_main
,
310 .main_len
= ARRAY_SIZE(mt8195_mtk_ddp_main
),
314 static const struct mtk_mmsys_driver_data mt8195_vdosys1_driver_data
= {
315 .ext_path
= mt8195_mtk_ddp_ext
,
316 .ext_len
= ARRAY_SIZE(mt8195_mtk_ddp_ext
),
321 static const struct of_device_id mtk_drm_of_ids
[] = {
322 { .compatible
= "mediatek,mt2701-mmsys",
323 .data
= &mt2701_mmsys_driver_data
},
324 { .compatible
= "mediatek,mt7623-mmsys",
325 .data
= &mt7623_mmsys_driver_data
},
326 { .compatible
= "mediatek,mt2712-mmsys",
327 .data
= &mt2712_mmsys_driver_data
},
328 { .compatible
= "mediatek,mt8167-mmsys",
329 .data
= &mt8167_mmsys_driver_data
},
330 { .compatible
= "mediatek,mt8173-mmsys",
331 .data
= &mt8173_mmsys_driver_data
},
332 { .compatible
= "mediatek,mt8183-mmsys",
333 .data
= &mt8183_mmsys_driver_data
},
334 { .compatible
= "mediatek,mt8186-mmsys",
335 .data
= &mt8186_mmsys_driver_data
},
336 { .compatible
= "mediatek,mt8188-vdosys0",
337 .data
= &mt8188_vdosys0_driver_data
},
338 { .compatible
= "mediatek,mt8192-mmsys",
339 .data
= &mt8192_mmsys_driver_data
},
340 { .compatible
= "mediatek,mt8195-mmsys",
341 .data
= &mt8195_vdosys0_driver_data
},
342 { .compatible
= "mediatek,mt8195-vdosys0",
343 .data
= &mt8195_vdosys0_driver_data
},
344 { .compatible
= "mediatek,mt8195-vdosys1",
345 .data
= &mt8195_vdosys1_driver_data
},
348 MODULE_DEVICE_TABLE(of
, mtk_drm_of_ids
);
350 static int mtk_drm_match(struct device
*dev
, void *data
)
352 if (!strncmp(dev_name(dev
), "mediatek-drm", sizeof("mediatek-drm") - 1))
357 static bool mtk_drm_get_all_drm_priv(struct device
*dev
)
359 struct mtk_drm_private
*drm_priv
= dev_get_drvdata(dev
);
360 struct mtk_drm_private
*all_drm_priv
[MAX_CRTC
];
361 struct mtk_drm_private
*temp_drm_priv
;
362 struct device_node
*phandle
= dev
->parent
->of_node
;
363 const struct of_device_id
*of_id
;
364 struct device_node
*node
;
365 struct device
*drm_dev
;
366 unsigned int cnt
= 0;
369 for_each_child_of_node(phandle
->parent
, node
) {
370 struct platform_device
*pdev
;
372 of_id
= of_match_node(mtk_drm_of_ids
, node
);
376 pdev
= of_find_device_by_node(node
);
380 drm_dev
= device_find_child(&pdev
->dev
, NULL
, mtk_drm_match
);
384 temp_drm_priv
= dev_get_drvdata(drm_dev
);
388 if (temp_drm_priv
->data
->main_len
)
389 all_drm_priv
[CRTC_MAIN
] = temp_drm_priv
;
390 else if (temp_drm_priv
->data
->ext_len
)
391 all_drm_priv
[CRTC_EXT
] = temp_drm_priv
;
392 else if (temp_drm_priv
->data
->third_len
)
393 all_drm_priv
[CRTC_THIRD
] = temp_drm_priv
;
395 if (temp_drm_priv
->mtk_drm_bound
)
402 if (drm_priv
->data
->mmsys_dev_num
== cnt
) {
403 for (i
= 0; i
< cnt
; i
++)
404 for (j
= 0; j
< cnt
; j
++)
405 all_drm_priv
[j
]->all_drm_private
[i
] = all_drm_priv
[i
];
413 static bool mtk_drm_find_mmsys_comp(struct mtk_drm_private
*private, int comp_id
)
415 const struct mtk_mmsys_driver_data
*drv_data
= private->data
;
418 if (drv_data
->main_path
)
419 for (i
= 0; i
< drv_data
->main_len
; i
++)
420 if (drv_data
->main_path
[i
] == comp_id
)
423 if (drv_data
->ext_path
)
424 for (i
= 0; i
< drv_data
->ext_len
; i
++)
425 if (drv_data
->ext_path
[i
] == comp_id
)
428 if (drv_data
->third_path
)
429 for (i
= 0; i
< drv_data
->third_len
; i
++)
430 if (drv_data
->third_path
[i
] == comp_id
)
433 if (drv_data
->num_conn_routes
)
434 for (i
= 0; i
< drv_data
->num_conn_routes
; i
++)
435 if (drv_data
->conn_routes
[i
].route_ddp
== comp_id
)
441 static int mtk_drm_kms_init(struct drm_device
*drm
)
443 struct mtk_drm_private
*private = drm
->dev_private
;
444 struct mtk_drm_private
*priv_n
;
445 struct device
*dma_dev
= NULL
;
448 if (drm_firmware_drivers_only())
451 ret
= drmm_mode_config_init(drm
);
455 drm
->mode_config
.min_width
= 64;
456 drm
->mode_config
.min_height
= 64;
459 * set max width and height as default value(4096x4096).
460 * this value would be used to check framebuffer size limitation
461 * at drm_mode_addfb().
463 drm
->mode_config
.max_width
= 4096;
464 drm
->mode_config
.max_height
= 4096;
465 drm
->mode_config
.funcs
= &mtk_drm_mode_config_funcs
;
466 drm
->mode_config
.helper_private
= &mtk_drm_mode_config_helpers
;
468 for (i
= 0; i
< private->data
->mmsys_dev_num
; i
++) {
469 drm
->dev_private
= private->all_drm_private
[i
];
470 ret
= component_bind_all(private->all_drm_private
[i
]->dev
, drm
);
476 * Ensure internal panels are at the top of the connector list before
479 drm_helper_move_panel_connectors_to_head(drm
);
482 * 1. We currently support two fixed data streams, each optional,
483 * and each statically assigned to a crtc:
484 * OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0 ...
485 * 2. For multi mmsys architecture, crtc path data are located in
486 * different drm private data structures. Loop through crtc index to
487 * create crtc from the main path and then ext_path and finally the
490 for (i
= 0; i
< MAX_CRTC
; i
++) {
491 for (j
= 0; j
< private->data
->mmsys_dev_num
; j
++) {
492 priv_n
= private->all_drm_private
[j
];
494 if (i
== CRTC_MAIN
&& priv_n
->data
->main_len
) {
495 ret
= mtk_drm_crtc_create(drm
, priv_n
->data
->main_path
,
496 priv_n
->data
->main_len
, j
,
497 priv_n
->data
->conn_routes
,
498 priv_n
->data
->num_conn_routes
);
500 goto err_component_unbind
;
503 } else if (i
== CRTC_EXT
&& priv_n
->data
->ext_len
) {
504 ret
= mtk_drm_crtc_create(drm
, priv_n
->data
->ext_path
,
505 priv_n
->data
->ext_len
, j
, NULL
, 0);
507 goto err_component_unbind
;
510 } else if (i
== CRTC_THIRD
&& priv_n
->data
->third_len
) {
511 ret
= mtk_drm_crtc_create(drm
, priv_n
->data
->third_path
,
512 priv_n
->data
->third_len
, j
, NULL
, 0);
514 goto err_component_unbind
;
521 /* Use OVL device for all DMA memory allocations */
522 dma_dev
= mtk_drm_crtc_dma_dev_get(drm_crtc_from_index(drm
, 0));
525 dev_err(drm
->dev
, "Need at least one OVL device\n");
526 goto err_component_unbind
;
529 for (i
= 0; i
< private->data
->mmsys_dev_num
; i
++)
530 private->all_drm_private
[i
]->dma_dev
= dma_dev
;
533 * Configure the DMA segment size to make sure we get contiguous IOVA
534 * when importing PRIME buffers.
536 ret
= dma_set_max_seg_size(dma_dev
, UINT_MAX
);
538 dev_err(dma_dev
, "Failed to set DMA segment size\n");
539 goto err_component_unbind
;
542 ret
= drm_vblank_init(drm
, MAX_CRTC
);
544 goto err_component_unbind
;
546 drm_kms_helper_poll_init(drm
);
547 drm_mode_config_reset(drm
);
551 err_component_unbind
:
552 for (i
= 0; i
< private->data
->mmsys_dev_num
; i
++)
553 component_unbind_all(private->all_drm_private
[i
]->dev
, drm
);
555 for (i
= 0; i
< private->data
->mmsys_dev_num
; i
++)
556 put_device(private->all_drm_private
[i
]->mutex_dev
);
561 static void mtk_drm_kms_deinit(struct drm_device
*drm
)
563 drm_kms_helper_poll_fini(drm
);
564 drm_atomic_helper_shutdown(drm
);
566 component_unbind_all(drm
->dev
, drm
);
569 DEFINE_DRM_GEM_FOPS(mtk_drm_fops
);
572 * We need to override this because the device used to import the memory is
573 * not dev->dev, as drm_gem_prime_import() expects.
575 static struct drm_gem_object
*mtk_drm_gem_prime_import(struct drm_device
*dev
,
576 struct dma_buf
*dma_buf
)
578 struct mtk_drm_private
*private = dev
->dev_private
;
580 return drm_gem_prime_import_dev(dev
, dma_buf
, private->dma_dev
);
583 static const struct drm_driver mtk_drm_driver
= {
584 .driver_features
= DRIVER_MODESET
| DRIVER_GEM
| DRIVER_ATOMIC
,
586 .dumb_create
= mtk_drm_gem_dumb_create
,
588 .gem_prime_import
= mtk_drm_gem_prime_import
,
589 .gem_prime_import_sg_table
= mtk_gem_prime_import_sg_table
,
590 .fops
= &mtk_drm_fops
,
595 .major
= DRIVER_MAJOR
,
596 .minor
= DRIVER_MINOR
,
599 static int compare_dev(struct device
*dev
, void *data
)
601 return dev
== (struct device
*)data
;
604 static int mtk_drm_bind(struct device
*dev
)
606 struct mtk_drm_private
*private = dev_get_drvdata(dev
);
607 struct platform_device
*pdev
;
608 struct drm_device
*drm
;
611 if (!iommu_present(&platform_bus_type
))
612 return -EPROBE_DEFER
;
614 pdev
= of_find_device_by_node(private->mutex_node
);
616 dev_err(dev
, "Waiting for disp-mutex device %pOF\n",
617 private->mutex_node
);
618 of_node_put(private->mutex_node
);
619 return -EPROBE_DEFER
;
622 private->mutex_dev
= &pdev
->dev
;
623 private->mtk_drm_bound
= true;
626 if (!mtk_drm_get_all_drm_priv(dev
))
629 drm
= drm_dev_alloc(&mtk_drm_driver
, dev
);
633 private->drm_master
= true;
634 drm
->dev_private
= private;
635 for (i
= 0; i
< private->data
->mmsys_dev_num
; i
++)
636 private->all_drm_private
[i
]->drm
= drm
;
638 ret
= mtk_drm_kms_init(drm
);
642 ret
= drm_dev_register(drm
, 0);
646 drm_fbdev_generic_setup(drm
, 32);
651 mtk_drm_kms_deinit(drm
);
658 static void mtk_drm_unbind(struct device
*dev
)
660 struct mtk_drm_private
*private = dev_get_drvdata(dev
);
662 /* for multi mmsys dev, unregister drm dev in mmsys master */
663 if (private->drm_master
) {
664 drm_dev_unregister(private->drm
);
665 mtk_drm_kms_deinit(private->drm
);
666 drm_dev_put(private->drm
);
668 private->mtk_drm_bound
= false;
669 private->drm_master
= false;
673 static const struct component_master_ops mtk_drm_ops
= {
674 .bind
= mtk_drm_bind
,
675 .unbind
= mtk_drm_unbind
,
678 static const struct of_device_id mtk_ddp_comp_dt_ids
[] = {
679 { .compatible
= "mediatek,mt8167-disp-aal",
680 .data
= (void *)MTK_DISP_AAL
},
681 { .compatible
= "mediatek,mt8173-disp-aal",
682 .data
= (void *)MTK_DISP_AAL
},
683 { .compatible
= "mediatek,mt8183-disp-aal",
684 .data
= (void *)MTK_DISP_AAL
},
685 { .compatible
= "mediatek,mt8192-disp-aal",
686 .data
= (void *)MTK_DISP_AAL
},
687 { .compatible
= "mediatek,mt8167-disp-ccorr",
688 .data
= (void *)MTK_DISP_CCORR
},
689 { .compatible
= "mediatek,mt8183-disp-ccorr",
690 .data
= (void *)MTK_DISP_CCORR
},
691 { .compatible
= "mediatek,mt8192-disp-ccorr",
692 .data
= (void *)MTK_DISP_CCORR
},
693 { .compatible
= "mediatek,mt2701-disp-color",
694 .data
= (void *)MTK_DISP_COLOR
},
695 { .compatible
= "mediatek,mt8167-disp-color",
696 .data
= (void *)MTK_DISP_COLOR
},
697 { .compatible
= "mediatek,mt8173-disp-color",
698 .data
= (void *)MTK_DISP_COLOR
},
699 { .compatible
= "mediatek,mt8167-disp-dither",
700 .data
= (void *)MTK_DISP_DITHER
},
701 { .compatible
= "mediatek,mt8183-disp-dither",
702 .data
= (void *)MTK_DISP_DITHER
},
703 { .compatible
= "mediatek,mt8195-disp-dsc",
704 .data
= (void *)MTK_DISP_DSC
},
705 { .compatible
= "mediatek,mt8167-disp-gamma",
706 .data
= (void *)MTK_DISP_GAMMA
, },
707 { .compatible
= "mediatek,mt8173-disp-gamma",
708 .data
= (void *)MTK_DISP_GAMMA
, },
709 { .compatible
= "mediatek,mt8183-disp-gamma",
710 .data
= (void *)MTK_DISP_GAMMA
, },
711 { .compatible
= "mediatek,mt8195-disp-merge",
712 .data
= (void *)MTK_DISP_MERGE
},
713 { .compatible
= "mediatek,mt2701-disp-mutex",
714 .data
= (void *)MTK_DISP_MUTEX
},
715 { .compatible
= "mediatek,mt2712-disp-mutex",
716 .data
= (void *)MTK_DISP_MUTEX
},
717 { .compatible
= "mediatek,mt8167-disp-mutex",
718 .data
= (void *)MTK_DISP_MUTEX
},
719 { .compatible
= "mediatek,mt8173-disp-mutex",
720 .data
= (void *)MTK_DISP_MUTEX
},
721 { .compatible
= "mediatek,mt8183-disp-mutex",
722 .data
= (void *)MTK_DISP_MUTEX
},
723 { .compatible
= "mediatek,mt8186-disp-mutex",
724 .data
= (void *)MTK_DISP_MUTEX
},
725 { .compatible
= "mediatek,mt8188-disp-mutex",
726 .data
= (void *)MTK_DISP_MUTEX
},
727 { .compatible
= "mediatek,mt8192-disp-mutex",
728 .data
= (void *)MTK_DISP_MUTEX
},
729 { .compatible
= "mediatek,mt8195-disp-mutex",
730 .data
= (void *)MTK_DISP_MUTEX
},
731 { .compatible
= "mediatek,mt8173-disp-od",
732 .data
= (void *)MTK_DISP_OD
},
733 { .compatible
= "mediatek,mt2701-disp-ovl",
734 .data
= (void *)MTK_DISP_OVL
},
735 { .compatible
= "mediatek,mt8167-disp-ovl",
736 .data
= (void *)MTK_DISP_OVL
},
737 { .compatible
= "mediatek,mt8173-disp-ovl",
738 .data
= (void *)MTK_DISP_OVL
},
739 { .compatible
= "mediatek,mt8183-disp-ovl",
740 .data
= (void *)MTK_DISP_OVL
},
741 { .compatible
= "mediatek,mt8192-disp-ovl",
742 .data
= (void *)MTK_DISP_OVL
},
743 { .compatible
= "mediatek,mt8183-disp-ovl-2l",
744 .data
= (void *)MTK_DISP_OVL_2L
},
745 { .compatible
= "mediatek,mt8192-disp-ovl-2l",
746 .data
= (void *)MTK_DISP_OVL_2L
},
747 { .compatible
= "mediatek,mt8192-disp-postmask",
748 .data
= (void *)MTK_DISP_POSTMASK
},
749 { .compatible
= "mediatek,mt2701-disp-pwm",
750 .data
= (void *)MTK_DISP_BLS
},
751 { .compatible
= "mediatek,mt8167-disp-pwm",
752 .data
= (void *)MTK_DISP_PWM
},
753 { .compatible
= "mediatek,mt8173-disp-pwm",
754 .data
= (void *)MTK_DISP_PWM
},
755 { .compatible
= "mediatek,mt2701-disp-rdma",
756 .data
= (void *)MTK_DISP_RDMA
},
757 { .compatible
= "mediatek,mt8167-disp-rdma",
758 .data
= (void *)MTK_DISP_RDMA
},
759 { .compatible
= "mediatek,mt8173-disp-rdma",
760 .data
= (void *)MTK_DISP_RDMA
},
761 { .compatible
= "mediatek,mt8183-disp-rdma",
762 .data
= (void *)MTK_DISP_RDMA
},
763 { .compatible
= "mediatek,mt8195-disp-rdma",
764 .data
= (void *)MTK_DISP_RDMA
},
765 { .compatible
= "mediatek,mt8173-disp-ufoe",
766 .data
= (void *)MTK_DISP_UFOE
},
767 { .compatible
= "mediatek,mt8173-disp-wdma",
768 .data
= (void *)MTK_DISP_WDMA
},
769 { .compatible
= "mediatek,mt2701-dpi",
770 .data
= (void *)MTK_DPI
},
771 { .compatible
= "mediatek,mt8167-dsi",
772 .data
= (void *)MTK_DSI
},
773 { .compatible
= "mediatek,mt8173-dpi",
774 .data
= (void *)MTK_DPI
},
775 { .compatible
= "mediatek,mt8183-dpi",
776 .data
= (void *)MTK_DPI
},
777 { .compatible
= "mediatek,mt8186-dpi",
778 .data
= (void *)MTK_DPI
},
779 { .compatible
= "mediatek,mt8188-dp-intf",
780 .data
= (void *)MTK_DP_INTF
},
781 { .compatible
= "mediatek,mt8192-dpi",
782 .data
= (void *)MTK_DPI
},
783 { .compatible
= "mediatek,mt8195-dp-intf",
784 .data
= (void *)MTK_DP_INTF
},
785 { .compatible
= "mediatek,mt2701-dsi",
786 .data
= (void *)MTK_DSI
},
787 { .compatible
= "mediatek,mt8173-dsi",
788 .data
= (void *)MTK_DSI
},
789 { .compatible
= "mediatek,mt8183-dsi",
790 .data
= (void *)MTK_DSI
},
791 { .compatible
= "mediatek,mt8186-dsi",
792 .data
= (void *)MTK_DSI
},
793 { .compatible
= "mediatek,mt8188-dsi",
794 .data
= (void *)MTK_DSI
},
798 static int mtk_drm_probe(struct platform_device
*pdev
)
800 struct device
*dev
= &pdev
->dev
;
801 struct device_node
*phandle
= dev
->parent
->of_node
;
802 const struct of_device_id
*of_id
;
803 struct mtk_drm_private
*private;
804 struct device_node
*node
;
805 struct component_match
*match
= NULL
;
806 struct platform_device
*ovl_adaptor
;
810 private = devm_kzalloc(dev
, sizeof(*private), GFP_KERNEL
);
814 private->mmsys_dev
= dev
->parent
;
815 if (!private->mmsys_dev
) {
816 dev_err(dev
, "Failed to get MMSYS device\n");
820 of_id
= of_match_node(mtk_drm_of_ids
, phandle
);
824 private->data
= of_id
->data
;
826 private->all_drm_private
= devm_kmalloc_array(dev
, private->data
->mmsys_dev_num
,
827 sizeof(*private->all_drm_private
),
829 if (!private->all_drm_private
)
832 /* Bringup ovl_adaptor */
833 if (mtk_drm_find_mmsys_comp(private, DDP_COMPONENT_DRM_OVL_ADAPTOR
)) {
834 ovl_adaptor
= platform_device_register_data(dev
, "mediatek-disp-ovl-adaptor",
836 (void *)private->mmsys_dev
,
837 sizeof(*private->mmsys_dev
));
838 private->ddp_comp
[DDP_COMPONENT_DRM_OVL_ADAPTOR
].dev
= &ovl_adaptor
->dev
;
839 mtk_ddp_comp_init(NULL
, &private->ddp_comp
[DDP_COMPONENT_DRM_OVL_ADAPTOR
],
840 DDP_COMPONENT_DRM_OVL_ADAPTOR
);
841 component_match_add(dev
, &match
, compare_dev
, &ovl_adaptor
->dev
);
844 /* Iterate over sibling DISP function blocks */
845 for_each_child_of_node(phandle
->parent
, node
) {
846 const struct of_device_id
*of_id
;
847 enum mtk_ddp_comp_type comp_type
;
850 of_id
= of_match_node(mtk_ddp_comp_dt_ids
, node
);
854 if (!of_device_is_available(node
)) {
855 dev_dbg(dev
, "Skipping disabled component %pOF\n",
860 comp_type
= (enum mtk_ddp_comp_type
)(uintptr_t)of_id
->data
;
862 if (comp_type
== MTK_DISP_MUTEX
) {
865 id
= of_alias_get_id(node
, "mutex");
866 if (id
< 0 || id
== private->data
->mmsys_id
) {
867 private->mutex_node
= of_node_get(node
);
868 dev_dbg(dev
, "get mutex for mmsys %d", private->data
->mmsys_id
);
873 comp_id
= mtk_ddp_comp_get_id(node
, comp_type
);
875 dev_warn(dev
, "Skipping unknown component %pOF\n",
880 if (!mtk_drm_find_mmsys_comp(private, comp_id
))
883 private->comp_node
[comp_id
] = of_node_get(node
);
886 * Currently only the AAL, CCORR, COLOR, GAMMA, MERGE, OVL, RDMA, DSI, and DPI
887 * blocks have separate component platform drivers and initialize their own
888 * DDP component structure. The others are initialized here.
890 if (comp_type
== MTK_DISP_AAL
||
891 comp_type
== MTK_DISP_CCORR
||
892 comp_type
== MTK_DISP_COLOR
||
893 comp_type
== MTK_DISP_GAMMA
||
894 comp_type
== MTK_DISP_MERGE
||
895 comp_type
== MTK_DISP_OVL
||
896 comp_type
== MTK_DISP_OVL_2L
||
897 comp_type
== MTK_DISP_OVL_ADAPTOR
||
898 comp_type
== MTK_DISP_RDMA
||
899 comp_type
== MTK_DP_INTF
||
900 comp_type
== MTK_DPI
||
901 comp_type
== MTK_DSI
) {
902 dev_info(dev
, "Adding component match for %pOF\n",
904 drm_of_component_match_add(dev
, &match
, component_compare_of
,
908 ret
= mtk_ddp_comp_init(node
, &private->ddp_comp
[comp_id
], comp_id
);
915 if (!private->mutex_node
) {
916 dev_err(dev
, "Failed to find disp-mutex node\n");
921 pm_runtime_enable(dev
);
923 platform_set_drvdata(pdev
, private);
925 ret
= component_master_add_with_match(dev
, &mtk_drm_ops
, match
);
932 pm_runtime_disable(dev
);
934 of_node_put(private->mutex_node
);
935 for (i
= 0; i
< DDP_COMPONENT_DRM_ID_MAX
; i
++)
936 of_node_put(private->comp_node
[i
]);
940 static void mtk_drm_remove(struct platform_device
*pdev
)
942 struct mtk_drm_private
*private = platform_get_drvdata(pdev
);
945 component_master_del(&pdev
->dev
, &mtk_drm_ops
);
946 pm_runtime_disable(&pdev
->dev
);
947 of_node_put(private->mutex_node
);
948 for (i
= 0; i
< DDP_COMPONENT_DRM_ID_MAX
; i
++)
949 of_node_put(private->comp_node
[i
]);
952 static int mtk_drm_sys_prepare(struct device
*dev
)
954 struct mtk_drm_private
*private = dev_get_drvdata(dev
);
955 struct drm_device
*drm
= private->drm
;
957 if (private->drm_master
)
958 return drm_mode_config_helper_suspend(drm
);
963 static void mtk_drm_sys_complete(struct device
*dev
)
965 struct mtk_drm_private
*private = dev_get_drvdata(dev
);
966 struct drm_device
*drm
= private->drm
;
969 if (private->drm_master
)
970 ret
= drm_mode_config_helper_resume(drm
);
972 dev_err(dev
, "Failed to resume\n");
975 static const struct dev_pm_ops mtk_drm_pm_ops
= {
976 .prepare
= mtk_drm_sys_prepare
,
977 .complete
= mtk_drm_sys_complete
,
980 static struct platform_driver mtk_drm_platform_driver
= {
981 .probe
= mtk_drm_probe
,
982 .remove_new
= mtk_drm_remove
,
984 .name
= "mediatek-drm",
985 .pm
= &mtk_drm_pm_ops
,
989 static struct platform_driver
* const mtk_drm_drivers
[] = {
990 &mtk_disp_aal_driver
,
991 &mtk_disp_ccorr_driver
,
992 &mtk_disp_color_driver
,
993 &mtk_disp_gamma_driver
,
994 &mtk_disp_merge_driver
,
995 &mtk_disp_ovl_adaptor_driver
,
996 &mtk_disp_ovl_driver
,
997 &mtk_disp_rdma_driver
,
999 &mtk_drm_platform_driver
,
1002 &mtk_mdp_rdma_driver
,
1005 static int __init
mtk_drm_init(void)
1007 return platform_register_drivers(mtk_drm_drivers
,
1008 ARRAY_SIZE(mtk_drm_drivers
));
1011 static void __exit
mtk_drm_exit(void)
1013 platform_unregister_drivers(mtk_drm_drivers
,
1014 ARRAY_SIZE(mtk_drm_drivers
));
1017 module_init(mtk_drm_init
);
1018 module_exit(mtk_drm_exit
);
1020 MODULE_AUTHOR("YT SHEN <yt.shen@mediatek.com>");
1021 MODULE_DESCRIPTION("Mediatek SoC DRM driver");
1022 MODULE_LICENSE("GPL v2");