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>
10 #include <linux/of_address.h>
11 #include <linux/of_platform.h>
12 #include <linux/pm_runtime.h>
13 #include <linux/soc/mediatek/mtk-mmsys.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_fb_helper.h>
20 #include <drm/drm_fourcc.h>
21 #include <drm/drm_gem.h>
22 #include <drm/drm_gem_cma_helper.h>
23 #include <drm/drm_gem_framebuffer_helper.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.h"
30 #include "mtk_drm_ddp_comp.h"
31 #include "mtk_drm_drv.h"
32 #include "mtk_drm_gem.h"
34 #define DRIVER_NAME "mediatek"
35 #define DRIVER_DESC "Mediatek SoC DRM"
36 #define DRIVER_DATE "20150513"
37 #define DRIVER_MAJOR 1
38 #define DRIVER_MINOR 0
40 static const struct drm_mode_config_helper_funcs mtk_drm_mode_config_helpers
= {
41 .atomic_commit_tail
= drm_atomic_helper_commit_tail_rpm
,
44 static struct drm_framebuffer
*
45 mtk_drm_mode_fb_create(struct drm_device
*dev
,
46 struct drm_file
*file
,
47 const struct drm_mode_fb_cmd2
*cmd
)
49 const struct drm_format_info
*info
= drm_get_format_info(dev
, cmd
);
51 if (info
->num_planes
!= 1)
52 return ERR_PTR(-EINVAL
);
54 return drm_gem_fb_create(dev
, file
, cmd
);
57 static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs
= {
58 .fb_create
= mtk_drm_mode_fb_create
,
59 .atomic_check
= drm_atomic_helper_check
,
60 .atomic_commit
= drm_atomic_helper_commit
,
63 static const enum mtk_ddp_comp_id mt2701_mtk_ddp_main
[] = {
71 static const enum mtk_ddp_comp_id mt2701_mtk_ddp_ext
[] = {
76 static const enum mtk_ddp_comp_id mt7623_mtk_ddp_main
[] = {
84 static const enum mtk_ddp_comp_id mt7623_mtk_ddp_ext
[] = {
89 static const enum mtk_ddp_comp_id mt2712_mtk_ddp_main
[] = {
99 static const enum mtk_ddp_comp_id mt2712_mtk_ddp_ext
[] = {
101 DDP_COMPONENT_COLOR1
,
109 static const enum mtk_ddp_comp_id mt2712_mtk_ddp_third
[] = {
115 static const enum mtk_ddp_comp_id mt8173_mtk_ddp_main
[] = {
117 DDP_COMPONENT_COLOR0
,
126 static const enum mtk_ddp_comp_id mt8173_mtk_ddp_ext
[] = {
128 DDP_COMPONENT_COLOR1
,
134 static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data
= {
135 .main_path
= mt2701_mtk_ddp_main
,
136 .main_len
= ARRAY_SIZE(mt2701_mtk_ddp_main
),
137 .ext_path
= mt2701_mtk_ddp_ext
,
138 .ext_len
= ARRAY_SIZE(mt2701_mtk_ddp_ext
),
139 .shadow_register
= true,
142 static const struct mtk_mmsys_driver_data mt7623_mmsys_driver_data
= {
143 .main_path
= mt7623_mtk_ddp_main
,
144 .main_len
= ARRAY_SIZE(mt7623_mtk_ddp_main
),
145 .ext_path
= mt7623_mtk_ddp_ext
,
146 .ext_len
= ARRAY_SIZE(mt7623_mtk_ddp_ext
),
147 .shadow_register
= true,
150 static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data
= {
151 .main_path
= mt2712_mtk_ddp_main
,
152 .main_len
= ARRAY_SIZE(mt2712_mtk_ddp_main
),
153 .ext_path
= mt2712_mtk_ddp_ext
,
154 .ext_len
= ARRAY_SIZE(mt2712_mtk_ddp_ext
),
155 .third_path
= mt2712_mtk_ddp_third
,
156 .third_len
= ARRAY_SIZE(mt2712_mtk_ddp_third
),
159 static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data
= {
160 .main_path
= mt8173_mtk_ddp_main
,
161 .main_len
= ARRAY_SIZE(mt8173_mtk_ddp_main
),
162 .ext_path
= mt8173_mtk_ddp_ext
,
163 .ext_len
= ARRAY_SIZE(mt8173_mtk_ddp_ext
),
166 static int mtk_drm_kms_init(struct drm_device
*drm
)
168 struct mtk_drm_private
*private = drm
->dev_private
;
169 struct platform_device
*pdev
;
170 struct device_node
*np
;
171 struct device
*dma_dev
;
174 if (!iommu_present(&platform_bus_type
))
175 return -EPROBE_DEFER
;
177 pdev
= of_find_device_by_node(private->mutex_node
);
179 dev_err(drm
->dev
, "Waiting for disp-mutex device %pOF\n",
180 private->mutex_node
);
181 of_node_put(private->mutex_node
);
182 return -EPROBE_DEFER
;
184 private->mutex_dev
= &pdev
->dev
;
186 ret
= drmm_mode_config_init(drm
);
190 drm
->mode_config
.min_width
= 64;
191 drm
->mode_config
.min_height
= 64;
194 * set max width and height as default value(4096x4096).
195 * this value would be used to check framebuffer size limitation
196 * at drm_mode_addfb().
198 drm
->mode_config
.max_width
= 4096;
199 drm
->mode_config
.max_height
= 4096;
200 drm
->mode_config
.funcs
= &mtk_drm_mode_config_funcs
;
201 drm
->mode_config
.helper_private
= &mtk_drm_mode_config_helpers
;
203 ret
= component_bind_all(drm
->dev
, drm
);
208 * We currently support two fixed data streams, each optional,
209 * and each statically assigned to a crtc:
210 * OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0 ...
212 ret
= mtk_drm_crtc_create(drm
, private->data
->main_path
,
213 private->data
->main_len
);
215 goto err_component_unbind
;
216 /* ... and OVL1 -> COLOR1 -> GAMMA -> RDMA1 -> DPI0. */
217 ret
= mtk_drm_crtc_create(drm
, private->data
->ext_path
,
218 private->data
->ext_len
);
220 goto err_component_unbind
;
222 ret
= mtk_drm_crtc_create(drm
, private->data
->third_path
,
223 private->data
->third_len
);
225 goto err_component_unbind
;
227 /* Use OVL device for all DMA memory allocations */
228 np
= private->comp_node
[private->data
->main_path
[0]] ?:
229 private->comp_node
[private->data
->ext_path
[0]];
230 pdev
= of_find_device_by_node(np
);
233 dev_err(drm
->dev
, "Need at least one OVL device\n");
234 goto err_component_unbind
;
237 dma_dev
= &pdev
->dev
;
238 private->dma_dev
= dma_dev
;
241 * Configure the DMA segment size to make sure we get contiguous IOVA
242 * when importing PRIME buffers.
244 ret
= dma_set_max_seg_size(dma_dev
, UINT_MAX
);
246 dev_err(dma_dev
, "Failed to set DMA segment size\n");
247 goto err_component_unbind
;
251 * We don't use the drm_irq_install() helpers provided by the DRM
252 * core, so we need to set this manually in order to allow the
253 * DRM_IOCTL_WAIT_VBLANK to operate correctly.
255 drm
->irq_enabled
= true;
256 ret
= drm_vblank_init(drm
, MAX_CRTC
);
258 goto err_component_unbind
;
260 drm_kms_helper_poll_init(drm
);
261 drm_mode_config_reset(drm
);
265 err_component_unbind
:
266 component_unbind_all(drm
->dev
, drm
);
268 put_device(private->mutex_dev
);
272 static void mtk_drm_kms_deinit(struct drm_device
*drm
)
274 drm_kms_helper_poll_fini(drm
);
275 drm_atomic_helper_shutdown(drm
);
277 component_unbind_all(drm
->dev
, drm
);
280 static const struct file_operations mtk_drm_fops
= {
281 .owner
= THIS_MODULE
,
283 .release
= drm_release
,
284 .unlocked_ioctl
= drm_ioctl
,
285 .mmap
= mtk_drm_gem_mmap
,
288 .compat_ioctl
= drm_compat_ioctl
,
292 * We need to override this because the device used to import the memory is
293 * not dev->dev, as drm_gem_prime_import() expects.
295 static struct drm_gem_object
*mtk_drm_gem_prime_import(struct drm_device
*dev
,
296 struct dma_buf
*dma_buf
)
298 struct mtk_drm_private
*private = dev
->dev_private
;
300 return drm_gem_prime_import_dev(dev
, dma_buf
, private->dma_dev
);
303 static const struct drm_driver mtk_drm_driver
= {
304 .driver_features
= DRIVER_MODESET
| DRIVER_GEM
| DRIVER_ATOMIC
,
306 .dumb_create
= mtk_drm_gem_dumb_create
,
308 .prime_handle_to_fd
= drm_gem_prime_handle_to_fd
,
309 .prime_fd_to_handle
= drm_gem_prime_fd_to_handle
,
310 .gem_prime_import
= mtk_drm_gem_prime_import
,
311 .gem_prime_import_sg_table
= mtk_gem_prime_import_sg_table
,
312 .gem_prime_mmap
= mtk_drm_gem_mmap_buf
,
313 .fops
= &mtk_drm_fops
,
318 .major
= DRIVER_MAJOR
,
319 .minor
= DRIVER_MINOR
,
322 static int compare_of(struct device
*dev
, void *data
)
324 return dev
->of_node
== data
;
327 static int mtk_drm_bind(struct device
*dev
)
329 struct mtk_drm_private
*private = dev_get_drvdata(dev
);
330 struct drm_device
*drm
;
333 drm
= drm_dev_alloc(&mtk_drm_driver
, dev
);
337 drm
->dev_private
= private;
340 ret
= mtk_drm_kms_init(drm
);
344 ret
= drm_dev_register(drm
, 0);
348 drm_fbdev_generic_setup(drm
, 32);
353 mtk_drm_kms_deinit(drm
);
359 static void mtk_drm_unbind(struct device
*dev
)
361 struct mtk_drm_private
*private = dev_get_drvdata(dev
);
363 drm_dev_unregister(private->drm
);
364 mtk_drm_kms_deinit(private->drm
);
365 drm_dev_put(private->drm
);
366 private->num_pipes
= 0;
370 static const struct component_master_ops mtk_drm_ops
= {
371 .bind
= mtk_drm_bind
,
372 .unbind
= mtk_drm_unbind
,
375 static const struct of_device_id mtk_ddp_comp_dt_ids
[] = {
376 { .compatible
= "mediatek,mt2701-disp-ovl",
377 .data
= (void *)MTK_DISP_OVL
},
378 { .compatible
= "mediatek,mt8173-disp-ovl",
379 .data
= (void *)MTK_DISP_OVL
},
380 { .compatible
= "mediatek,mt2701-disp-rdma",
381 .data
= (void *)MTK_DISP_RDMA
},
382 { .compatible
= "mediatek,mt8173-disp-rdma",
383 .data
= (void *)MTK_DISP_RDMA
},
384 { .compatible
= "mediatek,mt8173-disp-wdma",
385 .data
= (void *)MTK_DISP_WDMA
},
386 { .compatible
= "mediatek,mt2701-disp-color",
387 .data
= (void *)MTK_DISP_COLOR
},
388 { .compatible
= "mediatek,mt8173-disp-color",
389 .data
= (void *)MTK_DISP_COLOR
},
390 { .compatible
= "mediatek,mt8173-disp-aal",
391 .data
= (void *)MTK_DISP_AAL
},
392 { .compatible
= "mediatek,mt8173-disp-gamma",
393 .data
= (void *)MTK_DISP_GAMMA
, },
394 { .compatible
= "mediatek,mt8173-disp-ufoe",
395 .data
= (void *)MTK_DISP_UFOE
},
396 { .compatible
= "mediatek,mt2701-dsi",
397 .data
= (void *)MTK_DSI
},
398 { .compatible
= "mediatek,mt8173-dsi",
399 .data
= (void *)MTK_DSI
},
400 { .compatible
= "mediatek,mt2701-dpi",
401 .data
= (void *)MTK_DPI
},
402 { .compatible
= "mediatek,mt8173-dpi",
403 .data
= (void *)MTK_DPI
},
404 { .compatible
= "mediatek,mt2701-disp-mutex",
405 .data
= (void *)MTK_DISP_MUTEX
},
406 { .compatible
= "mediatek,mt2712-disp-mutex",
407 .data
= (void *)MTK_DISP_MUTEX
},
408 { .compatible
= "mediatek,mt8173-disp-mutex",
409 .data
= (void *)MTK_DISP_MUTEX
},
410 { .compatible
= "mediatek,mt2701-disp-pwm",
411 .data
= (void *)MTK_DISP_BLS
},
412 { .compatible
= "mediatek,mt8173-disp-pwm",
413 .data
= (void *)MTK_DISP_PWM
},
414 { .compatible
= "mediatek,mt8173-disp-od",
415 .data
= (void *)MTK_DISP_OD
},
419 static const struct of_device_id mtk_drm_of_ids
[] = {
420 { .compatible
= "mediatek,mt2701-mmsys",
421 .data
= &mt2701_mmsys_driver_data
},
422 { .compatible
= "mediatek,mt7623-mmsys",
423 .data
= &mt7623_mmsys_driver_data
},
424 { .compatible
= "mediatek,mt2712-mmsys",
425 .data
= &mt2712_mmsys_driver_data
},
426 { .compatible
= "mediatek,mt8173-mmsys",
427 .data
= &mt8173_mmsys_driver_data
},
431 static int mtk_drm_probe(struct platform_device
*pdev
)
433 struct device
*dev
= &pdev
->dev
;
434 struct device_node
*phandle
= dev
->parent
->of_node
;
435 const struct of_device_id
*of_id
;
436 struct mtk_drm_private
*private;
437 struct device_node
*node
;
438 struct component_match
*match
= NULL
;
442 private = devm_kzalloc(dev
, sizeof(*private), GFP_KERNEL
);
446 private->mmsys_dev
= dev
->parent
;
447 if (!private->mmsys_dev
) {
448 dev_err(dev
, "Failed to get MMSYS device\n");
452 of_id
= of_match_node(mtk_drm_of_ids
, phandle
);
456 private->data
= of_id
->data
;
458 /* Iterate over sibling DISP function blocks */
459 for_each_child_of_node(phandle
->parent
, node
) {
460 const struct of_device_id
*of_id
;
461 enum mtk_ddp_comp_type comp_type
;
464 of_id
= of_match_node(mtk_ddp_comp_dt_ids
, node
);
468 if (!of_device_is_available(node
)) {
469 dev_dbg(dev
, "Skipping disabled component %pOF\n",
474 comp_type
= (enum mtk_ddp_comp_type
)of_id
->data
;
476 if (comp_type
== MTK_DISP_MUTEX
) {
477 private->mutex_node
= of_node_get(node
);
481 comp_id
= mtk_ddp_comp_get_id(node
, comp_type
);
483 dev_warn(dev
, "Skipping unknown component %pOF\n",
488 private->comp_node
[comp_id
] = of_node_get(node
);
491 * Currently only the COLOR, OVL, RDMA, DSI, and DPI blocks have
492 * separate component platform drivers and initialize their own
493 * DDP component structure. The others are initialized here.
495 if (comp_type
== MTK_DISP_COLOR
||
496 comp_type
== MTK_DISP_OVL
||
497 comp_type
== MTK_DISP_OVL_2L
||
498 comp_type
== MTK_DISP_RDMA
||
499 comp_type
== MTK_DSI
||
500 comp_type
== MTK_DPI
) {
501 dev_info(dev
, "Adding component match for %pOF\n",
503 drm_of_component_match_add(dev
, &match
, compare_of
,
506 struct mtk_ddp_comp
*comp
;
508 comp
= devm_kzalloc(dev
, sizeof(*comp
), GFP_KERNEL
);
515 ret
= mtk_ddp_comp_init(dev
->parent
, node
, comp
,
522 private->ddp_comp
[comp_id
] = comp
;
526 if (!private->mutex_node
) {
527 dev_err(dev
, "Failed to find disp-mutex node\n");
532 pm_runtime_enable(dev
);
534 platform_set_drvdata(pdev
, private);
536 ret
= component_master_add_with_match(dev
, &mtk_drm_ops
, match
);
543 pm_runtime_disable(dev
);
545 of_node_put(private->mutex_node
);
546 for (i
= 0; i
< DDP_COMPONENT_ID_MAX
; i
++) {
547 of_node_put(private->comp_node
[i
]);
548 if (private->ddp_comp
[i
]) {
549 put_device(private->ddp_comp
[i
]->larb_dev
);
550 private->ddp_comp
[i
] = NULL
;
556 static int mtk_drm_remove(struct platform_device
*pdev
)
558 struct mtk_drm_private
*private = platform_get_drvdata(pdev
);
561 component_master_del(&pdev
->dev
, &mtk_drm_ops
);
562 pm_runtime_disable(&pdev
->dev
);
563 of_node_put(private->mutex_node
);
564 for (i
= 0; i
< DDP_COMPONENT_ID_MAX
; i
++)
565 of_node_put(private->comp_node
[i
]);
570 #ifdef CONFIG_PM_SLEEP
571 static int mtk_drm_sys_suspend(struct device
*dev
)
573 struct mtk_drm_private
*private = dev_get_drvdata(dev
);
574 struct drm_device
*drm
= private->drm
;
577 ret
= drm_mode_config_helper_suspend(drm
);
582 static int mtk_drm_sys_resume(struct device
*dev
)
584 struct mtk_drm_private
*private = dev_get_drvdata(dev
);
585 struct drm_device
*drm
= private->drm
;
588 ret
= drm_mode_config_helper_resume(drm
);
594 static SIMPLE_DEV_PM_OPS(mtk_drm_pm_ops
, mtk_drm_sys_suspend
,
597 static struct platform_driver mtk_drm_platform_driver
= {
598 .probe
= mtk_drm_probe
,
599 .remove
= mtk_drm_remove
,
601 .name
= "mediatek-drm",
602 .pm
= &mtk_drm_pm_ops
,
606 static struct platform_driver
* const mtk_drm_drivers
[] = {
608 &mtk_disp_color_driver
,
609 &mtk_disp_ovl_driver
,
610 &mtk_disp_rdma_driver
,
612 &mtk_drm_platform_driver
,
616 static int __init
mtk_drm_init(void)
618 return platform_register_drivers(mtk_drm_drivers
,
619 ARRAY_SIZE(mtk_drm_drivers
));
622 static void __exit
mtk_drm_exit(void)
624 platform_unregister_drivers(mtk_drm_drivers
,
625 ARRAY_SIZE(mtk_drm_drivers
));
628 module_init(mtk_drm_init
);
629 module_exit(mtk_drm_exit
);
631 MODULE_AUTHOR("YT SHEN <yt.shen@mediatek.com>");
632 MODULE_DESCRIPTION("Mediatek SoC DRM driver");
633 MODULE_LICENSE("GPL v2");