File Index
Files and directories
Sign in
FILE

mtk_drm_drv.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/mediatek/mtk_drm_drv.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2015 MediaTek Inc.
   4 * Author: YT SHEN <yt.shen@mediatek.com>
   5 */
   6
   7#include <linux/component.h>
   8#include <linux/module.h>
   9#include <linux/of.h>
  10#include <linux/of_platform.h>
  11#include <linux/platform_device.h>
  12#include <linux/pm_runtime.h>
  13#include <linux/dma-mapping.h>
  14
  15#include <drm/clients/drm_client_setup.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_dma.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>
  27
  28#include "mtk_crtc.h"
  29#include "mtk_ddp_comp.h"
  30#include "mtk_disp_drv.h"
  31#include "mtk_drm_drv.h"
  32#include "mtk_gem.h"
  33
  34#define DRIVER_NAME "mediatek"
  35#define DRIVER_DESC "Mediatek SoC DRM"
  36#define DRIVER_MAJOR 1
  37#define DRIVER_MINOR 0
  38
  39static const struct drm_mode_config_helper_funcs mtk_drm_mode_config_helpers = {
  40	.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
  41};
  42
  43static struct drm_framebuffer *
  44mtk_drm_mode_fb_create(struct drm_device *dev,
  45		       struct drm_file *file,
  46		       const struct drm_format_info *info,
  47		       const struct drm_mode_fb_cmd2 *cmd)
  48{
  49	if (info->num_planes != 1)
  50		return ERR_PTR(-EINVAL);
  51
  52	return drm_gem_fb_create(dev, file, info, cmd);
  53}
  54
  55static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs = {
  56	.fb_create = mtk_drm_mode_fb_create,
  57	.atomic_check = drm_atomic_helper_check,
  58	.atomic_commit = drm_atomic_helper_commit,
  59};
  60
  61static const unsigned int mt2701_mtk_ddp_main[] = {
  62	DDP_COMPONENT_OVL0,
  63	DDP_COMPONENT_RDMA0,
  64	DDP_COMPONENT_COLOR0,
  65	DDP_COMPONENT_BLS,
  66	DDP_COMPONENT_DSI0,
  67};
  68
  69static const unsigned int mt2701_mtk_ddp_ext[] = {
  70	DDP_COMPONENT_RDMA1,
  71	DDP_COMPONENT_DPI0,
  72};
  73
  74static const unsigned int mt7623_mtk_ddp_main[] = {
  75	DDP_COMPONENT_OVL0,
  76	DDP_COMPONENT_RDMA0,
  77	DDP_COMPONENT_COLOR0,
  78	DDP_COMPONENT_BLS,
  79	DDP_COMPONENT_DPI0,
  80};
  81
  82static const unsigned int mt7623_mtk_ddp_ext[] = {
  83	DDP_COMPONENT_RDMA1,
  84	DDP_COMPONENT_DSI0,
  85};
  86
  87static const unsigned int mt2712_mtk_ddp_main[] = {
  88	DDP_COMPONENT_OVL0,
  89	DDP_COMPONENT_COLOR0,
  90	DDP_COMPONENT_AAL0,
  91	DDP_COMPONENT_OD0,
  92	DDP_COMPONENT_RDMA0,
  93	DDP_COMPONENT_DPI0,
  94	DDP_COMPONENT_PWM0,
  95};
  96
  97static const unsigned int mt2712_mtk_ddp_ext[] = {
  98	DDP_COMPONENT_OVL1,
  99	DDP_COMPONENT_COLOR1,
 100	DDP_COMPONENT_AAL1,
 101	DDP_COMPONENT_OD1,
 102	DDP_COMPONENT_RDMA1,
 103	DDP_COMPONENT_DPI1,
 104	DDP_COMPONENT_PWM1,
 105};
 106
 107static const unsigned int mt2712_mtk_ddp_third[] = {
 108	DDP_COMPONENT_RDMA2,
 109	DDP_COMPONENT_DSI3,
 110	DDP_COMPONENT_PWM2,
 111};
 112
 113static unsigned int mt8167_mtk_ddp_main[] = {
 114	DDP_COMPONENT_OVL0,
 115	DDP_COMPONENT_COLOR0,
 116	DDP_COMPONENT_CCORR,
 117	DDP_COMPONENT_AAL0,
 118	DDP_COMPONENT_GAMMA,
 119	DDP_COMPONENT_DITHER0,
 120	DDP_COMPONENT_RDMA0,
 121	DDP_COMPONENT_DSI0,
 122};
 123
 124static const unsigned int mt8173_mtk_ddp_main[] = {
 125	DDP_COMPONENT_OVL0,
 126	DDP_COMPONENT_COLOR0,
 127	DDP_COMPONENT_AAL0,
 128	DDP_COMPONENT_OD0,
 129	DDP_COMPONENT_RDMA0,
 130	DDP_COMPONENT_UFOE,
 131	DDP_COMPONENT_DSI0,
 132	DDP_COMPONENT_PWM0,
 133};
 134
 135static const unsigned int mt8173_mtk_ddp_ext[] = {
 136	DDP_COMPONENT_OVL1,
 137	DDP_COMPONENT_COLOR1,
 138	DDP_COMPONENT_GAMMA,
 139	DDP_COMPONENT_RDMA1,
 140	DDP_COMPONENT_DPI0,
 141};
 142
 143static const unsigned int mt8183_mtk_ddp_main[] = {
 144	DDP_COMPONENT_OVL0,
 145	DDP_COMPONENT_OVL_2L0,
 146	DDP_COMPONENT_RDMA0,
 147	DDP_COMPONENT_COLOR0,
 148	DDP_COMPONENT_CCORR,
 149	DDP_COMPONENT_AAL0,
 150	DDP_COMPONENT_GAMMA,
 151	DDP_COMPONENT_DITHER0,
 152	DDP_COMPONENT_DSI0,
 153};
 154
 155static const unsigned int mt8183_mtk_ddp_ext[] = {
 156	DDP_COMPONENT_OVL_2L1,
 157	DDP_COMPONENT_RDMA1,
 158	DDP_COMPONENT_DPI0,
 159};
 160
 161static const unsigned int mt8186_mtk_ddp_main[] = {
 162	DDP_COMPONENT_OVL0,
 163	DDP_COMPONENT_RDMA0,
 164	DDP_COMPONENT_COLOR0,
 165	DDP_COMPONENT_CCORR,
 166	DDP_COMPONENT_AAL0,
 167	DDP_COMPONENT_GAMMA,
 168	DDP_COMPONENT_POSTMASK0,
 169	DDP_COMPONENT_DITHER0,
 170	DDP_COMPONENT_DSI0,
 171};
 172
 173static const unsigned int mt8186_mtk_ddp_ext[] = {
 174	DDP_COMPONENT_OVL_2L0,
 175	DDP_COMPONENT_RDMA1,
 176	DDP_COMPONENT_DPI0,
 177};
 178
 179static const unsigned int mt8188_mtk_ddp_main[] = {
 180	DDP_COMPONENT_OVL0,
 181	DDP_COMPONENT_RDMA0,
 182	DDP_COMPONENT_COLOR0,
 183	DDP_COMPONENT_CCORR,
 184	DDP_COMPONENT_AAL0,
 185	DDP_COMPONENT_GAMMA,
 186	DDP_COMPONENT_POSTMASK0,
 187	DDP_COMPONENT_DITHER0,
 188};
 189
 190static const struct mtk_drm_route mt8188_mtk_ddp_main_routes[] = {
 191	{0, DDP_COMPONENT_DP_INTF0},
 192	{0, DDP_COMPONENT_DSI0},
 193};
 194
 195static const unsigned int mt8192_mtk_ddp_main[] = {
 196	DDP_COMPONENT_OVL0,
 197	DDP_COMPONENT_OVL_2L0,
 198	DDP_COMPONENT_RDMA0,
 199	DDP_COMPONENT_COLOR0,
 200	DDP_COMPONENT_CCORR,
 201	DDP_COMPONENT_AAL0,
 202	DDP_COMPONENT_GAMMA,
 203	DDP_COMPONENT_POSTMASK0,
 204	DDP_COMPONENT_DITHER0,
 205	DDP_COMPONENT_DSI0,
 206};
 207
 208static const unsigned int mt8192_mtk_ddp_ext[] = {
 209	DDP_COMPONENT_OVL_2L2,
 210	DDP_COMPONENT_RDMA4,
 211	DDP_COMPONENT_DPI0,
 212};
 213
 214static const unsigned int mt8195_mtk_ddp_main[] = {
 215	DDP_COMPONENT_OVL0,
 216	DDP_COMPONENT_RDMA0,
 217	DDP_COMPONENT_COLOR0,
 218	DDP_COMPONENT_CCORR,
 219	DDP_COMPONENT_AAL0,
 220	DDP_COMPONENT_GAMMA,
 221	DDP_COMPONENT_DITHER0,
 222	DDP_COMPONENT_DSC0,
 223	DDP_COMPONENT_MERGE0,
 224	DDP_COMPONENT_DP_INTF0,
 225};
 226
 227static const unsigned int mt8195_mtk_ddp_ext[] = {
 228	DDP_COMPONENT_DRM_OVL_ADAPTOR,
 229	DDP_COMPONENT_MERGE5,
 230	DDP_COMPONENT_DP_INTF1,
 231};
 232
 233static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
 234	.main_path = mt2701_mtk_ddp_main,
 235	.main_len = ARRAY_SIZE(mt2701_mtk_ddp_main),
 236	.ext_path = mt2701_mtk_ddp_ext,
 237	.ext_len = ARRAY_SIZE(mt2701_mtk_ddp_ext),
 238	.shadow_register = true,
 239	.mmsys_dev_num = 1,
 240};
 241
 242static const struct mtk_mmsys_driver_data mt7623_mmsys_driver_data = {
 243	.main_path = mt7623_mtk_ddp_main,
 244	.main_len = ARRAY_SIZE(mt7623_mtk_ddp_main),
 245	.ext_path = mt7623_mtk_ddp_ext,
 246	.ext_len = ARRAY_SIZE(mt7623_mtk_ddp_ext),
 247	.shadow_register = true,
 248	.mmsys_dev_num = 1,
 249};
 250
 251static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = {
 252	.main_path = mt2712_mtk_ddp_main,
 253	.main_len = ARRAY_SIZE(mt2712_mtk_ddp_main),
 254	.ext_path = mt2712_mtk_ddp_ext,
 255	.ext_len = ARRAY_SIZE(mt2712_mtk_ddp_ext),
 256	.third_path = mt2712_mtk_ddp_third,
 257	.third_len = ARRAY_SIZE(mt2712_mtk_ddp_third),
 258	.mmsys_dev_num = 1,
 259};
 260
 261static const struct mtk_mmsys_driver_data mt8167_mmsys_driver_data = {
 262	.main_path = mt8167_mtk_ddp_main,
 263	.main_len = ARRAY_SIZE(mt8167_mtk_ddp_main),
 264	.mmsys_dev_num = 1,
 265};
 266
 267static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
 268	.main_path = mt8173_mtk_ddp_main,
 269	.main_len = ARRAY_SIZE(mt8173_mtk_ddp_main),
 270	.ext_path = mt8173_mtk_ddp_ext,
 271	.ext_len = ARRAY_SIZE(mt8173_mtk_ddp_ext),
 272	.mmsys_dev_num = 1,
 273};
 274
 275static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = {
 276	.main_path = mt8183_mtk_ddp_main,
 277	.main_len = ARRAY_SIZE(mt8183_mtk_ddp_main),
 278	.ext_path = mt8183_mtk_ddp_ext,
 279	.ext_len = ARRAY_SIZE(mt8183_mtk_ddp_ext),
 280	.mmsys_dev_num = 1,
 281};
 282
 283static const struct mtk_mmsys_driver_data mt8186_mmsys_driver_data = {
 284	.main_path = mt8186_mtk_ddp_main,
 285	.main_len = ARRAY_SIZE(mt8186_mtk_ddp_main),
 286	.ext_path = mt8186_mtk_ddp_ext,
 287	.ext_len = ARRAY_SIZE(mt8186_mtk_ddp_ext),
 288	.mmsys_dev_num = 1,
 289};
 290
 291static const struct mtk_mmsys_driver_data mt8188_vdosys0_driver_data = {
 292	.main_path = mt8188_mtk_ddp_main,
 293	.main_len = ARRAY_SIZE(mt8188_mtk_ddp_main),
 294	.conn_routes = mt8188_mtk_ddp_main_routes,
 295	.num_conn_routes = ARRAY_SIZE(mt8188_mtk_ddp_main_routes),
 296	.mmsys_dev_num = 2,
 297	.max_width = 8191,
 298	.min_width = 1,
 299	.min_height = 1,
 300};
 301
 302static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = {
 303	.main_path = mt8192_mtk_ddp_main,
 304	.main_len = ARRAY_SIZE(mt8192_mtk_ddp_main),
 305	.ext_path = mt8192_mtk_ddp_ext,
 306	.ext_len = ARRAY_SIZE(mt8192_mtk_ddp_ext),
 307	.mmsys_dev_num = 1,
 308};
 309
 310static const struct mtk_mmsys_driver_data mt8195_vdosys0_driver_data = {
 311	.main_path = mt8195_mtk_ddp_main,
 312	.main_len = ARRAY_SIZE(mt8195_mtk_ddp_main),
 313	.mmsys_dev_num = 2,
 314	.max_width = 8191,
 315	.min_width = 1,
 316	.min_height = 1,
 317};
 318
 319static const struct mtk_mmsys_driver_data mt8195_vdosys1_driver_data = {
 320	.ext_path = mt8195_mtk_ddp_ext,
 321	.ext_len = ARRAY_SIZE(mt8195_mtk_ddp_ext),
 322	.mmsys_id = 1,
 323	.mmsys_dev_num = 2,
 324	.max_width = 8191,
 325	.min_width = 2, /* 2-pixel align when ethdr is bypassed */
 326	.min_height = 1,
 327};
 328
 329static const struct mtk_mmsys_driver_data mt8365_mmsys_driver_data = {
 330	.mmsys_dev_num = 1,
 331};
 332
 333static const struct of_device_id mtk_drm_of_ids[] = {
 334	{ .compatible = "mediatek,mt2701-mmsys",
 335	  .data = &mt2701_mmsys_driver_data},
 336	{ .compatible = "mediatek,mt7623-mmsys",
 337	  .data = &mt7623_mmsys_driver_data},
 338	{ .compatible = "mediatek,mt2712-mmsys",
 339	  .data = &mt2712_mmsys_driver_data},
 340	{ .compatible = "mediatek,mt8167-mmsys",
 341	  .data = &mt8167_mmsys_driver_data},
 342	{ .compatible = "mediatek,mt8173-mmsys",
 343	  .data = &mt8173_mmsys_driver_data},
 344	{ .compatible = "mediatek,mt8183-mmsys",
 345	  .data = &mt8183_mmsys_driver_data},
 346	{ .compatible = "mediatek,mt8186-mmsys",
 347	  .data = &mt8186_mmsys_driver_data},
 348	{ .compatible = "mediatek,mt8188-vdosys0",
 349	  .data = &mt8188_vdosys0_driver_data},
 350	{ .compatible = "mediatek,mt8188-vdosys1",
 351	  .data = &mt8195_vdosys1_driver_data},
 352	{ .compatible = "mediatek,mt8192-mmsys",
 353	  .data = &mt8192_mmsys_driver_data},
 354	{ .compatible = "mediatek,mt8195-mmsys",
 355	  .data = &mt8195_vdosys0_driver_data},
 356	{ .compatible = "mediatek,mt8195-vdosys0",
 357	  .data = &mt8195_vdosys0_driver_data},
 358	{ .compatible = "mediatek,mt8195-vdosys1",
 359	  .data = &mt8195_vdosys1_driver_data},
 360	{ .compatible = "mediatek,mt8365-mmsys",
 361	  .data = &mt8365_mmsys_driver_data},
 362	{ }
 363};
 364MODULE_DEVICE_TABLE(of, mtk_drm_of_ids);
 365
 366static int mtk_drm_match(struct device *dev, const void *data)
 367{
 368	if (!strncmp(dev_name(dev), "mediatek-drm", sizeof("mediatek-drm") - 1))
 369		return true;
 370	return false;
 371}
 372
 373static bool mtk_drm_get_all_drm_priv(struct device *dev)
 374{
 375	struct mtk_drm_private *drm_priv = dev_get_drvdata(dev);
 376	struct mtk_drm_private *all_drm_priv[MAX_CRTC];
 377	struct mtk_drm_private *temp_drm_priv;
 378	struct device_node *phandle = dev->parent->of_node;
 379	const struct of_device_id *of_id;
 380	struct device_node *node;
 381	struct device *drm_dev;
 382	unsigned int cnt = 0;
 383	int i, j;
 384
 385	for_each_child_of_node(phandle->parent, node) {
 386		struct platform_device *pdev;
 387
 388		of_id = of_match_node(mtk_drm_of_ids, node);
 389		if (!of_id)
 390			continue;
 391
 392		pdev = of_find_device_by_node(node);
 393		if (!pdev)
 394			continue;
 395
 396		drm_dev = device_find_child(&pdev->dev, NULL, mtk_drm_match);
 397		put_device(&pdev->dev);
 398		if (!drm_dev)
 399			continue;
 400
 401		temp_drm_priv = dev_get_drvdata(drm_dev);
 402		put_device(drm_dev);
 403		if (!temp_drm_priv)
 404			continue;
 405
 406		if (temp_drm_priv->data->main_len)
 407			all_drm_priv[CRTC_MAIN] = temp_drm_priv;
 408		else if (temp_drm_priv->data->ext_len)
 409			all_drm_priv[CRTC_EXT] = temp_drm_priv;
 410		else if (temp_drm_priv->data->third_len)
 411			all_drm_priv[CRTC_THIRD] = temp_drm_priv;
 412
 413		if (temp_drm_priv->mtk_drm_bound)
 414			cnt++;
 415
 416		if (cnt == MAX_CRTC) {
 417			of_node_put(node);
 418			break;
 419		}
 420	}
 421
 422	if (drm_priv->data->mmsys_dev_num == cnt) {
 423		for (i = 0; i < cnt; i++)
 424			for (j = 0; j < cnt; j++)
 425				all_drm_priv[j]->all_drm_private[i] = all_drm_priv[i];
 426
 427		return true;
 428	}
 429
 430	return false;
 431}
 432
 433static bool mtk_drm_find_mmsys_comp(struct mtk_drm_private *private, int comp_id)
 434{
 435	const struct mtk_mmsys_driver_data *drv_data = private->data;
 436	int i;
 437
 438	if (drv_data->main_path)
 439		for (i = 0; i < drv_data->main_len; i++)
 440			if (drv_data->main_path[i] == comp_id)
 441				return true;
 442
 443	if (drv_data->ext_path)
 444		for (i = 0; i < drv_data->ext_len; i++)
 445			if (drv_data->ext_path[i] == comp_id)
 446				return true;
 447
 448	if (drv_data->third_path)
 449		for (i = 0; i < drv_data->third_len; i++)
 450			if (drv_data->third_path[i] == comp_id)
 451				return true;
 452
 453	if (drv_data->num_conn_routes)
 454		for (i = 0; i < drv_data->num_conn_routes; i++)
 455			if (drv_data->conn_routes[i].route_ddp == comp_id)
 456				return true;
 457
 458	return false;
 459}
 460
 461static int mtk_drm_kms_init(struct drm_device *drm)
 462{
 463	struct mtk_drm_private *private = drm->dev_private;
 464	struct mtk_drm_private *priv_n;
 465	struct device *dma_dev = NULL;
 466	struct drm_crtc *crtc;
 467	int ret, i, j;
 468
 469	if (drm_firmware_drivers_only())
 470		return -ENODEV;
 471
 472	ret = drmm_mode_config_init(drm);
 473	if (ret)
 474		return ret;
 475
 476	drm->mode_config.min_width = 64;
 477	drm->mode_config.min_height = 64;
 478
 479	/*
 480	 * set max width and height as default value(4096x4096).
 481	 * this value would be used to check framebuffer size limitation
 482	 * at drm_mode_addfb().
 483	 */
 484	drm->mode_config.max_width = 4096;
 485	drm->mode_config.max_height = 4096;
 486	drm->mode_config.funcs = &mtk_drm_mode_config_funcs;
 487	drm->mode_config.helper_private = &mtk_drm_mode_config_helpers;
 488
 489	for (i = 0; i < private->data->mmsys_dev_num; i++) {
 490		drm->dev_private = private->all_drm_private[i];
 491		ret = component_bind_all(private->all_drm_private[i]->dev, drm);
 492		if (ret) {
 493			while (--i >= 0)
 494				component_unbind_all(private->all_drm_private[i]->dev, drm);
 495			return ret;
 496		}
 497	}
 498
 499	/*
 500	 * Ensure internal panels are at the top of the connector list before
 501	 * crtc creation.
 502	 */
 503	drm_helper_move_panel_connectors_to_head(drm);
 504
 505	/*
 506	 * 1. We currently support two fixed data streams, each optional,
 507	 *    and each statically assigned to a crtc:
 508	 *    OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0 ...
 509	 * 2. For multi mmsys architecture, crtc path data are located in
 510	 *    different drm private data structures. Loop through crtc index to
 511	 *    create crtc from the main path and then ext_path and finally the
 512	 *    third path.
 513	 */
 514	for (i = 0; i < MAX_CRTC; i++) {
 515		for (j = 0; j < private->data->mmsys_dev_num; j++) {
 516			priv_n = private->all_drm_private[j];
 517
 518			if (priv_n->data->max_width)
 519				drm->mode_config.max_width = priv_n->data->max_width;
 520
 521			if (priv_n->data->min_width)
 522				drm->mode_config.min_width = priv_n->data->min_width;
 523
 524			if (priv_n->data->min_height)
 525				drm->mode_config.min_height = priv_n->data->min_height;
 526
 527			if (i == CRTC_MAIN && priv_n->data->main_len) {
 528				ret = mtk_crtc_create(drm, priv_n->data->main_path,
 529						      priv_n->data->main_len, j,
 530						      priv_n->data->conn_routes,
 531						      priv_n->data->num_conn_routes);
 532				if (ret)
 533					goto err_component_unbind;
 534
 535				continue;
 536			} else if (i == CRTC_EXT && priv_n->data->ext_len) {
 537				ret = mtk_crtc_create(drm, priv_n->data->ext_path,
 538						      priv_n->data->ext_len, j, NULL, 0);
 539				if (ret)
 540					goto err_component_unbind;
 541
 542				continue;
 543			} else if (i == CRTC_THIRD && priv_n->data->third_len) {
 544				ret = mtk_crtc_create(drm, priv_n->data->third_path,
 545						      priv_n->data->third_len, j, NULL, 0);
 546				if (ret)
 547					goto err_component_unbind;
 548
 549				continue;
 550			}
 551		}
 552	}
 553
 554	/* IGT will check if the cursor size is configured */
 555	drm->mode_config.cursor_width = 512;
 556	drm->mode_config.cursor_height = 512;
 557
 558	/* Use OVL device for all DMA memory allocations */
 559	crtc = drm_crtc_from_index(drm, 0);
 560	if (crtc)
 561		dma_dev = mtk_crtc_dma_dev_get(crtc);
 562	if (!dma_dev) {
 563		ret = -ENODEV;
 564		dev_err(drm->dev, "Need at least one OVL device\n");
 565		goto err_component_unbind;
 566	}
 567
 568	for (i = 0; i < private->data->mmsys_dev_num; i++)
 569		private->all_drm_private[i]->dma_dev = dma_dev;
 570
 571	/*
 572	 * Configure the DMA segment size to make sure we get contiguous IOVA
 573	 * when importing PRIME buffers.
 574	 */
 575	dma_set_max_seg_size(dma_dev, UINT_MAX);
 576
 577	ret = drm_vblank_init(drm, MAX_CRTC);
 578	if (ret < 0)
 579		goto err_component_unbind;
 580
 581	drm_kms_helper_poll_init(drm);
 582	drm_mode_config_reset(drm);
 583
 584	return 0;
 585
 586err_component_unbind:
 587	for (i = 0; i < private->data->mmsys_dev_num; i++)
 588		component_unbind_all(private->all_drm_private[i]->dev, drm);
 589
 590	return ret;
 591}
 592
 593static void mtk_drm_kms_deinit(struct drm_device *drm)
 594{
 595	drm_kms_helper_poll_fini(drm);
 596	drm_atomic_helper_shutdown(drm);
 597
 598	component_unbind_all(drm->dev, drm);
 599}
 600
 601DEFINE_DRM_GEM_FOPS(mtk_drm_fops);
 602
 603/*
 604 * We need to override this because the device used to import the memory is
 605 * not dev->dev, as drm_gem_prime_import() expects.
 606 */
 607static struct drm_gem_object *mtk_gem_prime_import(struct drm_device *dev,
 608						   struct dma_buf *dma_buf)
 609{
 610	struct mtk_drm_private *private = dev->dev_private;
 611
 612	return drm_gem_prime_import_dev(dev, dma_buf, private->dma_dev);
 613}
 614
 615static const struct drm_driver mtk_drm_driver = {
 616	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
 617
 618	.dumb_create = mtk_gem_dumb_create,
 619	DRM_FBDEV_DMA_DRIVER_OPS,
 620
 621	.gem_prime_import = mtk_gem_prime_import,
 622	.gem_prime_import_sg_table = mtk_gem_prime_import_sg_table,
 623	.fops = &mtk_drm_fops,
 624
 625	.name = DRIVER_NAME,
 626	.desc = DRIVER_DESC,
 627	.major = DRIVER_MAJOR,
 628	.minor = DRIVER_MINOR,
 629};
 630
 631static int compare_dev(struct device *dev, void *data)
 632{
 633	return dev == (struct device *)data;
 634}
 635
 636static int mtk_drm_bind(struct device *dev)
 637{
 638	struct mtk_drm_private *private = dev_get_drvdata(dev);
 639	struct platform_device *pdev;
 640	struct drm_device *drm;
 641	int ret, i;
 642
 643	pdev = of_find_device_by_node(private->mutex_node);
 644	if (!pdev) {
 645		dev_err(dev, "Waiting for disp-mutex device %pOF\n",
 646			private->mutex_node);
 647		of_node_put(private->mutex_node);
 648		return -EPROBE_DEFER;
 649	}
 650
 651	private->mutex_dev = &pdev->dev;
 652	private->mtk_drm_bound = true;
 653	private->dev = dev;
 654
 655	if (!mtk_drm_get_all_drm_priv(dev))
 656		return 0;
 657
 658	drm = drm_dev_alloc(&mtk_drm_driver, dev);
 659	if (IS_ERR(drm)) {
 660		ret = PTR_ERR(drm);
 661		goto err_put_dev;
 662	}
 663
 664	private->drm_master = true;
 665	drm->dev_private = private;
 666	for (i = 0; i < private->data->mmsys_dev_num; i++)
 667		private->all_drm_private[i]->drm = drm;
 668
 669	ret = mtk_drm_kms_init(drm);
 670	if (ret < 0)
 671		goto err_free;
 672
 673	ret = drm_dev_register(drm, 0);
 674	if (ret < 0)
 675		goto err_deinit;
 676
 677	drm_client_setup(drm, NULL);
 678
 679	return 0;
 680
 681err_deinit:
 682	mtk_drm_kms_deinit(drm);
 683err_free:
 684	private->drm = NULL;
 685	drm_dev_put(drm);
 686	for (i = 0; i < private->data->mmsys_dev_num; i++)
 687		private->all_drm_private[i]->drm = NULL;
 688err_put_dev:
 689	put_device(private->mutex_dev);
 690	return ret;
 691}
 692
 693static void mtk_drm_unbind(struct device *dev)
 694{
 695	struct mtk_drm_private *private = dev_get_drvdata(dev);
 696
 697	/* for multi mmsys dev, unregister drm dev in mmsys master */
 698	if (private->drm_master) {
 699		drm_dev_unregister(private->drm);
 700		mtk_drm_kms_deinit(private->drm);
 701		drm_dev_put(private->drm);
 702		put_device(private->mutex_dev);
 703	}
 704	private->mtk_drm_bound = false;
 705	private->drm_master = false;
 706	private->drm = NULL;
 707}
 708
 709static const struct component_master_ops mtk_drm_ops = {
 710	.bind		= mtk_drm_bind,
 711	.unbind		= mtk_drm_unbind,
 712};
 713
 714static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
 715	{ .compatible = "mediatek,mt8167-disp-aal",
 716	  .data = (void *)MTK_DISP_AAL},
 717	{ .compatible = "mediatek,mt8173-disp-aal",
 718	  .data = (void *)MTK_DISP_AAL},
 719	{ .compatible = "mediatek,mt8183-disp-aal",
 720	  .data = (void *)MTK_DISP_AAL},
 721	{ .compatible = "mediatek,mt8192-disp-aal",
 722	  .data = (void *)MTK_DISP_AAL},
 723	{ .compatible = "mediatek,mt8167-disp-ccorr",
 724	  .data = (void *)MTK_DISP_CCORR },
 725	{ .compatible = "mediatek,mt8183-disp-ccorr",
 726	  .data = (void *)MTK_DISP_CCORR },
 727	{ .compatible = "mediatek,mt8192-disp-ccorr",
 728	  .data = (void *)MTK_DISP_CCORR },
 729	{ .compatible = "mediatek,mt2701-disp-color",
 730	  .data = (void *)MTK_DISP_COLOR },
 731	{ .compatible = "mediatek,mt8167-disp-color",
 732	  .data = (void *)MTK_DISP_COLOR },
 733	{ .compatible = "mediatek,mt8173-disp-color",
 734	  .data = (void *)MTK_DISP_COLOR },
 735	{ .compatible = "mediatek,mt8167-disp-dither",
 736	  .data = (void *)MTK_DISP_DITHER },
 737	{ .compatible = "mediatek,mt8183-disp-dither",
 738	  .data = (void *)MTK_DISP_DITHER },
 739	{ .compatible = "mediatek,mt8195-disp-dsc",
 740	  .data = (void *)MTK_DISP_DSC },
 741	{ .compatible = "mediatek,mt8167-disp-gamma",
 742	  .data = (void *)MTK_DISP_GAMMA, },
 743	{ .compatible = "mediatek,mt8173-disp-gamma",
 744	  .data = (void *)MTK_DISP_GAMMA, },
 745	{ .compatible = "mediatek,mt8183-disp-gamma",
 746	  .data = (void *)MTK_DISP_GAMMA, },
 747	{ .compatible = "mediatek,mt8195-disp-gamma",
 748	  .data = (void *)MTK_DISP_GAMMA, },
 749	{ .compatible = "mediatek,mt8195-disp-merge",
 750	  .data = (void *)MTK_DISP_MERGE },
 751	{ .compatible = "mediatek,mt2701-disp-mutex",
 752	  .data = (void *)MTK_DISP_MUTEX },
 753	{ .compatible = "mediatek,mt2712-disp-mutex",
 754	  .data = (void *)MTK_DISP_MUTEX },
 755	{ .compatible = "mediatek,mt8167-disp-mutex",
 756	  .data = (void *)MTK_DISP_MUTEX },
 757	{ .compatible = "mediatek,mt8173-disp-mutex",
 758	  .data = (void *)MTK_DISP_MUTEX },
 759	{ .compatible = "mediatek,mt8183-disp-mutex",
 760	  .data = (void *)MTK_DISP_MUTEX },
 761	{ .compatible = "mediatek,mt8186-disp-mutex",
 762	  .data = (void *)MTK_DISP_MUTEX },
 763	{ .compatible = "mediatek,mt8188-disp-mutex",
 764	  .data = (void *)MTK_DISP_MUTEX },
 765	{ .compatible = "mediatek,mt8192-disp-mutex",
 766	  .data = (void *)MTK_DISP_MUTEX },
 767	{ .compatible = "mediatek,mt8195-disp-mutex",
 768	  .data = (void *)MTK_DISP_MUTEX },
 769	{ .compatible = "mediatek,mt8365-disp-mutex",
 770	  .data = (void *)MTK_DISP_MUTEX },
 771	{ .compatible = "mediatek,mt8173-disp-od",
 772	  .data = (void *)MTK_DISP_OD },
 773	{ .compatible = "mediatek,mt2701-disp-ovl",
 774	  .data = (void *)MTK_DISP_OVL },
 775	{ .compatible = "mediatek,mt8167-disp-ovl",
 776	  .data = (void *)MTK_DISP_OVL },
 777	{ .compatible = "mediatek,mt8173-disp-ovl",
 778	  .data = (void *)MTK_DISP_OVL },
 779	{ .compatible = "mediatek,mt8183-disp-ovl",
 780	  .data = (void *)MTK_DISP_OVL },
 781	{ .compatible = "mediatek,mt8192-disp-ovl",
 782	  .data = (void *)MTK_DISP_OVL },
 783	{ .compatible = "mediatek,mt8195-disp-ovl",
 784	  .data = (void *)MTK_DISP_OVL },
 785	{ .compatible = "mediatek,mt8183-disp-ovl-2l",
 786	  .data = (void *)MTK_DISP_OVL_2L },
 787	{ .compatible = "mediatek,mt8192-disp-ovl-2l",
 788	  .data = (void *)MTK_DISP_OVL_2L },
 789	{ .compatible = "mediatek,mt8192-disp-postmask",
 790	  .data = (void *)MTK_DISP_POSTMASK },
 791	{ .compatible = "mediatek,mt2701-disp-pwm",
 792	  .data = (void *)MTK_DISP_BLS },
 793	{ .compatible = "mediatek,mt8167-disp-pwm",
 794	  .data = (void *)MTK_DISP_PWM },
 795	{ .compatible = "mediatek,mt8173-disp-pwm",
 796	  .data = (void *)MTK_DISP_PWM },
 797	{ .compatible = "mediatek,mt2701-disp-rdma",
 798	  .data = (void *)MTK_DISP_RDMA },
 799	{ .compatible = "mediatek,mt8167-disp-rdma",
 800	  .data = (void *)MTK_DISP_RDMA },
 801	{ .compatible = "mediatek,mt8173-disp-rdma",
 802	  .data = (void *)MTK_DISP_RDMA },
 803	{ .compatible = "mediatek,mt8183-disp-rdma",
 804	  .data = (void *)MTK_DISP_RDMA },
 805	{ .compatible = "mediatek,mt8195-disp-rdma",
 806	  .data = (void *)MTK_DISP_RDMA },
 807	{ .compatible = "mediatek,mt8173-disp-ufoe",
 808	  .data = (void *)MTK_DISP_UFOE },
 809	{ .compatible = "mediatek,mt8173-disp-wdma",
 810	  .data = (void *)MTK_DISP_WDMA },
 811	{ .compatible = "mediatek,mt2701-dpi",
 812	  .data = (void *)MTK_DPI },
 813	{ .compatible = "mediatek,mt8167-dsi",
 814	  .data = (void *)MTK_DSI },
 815	{ .compatible = "mediatek,mt8173-dpi",
 816	  .data = (void *)MTK_DPI },
 817	{ .compatible = "mediatek,mt8183-dpi",
 818	  .data = (void *)MTK_DPI },
 819	{ .compatible = "mediatek,mt8186-dpi",
 820	  .data = (void *)MTK_DPI },
 821	{ .compatible = "mediatek,mt8188-dp-intf",
 822	  .data = (void *)MTK_DP_INTF },
 823	{ .compatible = "mediatek,mt8192-dpi",
 824	  .data = (void *)MTK_DPI },
 825	{ .compatible = "mediatek,mt8195-dp-intf",
 826	  .data = (void *)MTK_DP_INTF },
 827	{ .compatible = "mediatek,mt8195-dpi",
 828	  .data = (void *)MTK_DPI },
 829	{ .compatible = "mediatek,mt2701-dsi",
 830	  .data = (void *)MTK_DSI },
 831	{ .compatible = "mediatek,mt8173-dsi",
 832	  .data = (void *)MTK_DSI },
 833	{ .compatible = "mediatek,mt8183-dsi",
 834	  .data = (void *)MTK_DSI },
 835	{ .compatible = "mediatek,mt8186-dsi",
 836	  .data = (void *)MTK_DSI },
 837	{ .compatible = "mediatek,mt8188-dsi",
 838	  .data = (void *)MTK_DSI },
 839	{ }
 840};
 841
 842static int mtk_drm_of_get_ddp_comp_type(struct device_node *node, enum mtk_ddp_comp_type *ctype)
 843{
 844	const struct of_device_id *of_id = of_match_node(mtk_ddp_comp_dt_ids, node);
 845
 846	if (!of_id)
 847		return -EINVAL;
 848
 849	*ctype = (enum mtk_ddp_comp_type)((uintptr_t)of_id->data);
 850
 851	return 0;
 852}
 853
 854static int mtk_drm_of_get_ddp_ep_cid(struct device_node *node,
 855				     int output_port, enum mtk_crtc_path crtc_path,
 856				     struct device_node **next, unsigned int *cid)
 857{
 858	struct device_node *ep_dev_node, *ep_out;
 859	enum mtk_ddp_comp_type comp_type;
 860	int ret;
 861
 862	ep_out = of_graph_get_endpoint_by_regs(node, output_port, crtc_path);
 863	if (!ep_out)
 864		return -ENOENT;
 865
 866	ep_dev_node = of_graph_get_remote_port_parent(ep_out);
 867	of_node_put(ep_out);
 868	if (!ep_dev_node)
 869		return -EINVAL;
 870
 871	/*
 872	 * Pass the next node pointer regardless of failures in the later code
 873	 * so that if this function is called in a loop it will walk through all
 874	 * of the subsequent endpoints anyway.
 875	 */
 876	*next = ep_dev_node;
 877
 878	if (!of_device_is_available(ep_dev_node))
 879		return -ENODEV;
 880
 881	ret = mtk_drm_of_get_ddp_comp_type(ep_dev_node, &comp_type);
 882	if (ret) {
 883		if (mtk_ovl_adaptor_is_comp_present(ep_dev_node)) {
 884			*cid = (unsigned int)DDP_COMPONENT_DRM_OVL_ADAPTOR;
 885			return 0;
 886		}
 887		return ret;
 888	}
 889
 890	ret = mtk_ddp_comp_get_id(ep_dev_node, comp_type);
 891	if (ret < 0)
 892		return ret;
 893
 894	/* All ok! Pass the Component ID to the caller. */
 895	*cid = (unsigned int)ret;
 896
 897	return 0;
 898}
 899
 900/**
 901 * mtk_drm_of_ddp_path_build_one - Build a Display HW Pipeline for a CRTC Path
 902 * @dev:          The mediatek-drm device
 903 * @cpath:        CRTC Path relative to a VDO or MMSYS
 904 * @out_path:     Pointer to an array that will contain the new pipeline
 905 * @out_path_len: Number of entries in the pipeline array
 906 *
 907 * MediaTek SoCs can use different DDP hardware pipelines (or paths) depending
 908 * on the board-specific desired display configuration; this function walks
 909 * through all of the output endpoints starting from a VDO or MMSYS hardware
 910 * instance and builds the right pipeline as specified in device trees.
 911 *
 912 * Return:
 913 * * %0       - Display HW Pipeline successfully built and validated
 914 * * %-ENOENT - Display pipeline was not specified in device tree
 915 * * %-EINVAL - Display pipeline built but validation failed
 916 * * %-ENOMEM - Failure to allocate pipeline array to pass to the caller
 917 */
 918static int mtk_drm_of_ddp_path_build_one(struct device *dev, enum mtk_crtc_path cpath,
 919					 const unsigned int **out_path,
 920					 unsigned int *out_path_len)
 921{
 922	struct device_node *next = NULL, *prev, *vdo = dev->parent->of_node;
 923	unsigned int temp_path[DDP_COMPONENT_DRM_ID_MAX] = { 0 };
 924	unsigned int *final_ddp_path;
 925	unsigned short int idx = 0;
 926	bool ovl_adaptor_comp_added = false;
 927	int ret;
 928
 929	/* Get the first entry for the temp_path array */
 930	ret = mtk_drm_of_get_ddp_ep_cid(vdo, 0, cpath, &next, &temp_path[idx]);
 931	if (ret) {
 932		if (next && temp_path[idx] == DDP_COMPONENT_DRM_OVL_ADAPTOR) {
 933			dev_dbg(dev, "Adding OVL Adaptor for %pOF\n", next);
 934			ovl_adaptor_comp_added = true;
 935		} else {
 936			if (next)
 937				dev_err(dev, "Invalid component %pOF\n", next);
 938			else
 939				dev_err(dev, "Cannot find first endpoint for path %d\n", cpath);
 940
 941			return ret;
 942		}
 943	}
 944	idx++;
 945
 946	/*
 947	 * Walk through port outputs until we reach the last valid mediatek-drm component.
 948	 * To be valid, this must end with an "invalid" component that is a display node.
 949	 */
 950	do {
 951		prev = next;
 952		ret = mtk_drm_of_get_ddp_ep_cid(next, 1, cpath, &next, &temp_path[idx]);
 953		of_node_put(prev);
 954		if (ret) {
 955			of_node_put(next);
 956			break;
 957		}
 958
 959		/*
 960		 * If this is an OVL adaptor exclusive component and one of those
 961		 * was already added, don't add another instance of the generic
 962		 * DDP_COMPONENT_OVL_ADAPTOR, as this is used only to decide whether
 963		 * to probe that component master driver of which only one instance
 964		 * is needed and possible.
 965		 */
 966		if (temp_path[idx] == DDP_COMPONENT_DRM_OVL_ADAPTOR) {
 967			if (!ovl_adaptor_comp_added)
 968				ovl_adaptor_comp_added = true;
 969			else
 970				idx--;
 971		}
 972	} while (++idx < DDP_COMPONENT_DRM_ID_MAX);
 973
 974	/*
 975	 * The device component might not be enabled: in that case, don't
 976	 * check the last entry and just report that the device is missing.
 977	 */
 978	if (ret == -ENODEV)
 979		return ret;
 980
 981	/* If the last entry is not a final display output, the configuration is wrong */
 982	switch (temp_path[idx - 1]) {
 983	case DDP_COMPONENT_DP_INTF0:
 984	case DDP_COMPONENT_DP_INTF1:
 985	case DDP_COMPONENT_DPI0:
 986	case DDP_COMPONENT_DPI1:
 987	case DDP_COMPONENT_DSI0:
 988	case DDP_COMPONENT_DSI1:
 989	case DDP_COMPONENT_DSI2:
 990	case DDP_COMPONENT_DSI3:
 991		break;
 992	default:
 993		dev_err(dev, "Invalid display hw pipeline. Last component: %d (ret=%d)\n",
 994			temp_path[idx - 1], ret);
 995		return -EINVAL;
 996	}
 997
 998	final_ddp_path = devm_kmemdup(dev, temp_path, idx * sizeof(temp_path[0]), GFP_KERNEL);
 999	if (!final_ddp_path)
1000		return -ENOMEM;
1001
1002	dev_dbg(dev, "Display HW Pipeline built with %d components.\n", idx);
1003
1004	/* Pipeline built! */
1005	*out_path = final_ddp_path;
1006	*out_path_len = idx;
1007
1008	return 0;
1009}
1010
1011static int mtk_drm_of_ddp_path_build(struct device *dev, struct device_node *node,
1012				     struct mtk_mmsys_driver_data *data)
1013{
1014	struct device_node *ep_node;
1015	struct of_endpoint of_ep;
1016	bool output_present[MAX_CRTC] = { false };
1017	int ret;
1018
1019	for_each_endpoint_of_node(node, ep_node) {
1020		ret = of_graph_parse_endpoint(ep_node, &of_ep);
1021		if (ret) {
1022			dev_err_probe(dev, ret, "Cannot parse endpoint\n");
1023			break;
1024		}
1025
1026		if (of_ep.id >= MAX_CRTC) {
1027			ret = dev_err_probe(dev, -EINVAL,
1028					    "Invalid endpoint%u number\n", of_ep.port);
1029			break;
1030		}
1031
1032		output_present[of_ep.id] = true;
1033	}
1034
1035	if (ret) {
1036		of_node_put(ep_node);
1037		return ret;
1038	}
1039
1040	if (output_present[CRTC_MAIN]) {
1041		ret = mtk_drm_of_ddp_path_build_one(dev, CRTC_MAIN,
1042						    &data->main_path, &data->main_len);
1043		if (ret && ret != -ENODEV)
1044			return ret;
1045	}
1046
1047	if (output_present[CRTC_EXT]) {
1048		ret = mtk_drm_of_ddp_path_build_one(dev, CRTC_EXT,
1049						    &data->ext_path, &data->ext_len);
1050		if (ret && ret != -ENODEV)
1051			return ret;
1052	}
1053
1054	if (output_present[CRTC_THIRD]) {
1055		ret = mtk_drm_of_ddp_path_build_one(dev, CRTC_THIRD,
1056						    &data->third_path, &data->third_len);
1057		if (ret && ret != -ENODEV)
1058			return ret;
1059	}
1060
1061	return 0;
1062}
1063
1064static int mtk_drm_probe(struct platform_device *pdev)
1065{
1066	struct device *dev = &pdev->dev;
1067	struct device_node *phandle = dev->parent->of_node;
1068	const struct of_device_id *of_id;
1069	struct mtk_drm_private *private;
1070	struct mtk_mmsys_driver_data *mtk_drm_data;
1071	struct device_node *node;
1072	struct component_match *match = NULL;
1073	struct platform_device *ovl_adaptor;
1074	int ret;
1075	int i;
1076
1077	private = devm_kzalloc(dev, sizeof(*private), GFP_KERNEL);
1078	if (!private)
1079		return -ENOMEM;
1080
1081	private->mmsys_dev = dev->parent;
1082	if (!private->mmsys_dev) {
1083		dev_err(dev, "Failed to get MMSYS device\n");
1084		return -ENODEV;
1085	}
1086
1087	of_id = of_match_node(mtk_drm_of_ids, phandle);
1088	if (!of_id)
1089		return -ENODEV;
1090
1091	mtk_drm_data = (struct mtk_mmsys_driver_data *)of_id->data;
1092	if (!mtk_drm_data)
1093		return -EINVAL;
1094
1095	/* Try to build the display pipeline from devicetree graphs */
1096	if (of_graph_is_present(phandle)) {
1097		dev_dbg(dev, "Building display pipeline for MMSYS %u\n",
1098			mtk_drm_data->mmsys_id);
1099		private->data = devm_kmemdup(dev, mtk_drm_data,
1100					     sizeof(*mtk_drm_data), GFP_KERNEL);
1101		if (!private->data)
1102			return -ENOMEM;
1103
1104		ret = mtk_drm_of_ddp_path_build(dev, phandle, private->data);
1105		if (ret)
1106			return ret;
1107	} else {
1108		/* No devicetree graphs support: go with hardcoded paths if present */
1109		dev_dbg(dev, "Using hardcoded paths for MMSYS %u\n", mtk_drm_data->mmsys_id);
1110		private->data = mtk_drm_data;
1111	}
1112
1113	private->all_drm_private = devm_kmalloc_array(dev, private->data->mmsys_dev_num,
1114						      sizeof(*private->all_drm_private),
1115						      GFP_KERNEL);
1116	if (!private->all_drm_private)
1117		return -ENOMEM;
1118
1119	/* Bringup ovl_adaptor */
1120	if (mtk_drm_find_mmsys_comp(private, DDP_COMPONENT_DRM_OVL_ADAPTOR)) {
1121		ovl_adaptor = platform_device_register_data(dev, "mediatek-disp-ovl-adaptor",
1122							    PLATFORM_DEVID_AUTO,
1123							    (void *)private->mmsys_dev,
1124							    sizeof(*private->mmsys_dev));
1125		private->ddp_comp[DDP_COMPONENT_DRM_OVL_ADAPTOR].dev = &ovl_adaptor->dev;
1126		mtk_ddp_comp_init(dev, NULL, &private->ddp_comp[DDP_COMPONENT_DRM_OVL_ADAPTOR],
1127				  DDP_COMPONENT_DRM_OVL_ADAPTOR);
1128		component_match_add(dev, &match, compare_dev, &ovl_adaptor->dev);
1129	}
1130
1131	/* Iterate over sibling DISP function blocks */
1132	for_each_child_of_node(phandle->parent, node) {
1133		enum mtk_ddp_comp_type comp_type;
1134		int comp_id;
1135
1136		ret = mtk_drm_of_get_ddp_comp_type(node, &comp_type);
1137		if (ret)
1138			continue;
1139
1140		if (!of_device_is_available(node)) {
1141			dev_dbg(dev, "Skipping disabled component %pOF\n",
1142				node);
1143			continue;
1144		}
1145
1146		if (comp_type == MTK_DISP_MUTEX) {
1147			int id;
1148
1149			id = of_alias_get_id(node, "mutex");
1150			if (id < 0 || id == private->data->mmsys_id) {
1151				private->mutex_node = of_node_get(node);
1152				dev_dbg(dev, "get mutex for mmsys %d", private->data->mmsys_id);
1153			}
1154			continue;
1155		}
1156
1157		comp_id = mtk_ddp_comp_get_id(node, comp_type);
1158		if (comp_id < 0) {
1159			dev_warn(dev, "Skipping unknown component %pOF\n",
1160				 node);
1161			continue;
1162		}
1163
1164		if (!mtk_drm_find_mmsys_comp(private, comp_id))
1165			continue;
1166
1167		private->comp_node[comp_id] = of_node_get(node);
1168
1169		/*
1170		 * Currently only the AAL, CCORR, COLOR, GAMMA, MERGE, OVL, RDMA, DSI, and DPI
1171		 * blocks have separate component platform drivers and initialize their own
1172		 * DDP component structure. The others are initialized here.
1173		 */
1174		if (comp_type == MTK_DISP_AAL ||
1175		    comp_type == MTK_DISP_CCORR ||
1176		    comp_type == MTK_DISP_COLOR ||
1177		    comp_type == MTK_DISP_GAMMA ||
1178		    comp_type == MTK_DISP_MERGE ||
1179		    comp_type == MTK_DISP_OVL ||
1180		    comp_type == MTK_DISP_OVL_2L ||
1181		    comp_type == MTK_DISP_OVL_ADAPTOR ||
1182		    comp_type == MTK_DISP_RDMA ||
1183		    comp_type == MTK_DP_INTF ||
1184		    comp_type == MTK_DPI ||
1185		    comp_type == MTK_DSI) {
1186			dev_info(dev, "Adding component match for %pOF\n",
1187				 node);
1188			drm_of_component_match_add(dev, &match, component_compare_of,
1189						   node);
1190		}
1191
1192		ret = mtk_ddp_comp_init(dev, node, &private->ddp_comp[comp_id], comp_id);
1193		if (ret) {
1194			of_node_put(node);
1195			goto err_node;
1196		}
1197	}
1198
1199	if (!private->mutex_node) {
1200		dev_err(dev, "Failed to find disp-mutex node\n");
1201		ret = -ENODEV;
1202		goto err_node;
1203	}
1204
1205	pm_runtime_enable(dev);
1206
1207	platform_set_drvdata(pdev, private);
1208
1209	ret = component_master_add_with_match(dev, &mtk_drm_ops, match);
1210	if (ret)
1211		goto err_pm;
1212
1213	return 0;
1214
1215err_pm:
1216	pm_runtime_disable(dev);
1217err_node:
1218	of_node_put(private->mutex_node);
1219	for (i = 0; i < DDP_COMPONENT_DRM_ID_MAX; i++)
1220		of_node_put(private->comp_node[i]);
1221	return ret;
1222}
1223
1224static void mtk_drm_remove(struct platform_device *pdev)
1225{
1226	struct mtk_drm_private *private = platform_get_drvdata(pdev);
1227	int i;
1228
1229	component_master_del(&pdev->dev, &mtk_drm_ops);
1230	pm_runtime_disable(&pdev->dev);
1231	of_node_put(private->mutex_node);
1232	for (i = 0; i < DDP_COMPONENT_DRM_ID_MAX; i++)
1233		of_node_put(private->comp_node[i]);
1234}
1235
1236static void mtk_drm_shutdown(struct platform_device *pdev)
1237{
1238	struct mtk_drm_private *private = platform_get_drvdata(pdev);
1239
1240	drm_atomic_helper_shutdown(private->drm);
1241}
1242
1243static int mtk_drm_sys_prepare(struct device *dev)
1244{
1245	struct mtk_drm_private *private = dev_get_drvdata(dev);
1246	struct drm_device *drm = private->drm;
1247
1248	if (private->drm_master)
1249		return drm_mode_config_helper_suspend(drm);
1250	else
1251		return 0;
1252}
1253
1254static void mtk_drm_sys_complete(struct device *dev)
1255{
1256	struct mtk_drm_private *private = dev_get_drvdata(dev);
1257	struct drm_device *drm = private->drm;
1258	int ret = 0;
1259
1260	if (private->drm_master)
1261		ret = drm_mode_config_helper_resume(drm);
1262	if (ret)
1263		dev_err(dev, "Failed to resume\n");
1264}
1265
1266static const struct dev_pm_ops mtk_drm_pm_ops = {
1267	.prepare = mtk_drm_sys_prepare,
1268	.complete = mtk_drm_sys_complete,
1269};
1270
1271static struct platform_driver mtk_drm_platform_driver = {
1272	.probe	= mtk_drm_probe,
1273	.remove = mtk_drm_remove,
1274	.shutdown = mtk_drm_shutdown,
1275	.driver	= {
1276		.name	= "mediatek-drm",
1277		.pm     = &mtk_drm_pm_ops,
1278	},
1279};
1280
1281static struct platform_driver * const mtk_drm_drivers[] = {
1282	&mtk_disp_aal_driver,
1283	&mtk_disp_ccorr_driver,
1284	&mtk_disp_color_driver,
1285	&mtk_disp_gamma_driver,
1286	&mtk_disp_merge_driver,
1287	&mtk_disp_ovl_adaptor_driver,
1288	&mtk_disp_ovl_driver,
1289	&mtk_disp_rdma_driver,
1290	&mtk_dpi_driver,
1291	&mtk_drm_platform_driver,
1292	&mtk_dsi_driver,
1293	&mtk_ethdr_driver,
1294	&mtk_mdp_rdma_driver,
1295	&mtk_padding_driver,
1296};
1297
1298static int __init mtk_drm_init(void)
1299{
1300	return platform_register_drivers(mtk_drm_drivers,
1301					 ARRAY_SIZE(mtk_drm_drivers));
1302}
1303
1304static void __exit mtk_drm_exit(void)
1305{
1306	platform_unregister_drivers(mtk_drm_drivers,
1307				    ARRAY_SIZE(mtk_drm_drivers));
1308}
1309
1310module_init(mtk_drm_init);
1311module_exit(mtk_drm_exit);
1312
1313MODULE_AUTHOR("YT SHEN <yt.shen@mediatek.com>");
1314MODULE_DESCRIPTION("Mediatek SoC DRM driver");
1315MODULE_LICENSE("GPL v2");
~/ Read-only file preview.