Lines Matching +full:mediatek +full:- +full:display

1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2015 MediaTek Inc.
4 * Author: YT SHEN <yt.shen@mediatek.com>
13 #include <linux/dma-mapping.h>
34 #define DRIVER_NAME "mediatek"
35 #define DRIVER_DESC "Mediatek SoC DRM"
50 if (info->num_planes != 1) in mtk_drm_mode_fb_create()
51 return ERR_PTR(-EINVAL); in mtk_drm_mode_fb_create()
326 .min_width = 2, /* 2-pixel align when ethdr is bypassed */
331 { .compatible = "mediatek,mt2701-mmsys",
333 { .compatible = "mediatek,mt7623-mmsys",
335 { .compatible = "mediatek,mt2712-mmsys",
337 { .compatible = "mediatek,mt8167-mmsys",
339 { .compatible = "mediatek,mt8173-mmsys",
341 { .compatible = "mediatek,mt8183-mmsys",
343 { .compatible = "mediatek,mt8186-mmsys",
345 { .compatible = "mediatek,mt8188-vdosys0",
347 { .compatible = "mediatek,mt8188-vdosys1",
349 { .compatible = "mediatek,mt8192-mmsys",
351 { .compatible = "mediatek,mt8195-mmsys",
353 { .compatible = "mediatek,mt8195-vdosys0",
355 { .compatible = "mediatek,mt8195-vdosys1",
363 if (!strncmp(dev_name(dev), "mediatek-drm", sizeof("mediatek-drm") - 1)) in mtk_drm_match()
373 struct device_node *phandle = dev->parent->of_node; in mtk_drm_get_all_drm_priv()
380 for_each_child_of_node(phandle->parent, node) { in mtk_drm_get_all_drm_priv()
391 drm_dev = device_find_child(&pdev->dev, NULL, mtk_drm_match); in mtk_drm_get_all_drm_priv()
399 if (temp_drm_priv->data->main_len) in mtk_drm_get_all_drm_priv()
401 else if (temp_drm_priv->data->ext_len) in mtk_drm_get_all_drm_priv()
403 else if (temp_drm_priv->data->third_len) in mtk_drm_get_all_drm_priv()
406 if (temp_drm_priv->mtk_drm_bound) in mtk_drm_get_all_drm_priv()
415 if (drm_priv->data->mmsys_dev_num == cnt) { in mtk_drm_get_all_drm_priv()
418 all_drm_priv[j]->all_drm_private[i] = all_drm_priv[i]; in mtk_drm_get_all_drm_priv()
428 const struct mtk_mmsys_driver_data *drv_data = private->data; in mtk_drm_find_mmsys_comp()
431 if (drv_data->main_path) in mtk_drm_find_mmsys_comp()
432 for (i = 0; i < drv_data->main_len; i++) in mtk_drm_find_mmsys_comp()
433 if (drv_data->main_path[i] == comp_id) in mtk_drm_find_mmsys_comp()
436 if (drv_data->ext_path) in mtk_drm_find_mmsys_comp()
437 for (i = 0; i < drv_data->ext_len; i++) in mtk_drm_find_mmsys_comp()
438 if (drv_data->ext_path[i] == comp_id) in mtk_drm_find_mmsys_comp()
441 if (drv_data->third_path) in mtk_drm_find_mmsys_comp()
442 for (i = 0; i < drv_data->third_len; i++) in mtk_drm_find_mmsys_comp()
443 if (drv_data->third_path[i] == comp_id) in mtk_drm_find_mmsys_comp()
446 if (drv_data->num_conn_routes) in mtk_drm_find_mmsys_comp()
447 for (i = 0; i < drv_data->num_conn_routes; i++) in mtk_drm_find_mmsys_comp()
448 if (drv_data->conn_routes[i].route_ddp == comp_id) in mtk_drm_find_mmsys_comp()
456 struct mtk_drm_private *private = drm->dev_private; in mtk_drm_kms_init()
463 return -ENODEV; in mtk_drm_kms_init()
469 drm->mode_config.min_width = 64; in mtk_drm_kms_init()
470 drm->mode_config.min_height = 64; in mtk_drm_kms_init()
477 drm->mode_config.max_width = 4096; in mtk_drm_kms_init()
478 drm->mode_config.max_height = 4096; in mtk_drm_kms_init()
479 drm->mode_config.funcs = &mtk_drm_mode_config_funcs; in mtk_drm_kms_init()
480 drm->mode_config.helper_private = &mtk_drm_mode_config_helpers; in mtk_drm_kms_init()
482 for (i = 0; i < private->data->mmsys_dev_num; i++) { in mtk_drm_kms_init()
483 drm->dev_private = private->all_drm_private[i]; in mtk_drm_kms_init()
484 ret = component_bind_all(private->all_drm_private[i]->dev, drm); in mtk_drm_kms_init()
498 * OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0 ... in mtk_drm_kms_init()
505 for (j = 0; j < private->data->mmsys_dev_num; j++) { in mtk_drm_kms_init()
506 priv_n = private->all_drm_private[j]; in mtk_drm_kms_init()
508 if (priv_n->data->max_width) in mtk_drm_kms_init()
509 drm->mode_config.max_width = priv_n->data->max_width; in mtk_drm_kms_init()
511 if (priv_n->data->min_width) in mtk_drm_kms_init()
512 drm->mode_config.min_width = priv_n->data->min_width; in mtk_drm_kms_init()
514 if (priv_n->data->min_height) in mtk_drm_kms_init()
515 drm->mode_config.min_height = priv_n->data->min_height; in mtk_drm_kms_init()
517 if (i == CRTC_MAIN && priv_n->data->main_len) { in mtk_drm_kms_init()
518 ret = mtk_crtc_create(drm, priv_n->data->main_path, in mtk_drm_kms_init()
519 priv_n->data->main_len, j, in mtk_drm_kms_init()
520 priv_n->data->conn_routes, in mtk_drm_kms_init()
521 priv_n->data->num_conn_routes); in mtk_drm_kms_init()
526 } else if (i == CRTC_EXT && priv_n->data->ext_len) { in mtk_drm_kms_init()
527 ret = mtk_crtc_create(drm, priv_n->data->ext_path, in mtk_drm_kms_init()
528 priv_n->data->ext_len, j, NULL, 0); in mtk_drm_kms_init()
533 } else if (i == CRTC_THIRD && priv_n->data->third_len) { in mtk_drm_kms_init()
534 ret = mtk_crtc_create(drm, priv_n->data->third_path, in mtk_drm_kms_init()
535 priv_n->data->third_len, j, NULL, 0); in mtk_drm_kms_init()
545 drm->mode_config.cursor_width = 512; in mtk_drm_kms_init()
546 drm->mode_config.cursor_height = 512; in mtk_drm_kms_init()
553 ret = -ENODEV; in mtk_drm_kms_init()
554 dev_err(drm->dev, "Need at least one OVL device\n"); in mtk_drm_kms_init()
558 for (i = 0; i < private->data->mmsys_dev_num; i++) in mtk_drm_kms_init()
559 private->all_drm_private[i]->dma_dev = dma_dev; in mtk_drm_kms_init()
577 for (i = 0; i < private->data->mmsys_dev_num; i++) in mtk_drm_kms_init()
578 component_unbind_all(private->all_drm_private[i]->dev, drm); in mtk_drm_kms_init()
580 for (i = 0; i < private->data->mmsys_dev_num; i++) in mtk_drm_kms_init()
581 put_device(private->all_drm_private[i]->mutex_dev); in mtk_drm_kms_init()
591 component_unbind_all(drm->dev, drm); in mtk_drm_kms_deinit()
598 * not dev->dev, as drm_gem_prime_import() expects.
603 struct mtk_drm_private *private = dev->dev_private; in mtk_gem_prime_import()
605 return drm_gem_prime_import_dev(dev, dma_buf, private->dma_dev); in mtk_gem_prime_import()
636 pdev = of_find_device_by_node(private->mutex_node); in mtk_drm_bind()
638 dev_err(dev, "Waiting for disp-mutex device %pOF\n", in mtk_drm_bind()
639 private->mutex_node); in mtk_drm_bind()
640 of_node_put(private->mutex_node); in mtk_drm_bind()
641 return -EPROBE_DEFER; in mtk_drm_bind()
644 private->mutex_dev = &pdev->dev; in mtk_drm_bind()
645 private->mtk_drm_bound = true; in mtk_drm_bind()
646 private->dev = dev; in mtk_drm_bind()
655 private->drm_master = true; in mtk_drm_bind()
656 drm->dev_private = private; in mtk_drm_bind()
657 for (i = 0; i < private->data->mmsys_dev_num; i++) in mtk_drm_bind()
658 private->all_drm_private[i]->drm = drm; in mtk_drm_bind()
675 private->drm = NULL; in mtk_drm_bind()
677 for (i = 0; i < private->data->mmsys_dev_num; i++) in mtk_drm_bind()
678 private->all_drm_private[i]->drm = NULL; in mtk_drm_bind()
687 if (private->drm_master) { in mtk_drm_unbind()
688 drm_dev_unregister(private->drm); in mtk_drm_unbind()
689 mtk_drm_kms_deinit(private->drm); in mtk_drm_unbind()
690 drm_dev_put(private->drm); in mtk_drm_unbind()
692 private->mtk_drm_bound = false; in mtk_drm_unbind()
693 private->drm_master = false; in mtk_drm_unbind()
694 private->drm = NULL; in mtk_drm_unbind()
703 { .compatible = "mediatek,mt8167-disp-aal",
705 { .compatible = "mediatek,mt8173-disp-aal",
707 { .compatible = "mediatek,mt8183-disp-aal",
709 { .compatible = "mediatek,mt8192-disp-aal",
711 { .compatible = "mediatek,mt8167-disp-ccorr",
713 { .compatible = "mediatek,mt8183-disp-ccorr",
715 { .compatible = "mediatek,mt8192-disp-ccorr",
717 { .compatible = "mediatek,mt2701-disp-color",
719 { .compatible = "mediatek,mt8167-disp-color",
721 { .compatible = "mediatek,mt8173-disp-color",
723 { .compatible = "mediatek,mt8167-disp-dither",
725 { .compatible = "mediatek,mt8183-disp-dither",
727 { .compatible = "mediatek,mt8195-disp-dsc",
729 { .compatible = "mediatek,mt8167-disp-gamma",
731 { .compatible = "mediatek,mt8173-disp-gamma",
733 { .compatible = "mediatek,mt8183-disp-gamma",
735 { .compatible = "mediatek,mt8195-disp-gamma",
737 { .compatible = "mediatek,mt8195-disp-merge",
739 { .compatible = "mediatek,mt2701-disp-mutex",
741 { .compatible = "mediatek,mt2712-disp-mutex",
743 { .compatible = "mediatek,mt8167-disp-mutex",
745 { .compatible = "mediatek,mt8173-disp-mutex",
747 { .compatible = "mediatek,mt8183-disp-mutex",
749 { .compatible = "mediatek,mt8186-disp-mutex",
751 { .compatible = "mediatek,mt8188-disp-mutex",
753 { .compatible = "mediatek,mt8192-disp-mutex",
755 { .compatible = "mediatek,mt8195-disp-mutex",
757 { .compatible = "mediatek,mt8173-disp-od",
759 { .compatible = "mediatek,mt2701-disp-ovl",
761 { .compatible = "mediatek,mt8167-disp-ovl",
763 { .compatible = "mediatek,mt8173-disp-ovl",
765 { .compatible = "mediatek,mt8183-disp-ovl",
767 { .compatible = "mediatek,mt8192-disp-ovl",
769 { .compatible = "mediatek,mt8195-disp-ovl",
771 { .compatible = "mediatek,mt8183-disp-ovl-2l",
773 { .compatible = "mediatek,mt8192-disp-ovl-2l",
775 { .compatible = "mediatek,mt8192-disp-postmask",
777 { .compatible = "mediatek,mt2701-disp-pwm",
779 { .compatible = "mediatek,mt8167-disp-pwm",
781 { .compatible = "mediatek,mt8173-disp-pwm",
783 { .compatible = "mediatek,mt2701-disp-rdma",
785 { .compatible = "mediatek,mt8167-disp-rdma",
787 { .compatible = "mediatek,mt8173-disp-rdma",
789 { .compatible = "mediatek,mt8183-disp-rdma",
791 { .compatible = "mediatek,mt8195-disp-rdma",
793 { .compatible = "mediatek,mt8173-disp-ufoe",
795 { .compatible = "mediatek,mt8173-disp-wdma",
797 { .compatible = "mediatek,mt2701-dpi",
799 { .compatible = "mediatek,mt8167-dsi",
801 { .compatible = "mediatek,mt8173-dpi",
803 { .compatible = "mediatek,mt8183-dpi",
805 { .compatible = "mediatek,mt8186-dpi",
807 { .compatible = "mediatek,mt8188-dp-intf",
809 { .compatible = "mediatek,mt8192-dpi",
811 { .compatible = "mediatek,mt8195-dp-intf",
813 { .compatible = "mediatek,mt2701-dsi",
815 { .compatible = "mediatek,mt8173-dsi",
817 { .compatible = "mediatek,mt8183-dsi",
819 { .compatible = "mediatek,mt8186-dsi",
821 { .compatible = "mediatek,mt8188-dsi",
831 return -EINVAL; in mtk_drm_of_get_ddp_comp_type()
833 *ctype = (enum mtk_ddp_comp_type)((uintptr_t)of_id->data); in mtk_drm_of_get_ddp_comp_type()
848 return -ENOENT; in mtk_drm_of_get_ddp_ep_cid()
853 return -EINVAL; in mtk_drm_of_get_ddp_ep_cid()
863 return -ENODEV; in mtk_drm_of_get_ddp_ep_cid()
885 * mtk_drm_of_ddp_path_build_one - Build a Display HW Pipeline for a CRTC Path
886 * @dev: The mediatek-drm device
891 * MediaTek SoCs can use different DDP hardware pipelines (or paths) depending
892 * on the board-specific desired display configuration; this function walks
897 * * %0 - Display HW Pipeline successfully built and validated
898 * * %-ENOENT - Display pipeline was not specified in device tree
899 * * %-EINVAL - Display pipeline built but validation failed
900 * * %-ENOMEM - Failure to allocate pipeline array to pass to the caller
906 struct device_node *next = NULL, *prev, *vdo = dev->parent->of_node; in mtk_drm_of_ddp_path_build_one()
931 * Walk through port outputs until we reach the last valid mediatek-drm component. in mtk_drm_of_ddp_path_build_one()
932 * To be valid, this must end with an "invalid" component that is a display node. in mtk_drm_of_ddp_path_build_one()
954 idx--; in mtk_drm_of_ddp_path_build_one()
962 if (ret == -ENODEV) in mtk_drm_of_ddp_path_build_one()
965 /* If the last entry is not a final display output, the configuration is wrong */ in mtk_drm_of_ddp_path_build_one()
966 switch (temp_path[idx - 1]) { in mtk_drm_of_ddp_path_build_one()
977 dev_err(dev, "Invalid display hw pipeline. Last component: %d (ret=%d)\n", in mtk_drm_of_ddp_path_build_one()
978 temp_path[idx - 1], ret); in mtk_drm_of_ddp_path_build_one()
979 return -EINVAL; in mtk_drm_of_ddp_path_build_one()
984 return -ENOMEM; in mtk_drm_of_ddp_path_build_one()
986 dev_dbg(dev, "Display HW Pipeline built with %d components.\n", idx); in mtk_drm_of_ddp_path_build_one()
1011 ret = dev_err_probe(dev, -EINVAL, in mtk_drm_of_ddp_path_build()
1026 &data->main_path, &data->main_len); in mtk_drm_of_ddp_path_build()
1027 if (ret && ret != -ENODEV) in mtk_drm_of_ddp_path_build()
1033 &data->ext_path, &data->ext_len); in mtk_drm_of_ddp_path_build()
1034 if (ret && ret != -ENODEV) in mtk_drm_of_ddp_path_build()
1040 &data->third_path, &data->third_len); in mtk_drm_of_ddp_path_build()
1041 if (ret && ret != -ENODEV) in mtk_drm_of_ddp_path_build()
1050 struct device *dev = &pdev->dev; in mtk_drm_probe()
1051 struct device_node *phandle = dev->parent->of_node; in mtk_drm_probe()
1063 return -ENOMEM; in mtk_drm_probe()
1065 private->mmsys_dev = dev->parent; in mtk_drm_probe()
1066 if (!private->mmsys_dev) { in mtk_drm_probe()
1068 return -ENODEV; in mtk_drm_probe()
1073 return -ENODEV; in mtk_drm_probe()
1075 mtk_drm_data = (struct mtk_mmsys_driver_data *)of_id->data; in mtk_drm_probe()
1077 return -EINVAL; in mtk_drm_probe()
1079 /* Try to build the display pipeline from devicetree graphs */ in mtk_drm_probe()
1081 dev_dbg(dev, "Building display pipeline for MMSYS %u\n", in mtk_drm_probe()
1082 mtk_drm_data->mmsys_id); in mtk_drm_probe()
1083 private->data = devm_kmemdup(dev, mtk_drm_data, in mtk_drm_probe()
1085 if (!private->data) in mtk_drm_probe()
1086 return -ENOMEM; in mtk_drm_probe()
1088 ret = mtk_drm_of_ddp_path_build(dev, phandle, private->data); in mtk_drm_probe()
1093 dev_dbg(dev, "Using hardcoded paths for MMSYS %u\n", mtk_drm_data->mmsys_id); in mtk_drm_probe()
1094 private->data = mtk_drm_data; in mtk_drm_probe()
1097 private->all_drm_private = devm_kmalloc_array(dev, private->data->mmsys_dev_num, in mtk_drm_probe()
1098 sizeof(*private->all_drm_private), in mtk_drm_probe()
1100 if (!private->all_drm_private) in mtk_drm_probe()
1101 return -ENOMEM; in mtk_drm_probe()
1105 ovl_adaptor = platform_device_register_data(dev, "mediatek-disp-ovl-adaptor", in mtk_drm_probe()
1107 (void *)private->mmsys_dev, in mtk_drm_probe()
1108 sizeof(*private->mmsys_dev)); in mtk_drm_probe()
1109 private->ddp_comp[DDP_COMPONENT_DRM_OVL_ADAPTOR].dev = &ovl_adaptor->dev; in mtk_drm_probe()
1110 mtk_ddp_comp_init(NULL, &private->ddp_comp[DDP_COMPONENT_DRM_OVL_ADAPTOR], in mtk_drm_probe()
1112 component_match_add(dev, &match, compare_dev, &ovl_adaptor->dev); in mtk_drm_probe()
1116 for_each_child_of_node(phandle->parent, node) { in mtk_drm_probe()
1134 if (id < 0 || id == private->data->mmsys_id) { in mtk_drm_probe()
1135 private->mutex_node = of_node_get(node); in mtk_drm_probe()
1136 dev_dbg(dev, "get mutex for mmsys %d", private->data->mmsys_id); in mtk_drm_probe()
1151 private->comp_node[comp_id] = of_node_get(node); in mtk_drm_probe()
1176 ret = mtk_ddp_comp_init(node, &private->ddp_comp[comp_id], comp_id); in mtk_drm_probe()
1183 if (!private->mutex_node) { in mtk_drm_probe()
1184 dev_err(dev, "Failed to find disp-mutex node\n"); in mtk_drm_probe()
1185 ret = -ENODEV; in mtk_drm_probe()
1202 of_node_put(private->mutex_node); in mtk_drm_probe()
1204 of_node_put(private->comp_node[i]); in mtk_drm_probe()
1213 component_master_del(&pdev->dev, &mtk_drm_ops); in mtk_drm_remove()
1214 pm_runtime_disable(&pdev->dev); in mtk_drm_remove()
1215 of_node_put(private->mutex_node); in mtk_drm_remove()
1217 of_node_put(private->comp_node[i]); in mtk_drm_remove()
1224 drm_atomic_helper_shutdown(private->drm); in mtk_drm_shutdown()
1230 struct drm_device *drm = private->drm; in mtk_drm_sys_prepare()
1232 if (private->drm_master) in mtk_drm_sys_prepare()
1241 struct drm_device *drm = private->drm; in mtk_drm_sys_complete()
1244 if (private->drm_master) in mtk_drm_sys_complete()
1260 .name = "mediatek-drm",
1297 MODULE_AUTHOR("YT SHEN <yt.shen@mediatek.com>");
1298 MODULE_DESCRIPTION("Mediatek SoC DRM driver");