Linux Audio

Check our new training course

Linux kernel drivers training

Mar 31-Apr 9, 2025, special US time zones
Register
Loading...
v6.8
   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/drm_atomic.h>
  16#include <drm/drm_atomic_helper.h>
  17#include <drm/drm_drv.h>
  18#include <drm/drm_fbdev_generic.h>
  19#include <drm/drm_fourcc.h>
  20#include <drm/drm_gem.h>
  21#include <drm/drm_gem_framebuffer_helper.h>
  22#include <drm/drm_ioctl.h>
  23#include <drm/drm_of.h>
  24#include <drm/drm_probe_helper.h>
  25#include <drm/drm_vblank.h>
 
 
 
  26
  27#include "mtk_drm_crtc.h"
 
  28#include "mtk_drm_ddp_comp.h"
  29#include "mtk_drm_drv.h"
 
  30#include "mtk_drm_gem.h"
  31
  32#define DRIVER_NAME "mediatek"
  33#define DRIVER_DESC "Mediatek SoC DRM"
  34#define DRIVER_DATE "20150513"
  35#define DRIVER_MAJOR 1
  36#define DRIVER_MINOR 0
  37
  38static const struct drm_mode_config_helper_funcs mtk_drm_mode_config_helpers = {
  39	.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
  40};
  41
  42static struct drm_framebuffer *
  43mtk_drm_mode_fb_create(struct drm_device *dev,
  44		       struct drm_file *file,
  45		       const struct drm_mode_fb_cmd2 *cmd)
  46{
  47	const struct drm_format_info *info = drm_get_format_info(dev, cmd);
 
 
  48
  49	if (info->num_planes != 1)
  50		return ERR_PTR(-EINVAL);
 
 
 
  51
  52	return drm_gem_fb_create(dev, file, 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 = 1,
 297};
 298
 299static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = {
 300	.main_path = mt8192_mtk_ddp_main,
 301	.main_len = ARRAY_SIZE(mt8192_mtk_ddp_main),
 302	.ext_path = mt8192_mtk_ddp_ext,
 303	.ext_len = ARRAY_SIZE(mt8192_mtk_ddp_ext),
 304	.mmsys_dev_num = 1,
 305};
 306
 307static const struct mtk_mmsys_driver_data mt8195_vdosys0_driver_data = {
 308	.main_path = mt8195_mtk_ddp_main,
 309	.main_len = ARRAY_SIZE(mt8195_mtk_ddp_main),
 310	.mmsys_dev_num = 2,
 311};
 312
 313static const struct mtk_mmsys_driver_data mt8195_vdosys1_driver_data = {
 314	.ext_path = mt8195_mtk_ddp_ext,
 315	.ext_len = ARRAY_SIZE(mt8195_mtk_ddp_ext),
 316	.mmsys_id = 1,
 317	.mmsys_dev_num = 2,
 318};
 319
 320static const struct of_device_id mtk_drm_of_ids[] = {
 321	{ .compatible = "mediatek,mt2701-mmsys",
 322	  .data = &mt2701_mmsys_driver_data},
 323	{ .compatible = "mediatek,mt7623-mmsys",
 324	  .data = &mt7623_mmsys_driver_data},
 325	{ .compatible = "mediatek,mt2712-mmsys",
 326	  .data = &mt2712_mmsys_driver_data},
 327	{ .compatible = "mediatek,mt8167-mmsys",
 328	  .data = &mt8167_mmsys_driver_data},
 329	{ .compatible = "mediatek,mt8173-mmsys",
 330	  .data = &mt8173_mmsys_driver_data},
 331	{ .compatible = "mediatek,mt8183-mmsys",
 332	  .data = &mt8183_mmsys_driver_data},
 333	{ .compatible = "mediatek,mt8186-mmsys",
 334	  .data = &mt8186_mmsys_driver_data},
 335	{ .compatible = "mediatek,mt8188-vdosys0",
 336	  .data = &mt8188_vdosys0_driver_data},
 337	{ .compatible = "mediatek,mt8192-mmsys",
 338	  .data = &mt8192_mmsys_driver_data},
 339	{ .compatible = "mediatek,mt8195-mmsys",
 340	  .data = &mt8195_vdosys0_driver_data},
 341	{ .compatible = "mediatek,mt8195-vdosys0",
 342	  .data = &mt8195_vdosys0_driver_data},
 343	{ .compatible = "mediatek,mt8195-vdosys1",
 344	  .data = &mt8195_vdosys1_driver_data},
 345	{ }
 346};
 347MODULE_DEVICE_TABLE(of, mtk_drm_of_ids);
 348
 349static int mtk_drm_match(struct device *dev, void *data)
 350{
 351	if (!strncmp(dev_name(dev), "mediatek-drm", sizeof("mediatek-drm") - 1))
 352		return true;
 353	return false;
 354}
 355
 356static bool mtk_drm_get_all_drm_priv(struct device *dev)
 357{
 358	struct mtk_drm_private *drm_priv = dev_get_drvdata(dev);
 359	struct mtk_drm_private *all_drm_priv[MAX_CRTC];
 360	struct mtk_drm_private *temp_drm_priv;
 361	struct device_node *phandle = dev->parent->of_node;
 362	const struct of_device_id *of_id;
 363	struct device_node *node;
 364	struct device *drm_dev;
 365	unsigned int cnt = 0;
 366	int i, j;
 367
 368	for_each_child_of_node(phandle->parent, node) {
 369		struct platform_device *pdev;
 370
 371		of_id = of_match_node(mtk_drm_of_ids, node);
 372		if (!of_id)
 373			continue;
 374
 375		pdev = of_find_device_by_node(node);
 376		if (!pdev)
 377			continue;
 378
 379		drm_dev = device_find_child(&pdev->dev, NULL, mtk_drm_match);
 380		if (!drm_dev)
 381			continue;
 382
 383		temp_drm_priv = dev_get_drvdata(drm_dev);
 384		if (!temp_drm_priv)
 385			continue;
 386
 387		if (temp_drm_priv->data->main_len)
 388			all_drm_priv[CRTC_MAIN] = temp_drm_priv;
 389		else if (temp_drm_priv->data->ext_len)
 390			all_drm_priv[CRTC_EXT] = temp_drm_priv;
 391		else if (temp_drm_priv->data->third_len)
 392			all_drm_priv[CRTC_THIRD] = temp_drm_priv;
 393
 394		if (temp_drm_priv->mtk_drm_bound)
 395			cnt++;
 396
 397		if (cnt == MAX_CRTC)
 398			break;
 399	}
 400
 401	if (drm_priv->data->mmsys_dev_num == cnt) {
 402		for (i = 0; i < cnt; i++)
 403			for (j = 0; j < cnt; j++)
 404				all_drm_priv[j]->all_drm_private[i] = all_drm_priv[i];
 405
 406		return true;
 407	}
 408
 409	return false;
 410}
 411
 412static bool mtk_drm_find_mmsys_comp(struct mtk_drm_private *private, int comp_id)
 413{
 414	const struct mtk_mmsys_driver_data *drv_data = private->data;
 415	int i;
 416
 417	if (drv_data->main_path)
 418		for (i = 0; i < drv_data->main_len; i++)
 419			if (drv_data->main_path[i] == comp_id)
 420				return true;
 421
 422	if (drv_data->ext_path)
 423		for (i = 0; i < drv_data->ext_len; i++)
 424			if (drv_data->ext_path[i] == comp_id)
 425				return true;
 426
 427	if (drv_data->third_path)
 428		for (i = 0; i < drv_data->third_len; i++)
 429			if (drv_data->third_path[i] == comp_id)
 430				return true;
 431
 432	if (drv_data->num_conn_routes)
 433		for (i = 0; i < drv_data->num_conn_routes; i++)
 434			if (drv_data->conn_routes[i].route_ddp == comp_id)
 435				return true;
 436
 437	return false;
 438}
 439
 440static int mtk_drm_kms_init(struct drm_device *drm)
 441{
 442	struct mtk_drm_private *private = drm->dev_private;
 443	struct mtk_drm_private *priv_n;
 444	struct device *dma_dev = NULL;
 445	struct drm_crtc *crtc;
 446	int ret, i, j;
 447
 448	if (drm_firmware_drivers_only())
 449		return -ENODEV;
 450
 451	ret = drmm_mode_config_init(drm);
 452	if (ret)
 453		goto put_mutex_dev;
 
 
 
 
 
 
 
 454
 455	drm->mode_config.min_width = 64;
 456	drm->mode_config.min_height = 64;
 457
 458	/*
 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().
 462	 */
 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;
 467
 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);
 471		if (ret)
 472			goto put_mutex_dev;
 473	}
 474
 475	/*
 476	 * Ensure internal panels are at the top of the connector list before
 477	 * crtc creation.
 478	 */
 479	drm_helper_move_panel_connectors_to_head(drm);
 480
 481	/*
 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
 488	 *    third path.
 489	 */
 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];
 493
 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);
 499				if (ret)
 500					goto err_component_unbind;
 501
 502				continue;
 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);
 506				if (ret)
 507					goto err_component_unbind;
 508
 509				continue;
 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);
 513				if (ret)
 514					goto err_component_unbind;
 515
 516				continue;
 517			}
 518		}
 519	}
 520
 521	/* Use OVL device for all DMA memory allocations */
 522	crtc = drm_crtc_from_index(drm, 0);
 523	if (crtc)
 524		dma_dev = mtk_drm_crtc_dma_dev_get(crtc);
 525	if (!dma_dev) {
 526		ret = -ENODEV;
 527		dev_err(drm->dev, "Need at least one OVL device\n");
 528		goto err_component_unbind;
 529	}
 530
 531	for (i = 0; i < private->data->mmsys_dev_num; i++)
 532		private->all_drm_private[i]->dma_dev = dma_dev;
 533
 534	/*
 535	 * Configure the DMA segment size to make sure we get contiguous IOVA
 536	 * when importing PRIME buffers.
 
 537	 */
 538	ret = dma_set_max_seg_size(dma_dev, UINT_MAX);
 539	if (ret) {
 540		dev_err(dma_dev, "Failed to set DMA segment size\n");
 541		goto err_component_unbind;
 542	}
 543
 544	ret = drm_vblank_init(drm, MAX_CRTC);
 545	if (ret < 0)
 546		goto err_component_unbind;
 547
 548	drm_kms_helper_poll_init(drm);
 549	drm_mode_config_reset(drm);
 550
 551	return 0;
 552
 553err_component_unbind:
 554	for (i = 0; i < private->data->mmsys_dev_num; i++)
 555		component_unbind_all(private->all_drm_private[i]->dev, drm);
 556put_mutex_dev:
 557	for (i = 0; i < private->data->mmsys_dev_num; i++)
 558		put_device(private->all_drm_private[i]->mutex_dev);
 559
 560	return ret;
 561}
 562
 563static void mtk_drm_kms_deinit(struct drm_device *drm)
 564{
 565	drm_kms_helper_poll_fini(drm);
 566	drm_atomic_helper_shutdown(drm);
 567
 568	component_unbind_all(drm->dev, drm);
 
 569}
 570
 571DEFINE_DRM_GEM_FOPS(mtk_drm_fops);
 572
 573/*
 574 * We need to override this because the device used to import the memory is
 575 * not dev->dev, as drm_gem_prime_import() expects.
 576 */
 577static struct drm_gem_object *mtk_drm_gem_prime_import(struct drm_device *dev,
 578						       struct dma_buf *dma_buf)
 579{
 580	struct mtk_drm_private *private = dev->dev_private;
 581
 582	return drm_gem_prime_import_dev(dev, dma_buf, private->dma_dev);
 583}
 584
 585static const struct drm_driver mtk_drm_driver = {
 586	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
 587
 
 
 588	.dumb_create = mtk_drm_gem_dumb_create,
 589
 590	.gem_prime_import = mtk_drm_gem_prime_import,
 
 
 
 
 591	.gem_prime_import_sg_table = mtk_gem_prime_import_sg_table,
 
 592	.fops = &mtk_drm_fops,
 593
 594	.name = DRIVER_NAME,
 595	.desc = DRIVER_DESC,
 596	.date = DRIVER_DATE,
 597	.major = DRIVER_MAJOR,
 598	.minor = DRIVER_MINOR,
 599};
 600
 601static int compare_dev(struct device *dev, void *data)
 602{
 603	return dev == (struct device *)data;
 604}
 605
 606static int mtk_drm_bind(struct device *dev)
 607{
 608	struct mtk_drm_private *private = dev_get_drvdata(dev);
 609	struct platform_device *pdev;
 610	struct drm_device *drm;
 611	int ret, i;
 612
 613	pdev = of_find_device_by_node(private->mutex_node);
 614	if (!pdev) {
 615		dev_err(dev, "Waiting for disp-mutex device %pOF\n",
 616			private->mutex_node);
 617		of_node_put(private->mutex_node);
 618		return -EPROBE_DEFER;
 619	}
 620
 621	private->mutex_dev = &pdev->dev;
 622	private->mtk_drm_bound = true;
 623	private->dev = dev;
 624
 625	if (!mtk_drm_get_all_drm_priv(dev))
 626		return 0;
 627
 628	drm = drm_dev_alloc(&mtk_drm_driver, dev);
 629	if (IS_ERR(drm))
 630		return PTR_ERR(drm);
 631
 632	private->drm_master = true;
 633	drm->dev_private = private;
 634	for (i = 0; i < private->data->mmsys_dev_num; i++)
 635		private->all_drm_private[i]->drm = drm;
 636
 637	ret = mtk_drm_kms_init(drm);
 638	if (ret < 0)
 639		goto err_free;
 640
 641	ret = drm_dev_register(drm, 0);
 642	if (ret < 0)
 643		goto err_deinit;
 644
 645	drm_fbdev_generic_setup(drm, 32);
 646
 647	return 0;
 648
 649err_deinit:
 650	mtk_drm_kms_deinit(drm);
 651err_free:
 652	private->drm = NULL;
 653	drm_dev_put(drm);
 654	return ret;
 655}
 656
 657static void mtk_drm_unbind(struct device *dev)
 658{
 659	struct mtk_drm_private *private = dev_get_drvdata(dev);
 660
 661	/* for multi mmsys dev, unregister drm dev in mmsys master */
 662	if (private->drm_master) {
 663		drm_dev_unregister(private->drm);
 664		mtk_drm_kms_deinit(private->drm);
 665		drm_dev_put(private->drm);
 666	}
 667	private->mtk_drm_bound = false;
 668	private->drm_master = false;
 669	private->drm = NULL;
 670}
 671
 672static const struct component_master_ops mtk_drm_ops = {
 673	.bind		= mtk_drm_bind,
 674	.unbind		= mtk_drm_unbind,
 675};
 676
 677static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
 678	{ .compatible = "mediatek,mt8167-disp-aal",
 679	  .data = (void *)MTK_DISP_AAL},
 680	{ .compatible = "mediatek,mt8173-disp-aal",
 681	  .data = (void *)MTK_DISP_AAL},
 682	{ .compatible = "mediatek,mt8183-disp-aal",
 683	  .data = (void *)MTK_DISP_AAL},
 684	{ .compatible = "mediatek,mt8192-disp-aal",
 685	  .data = (void *)MTK_DISP_AAL},
 686	{ .compatible = "mediatek,mt8167-disp-ccorr",
 687	  .data = (void *)MTK_DISP_CCORR },
 688	{ .compatible = "mediatek,mt8183-disp-ccorr",
 689	  .data = (void *)MTK_DISP_CCORR },
 690	{ .compatible = "mediatek,mt8192-disp-ccorr",
 691	  .data = (void *)MTK_DISP_CCORR },
 692	{ .compatible = "mediatek,mt2701-disp-color",
 693	  .data = (void *)MTK_DISP_COLOR },
 694	{ .compatible = "mediatek,mt8167-disp-color",
 695	  .data = (void *)MTK_DISP_COLOR },
 696	{ .compatible = "mediatek,mt8173-disp-color",
 697	  .data = (void *)MTK_DISP_COLOR },
 698	{ .compatible = "mediatek,mt8167-disp-dither",
 699	  .data = (void *)MTK_DISP_DITHER },
 700	{ .compatible = "mediatek,mt8183-disp-dither",
 701	  .data = (void *)MTK_DISP_DITHER },
 702	{ .compatible = "mediatek,mt8195-disp-dsc",
 703	  .data = (void *)MTK_DISP_DSC },
 704	{ .compatible = "mediatek,mt8167-disp-gamma",
 705	  .data = (void *)MTK_DISP_GAMMA, },
 706	{ .compatible = "mediatek,mt8173-disp-gamma",
 707	  .data = (void *)MTK_DISP_GAMMA, },
 708	{ .compatible = "mediatek,mt8183-disp-gamma",
 709	  .data = (void *)MTK_DISP_GAMMA, },
 710	{ .compatible = "mediatek,mt8195-disp-merge",
 711	  .data = (void *)MTK_DISP_MERGE },
 712	{ .compatible = "mediatek,mt2701-disp-mutex",
 713	  .data = (void *)MTK_DISP_MUTEX },
 714	{ .compatible = "mediatek,mt2712-disp-mutex",
 715	  .data = (void *)MTK_DISP_MUTEX },
 716	{ .compatible = "mediatek,mt8167-disp-mutex",
 717	  .data = (void *)MTK_DISP_MUTEX },
 718	{ .compatible = "mediatek,mt8173-disp-mutex",
 719	  .data = (void *)MTK_DISP_MUTEX },
 720	{ .compatible = "mediatek,mt8183-disp-mutex",
 721	  .data = (void *)MTK_DISP_MUTEX },
 722	{ .compatible = "mediatek,mt8186-disp-mutex",
 723	  .data = (void *)MTK_DISP_MUTEX },
 724	{ .compatible = "mediatek,mt8188-disp-mutex",
 725	  .data = (void *)MTK_DISP_MUTEX },
 726	{ .compatible = "mediatek,mt8192-disp-mutex",
 727	  .data = (void *)MTK_DISP_MUTEX },
 728	{ .compatible = "mediatek,mt8195-disp-mutex",
 729	  .data = (void *)MTK_DISP_MUTEX },
 730	{ .compatible = "mediatek,mt8173-disp-od",
 731	  .data = (void *)MTK_DISP_OD },
 732	{ .compatible = "mediatek,mt2701-disp-ovl",
 733	  .data = (void *)MTK_DISP_OVL },
 734	{ .compatible = "mediatek,mt8167-disp-ovl",
 735	  .data = (void *)MTK_DISP_OVL },
 736	{ .compatible = "mediatek,mt8173-disp-ovl",
 737	  .data = (void *)MTK_DISP_OVL },
 738	{ .compatible = "mediatek,mt8183-disp-ovl",
 739	  .data = (void *)MTK_DISP_OVL },
 740	{ .compatible = "mediatek,mt8192-disp-ovl",
 741	  .data = (void *)MTK_DISP_OVL },
 742	{ .compatible = "mediatek,mt8183-disp-ovl-2l",
 743	  .data = (void *)MTK_DISP_OVL_2L },
 744	{ .compatible = "mediatek,mt8192-disp-ovl-2l",
 745	  .data = (void *)MTK_DISP_OVL_2L },
 746	{ .compatible = "mediatek,mt8192-disp-postmask",
 747	  .data = (void *)MTK_DISP_POSTMASK },
 748	{ .compatible = "mediatek,mt2701-disp-pwm",
 749	  .data = (void *)MTK_DISP_BLS },
 750	{ .compatible = "mediatek,mt8167-disp-pwm",
 751	  .data = (void *)MTK_DISP_PWM },
 752	{ .compatible = "mediatek,mt8173-disp-pwm",
 753	  .data = (void *)MTK_DISP_PWM },
 754	{ .compatible = "mediatek,mt2701-disp-rdma",
 755	  .data = (void *)MTK_DISP_RDMA },
 756	{ .compatible = "mediatek,mt8167-disp-rdma",
 757	  .data = (void *)MTK_DISP_RDMA },
 758	{ .compatible = "mediatek,mt8173-disp-rdma",
 759	  .data = (void *)MTK_DISP_RDMA },
 760	{ .compatible = "mediatek,mt8183-disp-rdma",
 761	  .data = (void *)MTK_DISP_RDMA },
 762	{ .compatible = "mediatek,mt8195-disp-rdma",
 763	  .data = (void *)MTK_DISP_RDMA },
 764	{ .compatible = "mediatek,mt8173-disp-ufoe",
 765	  .data = (void *)MTK_DISP_UFOE },
 766	{ .compatible = "mediatek,mt8173-disp-wdma",
 767	  .data = (void *)MTK_DISP_WDMA },
 768	{ .compatible = "mediatek,mt2701-dpi",
 769	  .data = (void *)MTK_DPI },
 770	{ .compatible = "mediatek,mt8167-dsi",
 771	  .data = (void *)MTK_DSI },
 772	{ .compatible = "mediatek,mt8173-dpi",
 773	  .data = (void *)MTK_DPI },
 774	{ .compatible = "mediatek,mt8183-dpi",
 775	  .data = (void *)MTK_DPI },
 776	{ .compatible = "mediatek,mt8186-dpi",
 777	  .data = (void *)MTK_DPI },
 778	{ .compatible = "mediatek,mt8188-dp-intf",
 779	  .data = (void *)MTK_DP_INTF },
 780	{ .compatible = "mediatek,mt8192-dpi",
 781	  .data = (void *)MTK_DPI },
 782	{ .compatible = "mediatek,mt8195-dp-intf",
 783	  .data = (void *)MTK_DP_INTF },
 784	{ .compatible = "mediatek,mt2701-dsi",
 785	  .data = (void *)MTK_DSI },
 786	{ .compatible = "mediatek,mt8173-dsi",
 787	  .data = (void *)MTK_DSI },
 788	{ .compatible = "mediatek,mt8183-dsi",
 789	  .data = (void *)MTK_DSI },
 790	{ .compatible = "mediatek,mt8186-dsi",
 791	  .data = (void *)MTK_DSI },
 792	{ .compatible = "mediatek,mt8188-dsi",
 793	  .data = (void *)MTK_DSI },
 794	{ }
 795};
 796
 797static int mtk_drm_probe(struct platform_device *pdev)
 798{
 799	struct device *dev = &pdev->dev;
 800	struct device_node *phandle = dev->parent->of_node;
 801	const struct of_device_id *of_id;
 802	struct mtk_drm_private *private;
 
 803	struct device_node *node;
 804	struct component_match *match = NULL;
 805	struct platform_device *ovl_adaptor;
 806	int ret;
 807	int i;
 808
 809	private = devm_kzalloc(dev, sizeof(*private), GFP_KERNEL);
 810	if (!private)
 811		return -ENOMEM;
 812
 813	private->mmsys_dev = dev->parent;
 814	if (!private->mmsys_dev) {
 815		dev_err(dev, "Failed to get MMSYS device\n");
 816		return -ENODEV;
 817	}
 818
 819	of_id = of_match_node(mtk_drm_of_ids, phandle);
 820	if (!of_id)
 821		return -ENODEV;
 822
 823	private->data = of_id->data;
 824
 825	private->all_drm_private = devm_kmalloc_array(dev, private->data->mmsys_dev_num,
 826						      sizeof(*private->all_drm_private),
 827						      GFP_KERNEL);
 828	if (!private->all_drm_private)
 829		return -ENOMEM;
 830
 831	/* Bringup ovl_adaptor */
 832	if (mtk_drm_find_mmsys_comp(private, DDP_COMPONENT_DRM_OVL_ADAPTOR)) {
 833		ovl_adaptor = platform_device_register_data(dev, "mediatek-disp-ovl-adaptor",
 834							    PLATFORM_DEVID_AUTO,
 835							    (void *)private->mmsys_dev,
 836							    sizeof(*private->mmsys_dev));
 837		private->ddp_comp[DDP_COMPONENT_DRM_OVL_ADAPTOR].dev = &ovl_adaptor->dev;
 838		mtk_ddp_comp_init(NULL, &private->ddp_comp[DDP_COMPONENT_DRM_OVL_ADAPTOR],
 839				  DDP_COMPONENT_DRM_OVL_ADAPTOR);
 840		component_match_add(dev, &match, compare_dev, &ovl_adaptor->dev);
 841	}
 842
 843	/* Iterate over sibling DISP function blocks */
 844	for_each_child_of_node(phandle->parent, node) {
 845		const struct of_device_id *of_id;
 846		enum mtk_ddp_comp_type comp_type;
 847		int comp_id;
 848
 849		of_id = of_match_node(mtk_ddp_comp_dt_ids, node);
 850		if (!of_id)
 851			continue;
 852
 853		if (!of_device_is_available(node)) {
 854			dev_dbg(dev, "Skipping disabled component %pOF\n",
 855				node);
 856			continue;
 857		}
 858
 859		comp_type = (enum mtk_ddp_comp_type)(uintptr_t)of_id->data;
 860
 861		if (comp_type == MTK_DISP_MUTEX) {
 862			int id;
 863
 864			id = of_alias_get_id(node, "mutex");
 865			if (id < 0 || id == private->data->mmsys_id) {
 866				private->mutex_node = of_node_get(node);
 867				dev_dbg(dev, "get mutex for mmsys %d", private->data->mmsys_id);
 868			}
 869			continue;
 870		}
 871
 872		comp_id = mtk_ddp_comp_get_id(node, comp_type);
 873		if (comp_id < 0) {
 874			dev_warn(dev, "Skipping unknown component %pOF\n",
 875				 node);
 876			continue;
 877		}
 878
 879		if (!mtk_drm_find_mmsys_comp(private, comp_id))
 880			continue;
 881
 882		private->comp_node[comp_id] = of_node_get(node);
 883
 884		/*
 885		 * Currently only the AAL, CCORR, COLOR, GAMMA, MERGE, OVL, RDMA, DSI, and DPI
 886		 * blocks have separate component platform drivers and initialize their own
 887		 * DDP component structure. The others are initialized here.
 888		 */
 889		if (comp_type == MTK_DISP_AAL ||
 890		    comp_type == MTK_DISP_CCORR ||
 891		    comp_type == MTK_DISP_COLOR ||
 892		    comp_type == MTK_DISP_GAMMA ||
 893		    comp_type == MTK_DISP_MERGE ||
 894		    comp_type == MTK_DISP_OVL ||
 895		    comp_type == MTK_DISP_OVL_2L ||
 896		    comp_type == MTK_DISP_OVL_ADAPTOR ||
 897		    comp_type == MTK_DISP_RDMA ||
 898		    comp_type == MTK_DP_INTF ||
 899		    comp_type == MTK_DPI ||
 900		    comp_type == MTK_DSI) {
 901			dev_info(dev, "Adding component match for %pOF\n",
 902				 node);
 903			drm_of_component_match_add(dev, &match, component_compare_of,
 904						   node);
 905		}
 
 
 
 
 
 
 
 
 
 
 
 906
 907		ret = mtk_ddp_comp_init(node, &private->ddp_comp[comp_id], comp_id);
 908		if (ret) {
 909			of_node_put(node);
 910			goto err_node;
 911		}
 912	}
 913
 914	if (!private->mutex_node) {
 915		dev_err(dev, "Failed to find disp-mutex node\n");
 916		ret = -ENODEV;
 917		goto err_node;
 918	}
 919
 920	pm_runtime_enable(dev);
 921
 922	platform_set_drvdata(pdev, private);
 923
 924	ret = component_master_add_with_match(dev, &mtk_drm_ops, match);
 925	if (ret)
 926		goto err_pm;
 927
 928	return 0;
 929
 930err_pm:
 931	pm_runtime_disable(dev);
 932err_node:
 933	of_node_put(private->mutex_node);
 934	for (i = 0; i < DDP_COMPONENT_DRM_ID_MAX; i++)
 935		of_node_put(private->comp_node[i]);
 936	return ret;
 937}
 938
 939static void mtk_drm_remove(struct platform_device *pdev)
 940{
 941	struct mtk_drm_private *private = platform_get_drvdata(pdev);
 
 942	int i;
 943
 
 
 
 
 944	component_master_del(&pdev->dev, &mtk_drm_ops);
 945	pm_runtime_disable(&pdev->dev);
 946	of_node_put(private->mutex_node);
 947	for (i = 0; i < DDP_COMPONENT_DRM_ID_MAX; i++)
 948		of_node_put(private->comp_node[i]);
 
 
 949}
 950
 951static int mtk_drm_sys_prepare(struct device *dev)
 
 952{
 953	struct mtk_drm_private *private = dev_get_drvdata(dev);
 954	struct drm_device *drm = private->drm;
 955
 956	if (private->drm_master)
 957		return drm_mode_config_helper_suspend(drm);
 958	else
 959		return 0;
 
 
 
 
 
 
 960}
 961
 962static void mtk_drm_sys_complete(struct device *dev)
 963{
 964	struct mtk_drm_private *private = dev_get_drvdata(dev);
 965	struct drm_device *drm = private->drm;
 966	int ret = 0;
 967
 968	if (private->drm_master)
 969		ret = drm_mode_config_helper_resume(drm);
 970	if (ret)
 971		dev_err(dev, "Failed to resume\n");
 
 972}
 
 
 
 
 973
 974static const struct dev_pm_ops mtk_drm_pm_ops = {
 975	.prepare = mtk_drm_sys_prepare,
 976	.complete = mtk_drm_sys_complete,
 
 
 
 977};
 978
 979static struct platform_driver mtk_drm_platform_driver = {
 980	.probe	= mtk_drm_probe,
 981	.remove_new = mtk_drm_remove,
 982	.driver	= {
 983		.name	= "mediatek-drm",
 
 984		.pm     = &mtk_drm_pm_ops,
 985	},
 986};
 987
 988static struct platform_driver * const mtk_drm_drivers[] = {
 989	&mtk_disp_aal_driver,
 990	&mtk_disp_ccorr_driver,
 991	&mtk_disp_color_driver,
 992	&mtk_disp_gamma_driver,
 993	&mtk_disp_merge_driver,
 994	&mtk_disp_ovl_adaptor_driver,
 995	&mtk_disp_ovl_driver,
 996	&mtk_disp_rdma_driver,
 997	&mtk_dpi_driver,
 998	&mtk_drm_platform_driver,
 999	&mtk_dsi_driver,
1000	&mtk_ethdr_driver,
1001	&mtk_mdp_rdma_driver,
1002	&mtk_padding_driver,
1003};
1004
1005static int __init mtk_drm_init(void)
1006{
1007	return platform_register_drivers(mtk_drm_drivers,
1008					 ARRAY_SIZE(mtk_drm_drivers));
1009}
1010
1011static void __exit mtk_drm_exit(void)
1012{
1013	platform_unregister_drivers(mtk_drm_drivers,
1014				    ARRAY_SIZE(mtk_drm_drivers));
1015}
1016
1017module_init(mtk_drm_init);
1018module_exit(mtk_drm_exit);
1019
1020MODULE_AUTHOR("YT SHEN <yt.shen@mediatek.com>");
1021MODULE_DESCRIPTION("Mediatek SoC DRM driver");
1022MODULE_LICENSE("GPL v2");
v4.17
 
  1/*
  2 * Copyright (c) 2015 MediaTek Inc.
  3 * Author: YT SHEN <yt.shen@mediatek.com>
  4 *
  5 * This program is free software; you can redistribute it and/or modify
  6 * it under the terms of the GNU General Public License version 2 as
  7 * published by the Free Software Foundation.
  8 *
  9 * This program is distributed in the hope that it will be useful,
 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12 * GNU General Public License for more details.
 13 */
 14
 15#include <drm/drmP.h>
 
 
 
 
 
 
 
 16#include <drm/drm_atomic.h>
 17#include <drm/drm_atomic_helper.h>
 18#include <drm/drm_crtc_helper.h>
 
 
 19#include <drm/drm_gem.h>
 20#include <drm/drm_gem_cma_helper.h>
 
 21#include <drm/drm_of.h>
 22#include <linux/component.h>
 23#include <linux/iommu.h>
 24#include <linux/of_address.h>
 25#include <linux/of_platform.h>
 26#include <linux/pm_runtime.h>
 27
 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_fb.h"
 33#include "mtk_drm_gem.h"
 34
 35#define DRIVER_NAME "mediatek"
 36#define DRIVER_DESC "Mediatek SoC DRM"
 37#define DRIVER_DATE "20150513"
 38#define DRIVER_MAJOR 1
 39#define DRIVER_MINOR 0
 40
 41static void mtk_atomic_schedule(struct mtk_drm_private *private,
 42				struct drm_atomic_state *state)
 
 
 
 
 
 
 43{
 44	private->commit.state = state;
 45	schedule_work(&private->commit.work);
 46}
 47
 48static void mtk_atomic_wait_for_fences(struct drm_atomic_state *state)
 49{
 50	struct drm_plane *plane;
 51	struct drm_plane_state *new_plane_state;
 52	int i;
 53
 54	for_each_new_plane_in_state(state, plane, new_plane_state, i)
 55		mtk_fb_wait(new_plane_state->fb);
 56}
 57
 58static void mtk_atomic_complete(struct mtk_drm_private *private,
 59				struct drm_atomic_state *state)
 60{
 61	struct drm_device *drm = private->drm;
 
 62
 63	mtk_atomic_wait_for_fences(state);
 
 
 
 
 
 
 64
 65	/*
 66	 * Mediatek drm supports runtime PM, so plane registers cannot be
 67	 * written when their crtc is disabled.
 68	 *
 69	 * The comment for drm_atomic_helper_commit states:
 70	 *     For drivers supporting runtime PM the recommended sequence is
 71	 *
 72	 *     drm_atomic_helper_commit_modeset_disables(dev, state);
 73	 *     drm_atomic_helper_commit_modeset_enables(dev, state);
 74	 *     drm_atomic_helper_commit_planes(dev, state,
 75	 *                                     DRM_PLANE_COMMIT_ACTIVE_ONLY);
 76	 *
 77	 * See the kerneldoc entries for these three functions for more details.
 78	 */
 79	drm_atomic_helper_commit_modeset_disables(drm, state);
 80	drm_atomic_helper_commit_modeset_enables(drm, state);
 81	drm_atomic_helper_commit_planes(drm, state,
 82					DRM_PLANE_COMMIT_ACTIVE_ONLY);
 83
 84	drm_atomic_helper_wait_for_vblanks(drm, state);
 
 
 
 
 
 
 85
 86	drm_atomic_helper_cleanup_planes(drm, state);
 87	drm_atomic_state_put(state);
 88}
 
 89
 90static void mtk_atomic_work(struct work_struct *work)
 91{
 92	struct mtk_drm_private *private = container_of(work,
 93			struct mtk_drm_private, commit.work);
 
 
 
 
 
 94
 95	mtk_atomic_complete(private, private->commit.state);
 96}
 
 
 
 
 
 
 
 97
 98static int mtk_atomic_commit(struct drm_device *drm,
 99			     struct drm_atomic_state *state,
100			     bool async)
101{
102	struct mtk_drm_private *private = drm->dev_private;
103	int ret;
104
105	ret = drm_atomic_helper_prepare_planes(drm, state);
106	if (ret)
107		return ret;
 
 
 
 
 
 
 
108
109	mutex_lock(&private->commit.lock);
110	flush_work(&private->commit.work);
 
 
 
 
 
 
 
 
111
112	ret = drm_atomic_helper_swap_state(state, true);
113	if (ret) {
114		mutex_unlock(&private->commit.lock);
115		drm_atomic_helper_cleanup_planes(drm, state);
116		return ret;
117	}
 
118
119	drm_atomic_state_get(state);
120	if (async)
121		mtk_atomic_schedule(private, state);
122	else
123		mtk_atomic_complete(private, state);
 
 
 
 
 
 
124
125	mutex_unlock(&private->commit.lock);
126
127	return 0;
128}
129
130static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs = {
131	.fb_create = mtk_drm_mode_fb_create,
132	.atomic_check = drm_atomic_helper_check,
133	.atomic_commit = mtk_atomic_commit,
134};
135
136static const enum mtk_ddp_comp_id mt2701_mtk_ddp_main[] = {
137	DDP_COMPONENT_OVL0,
138	DDP_COMPONENT_RDMA0,
139	DDP_COMPONENT_COLOR0,
140	DDP_COMPONENT_BLS,
 
 
 
 
141	DDP_COMPONENT_DSI0,
142};
143
144static const enum mtk_ddp_comp_id mt2701_mtk_ddp_ext[] = {
 
145	DDP_COMPONENT_RDMA1,
146	DDP_COMPONENT_DPI0,
147};
148
149static const enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = {
150	DDP_COMPONENT_OVL0,
 
151	DDP_COMPONENT_COLOR0,
152	DDP_COMPONENT_AAL,
153	DDP_COMPONENT_OD,
 
 
 
 
 
 
 
 
 
 
 
 
 
154	DDP_COMPONENT_RDMA0,
155	DDP_COMPONENT_UFOE,
 
 
 
 
 
156	DDP_COMPONENT_DSI0,
157	DDP_COMPONENT_PWM0,
158};
159
160static const enum mtk_ddp_comp_id mt8173_mtk_ddp_ext[] = {
161	DDP_COMPONENT_OVL1,
162	DDP_COMPONENT_COLOR1,
 
 
 
 
 
 
 
 
 
163	DDP_COMPONENT_GAMMA,
164	DDP_COMPONENT_RDMA1,
165	DDP_COMPONENT_DPI0,
 
 
 
 
 
 
 
 
166};
167
168static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = {
169	.main_path = mt2701_mtk_ddp_main,
170	.main_len = ARRAY_SIZE(mt2701_mtk_ddp_main),
171	.ext_path = mt2701_mtk_ddp_ext,
172	.ext_len = ARRAY_SIZE(mt2701_mtk_ddp_ext),
173	.shadow_register = true,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174};
175
176static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = {
177	.main_path = mt8173_mtk_ddp_main,
178	.main_len = ARRAY_SIZE(mt8173_mtk_ddp_main),
179	.ext_path = mt8173_mtk_ddp_ext,
180	.ext_len = ARRAY_SIZE(mt8173_mtk_ddp_ext),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181};
182
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183static int mtk_drm_kms_init(struct drm_device *drm)
184{
185	struct mtk_drm_private *private = drm->dev_private;
186	struct platform_device *pdev;
187	struct device_node *np;
188	int ret;
 
189
190	if (!iommu_present(&platform_bus_type))
191		return -EPROBE_DEFER;
192
193	pdev = of_find_device_by_node(private->mutex_node);
194	if (!pdev) {
195		dev_err(drm->dev, "Waiting for disp-mutex device %pOF\n",
196			private->mutex_node);
197		of_node_put(private->mutex_node);
198		return -EPROBE_DEFER;
199	}
200	private->mutex_dev = &pdev->dev;
201
202	drm_mode_config_init(drm);
203
204	drm->mode_config.min_width = 64;
205	drm->mode_config.min_height = 64;
206
207	/*
208	 * set max width and height as default value(4096x4096).
209	 * this value would be used to check framebuffer size limitation
210	 * at drm_mode_addfb().
211	 */
212	drm->mode_config.max_width = 4096;
213	drm->mode_config.max_height = 4096;
214	drm->mode_config.funcs = &mtk_drm_mode_config_funcs;
 
 
 
 
 
 
 
 
215
216	ret = component_bind_all(drm->dev, drm);
217	if (ret)
218		goto err_config_cleanup;
 
 
219
220	/*
221	 * We currently support two fixed data streams, each optional,
222	 * and each statically assigned to a crtc:
223	 * OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0 ...
 
 
 
 
224	 */
225	ret = mtk_drm_crtc_create(drm, private->data->main_path,
226				  private->data->main_len);
227	if (ret < 0)
228		goto err_component_unbind;
229	/* ... and OVL1 -> COLOR1 -> GAMMA -> RDMA1 -> DPI0. */
230	ret = mtk_drm_crtc_create(drm, private->data->ext_path,
231				  private->data->ext_len);
232	if (ret < 0)
233		goto err_component_unbind;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
235	/* Use OVL device for all DMA memory allocations */
236	np = private->comp_node[private->data->main_path[0]] ?:
237	     private->comp_node[private->data->ext_path[0]];
238	pdev = of_find_device_by_node(np);
239	if (!pdev) {
240		ret = -ENODEV;
241		dev_err(drm->dev, "Need at least one OVL device\n");
242		goto err_component_unbind;
243	}
244
245	private->dma_dev = &pdev->dev;
 
246
247	/*
248	 * We don't use the drm_irq_install() helpers provided by the DRM
249	 * core, so we need to set this manually in order to allow the
250	 * DRM_IOCTL_WAIT_VBLANK to operate correctly.
251	 */
252	drm->irq_enabled = true;
 
 
 
 
 
253	ret = drm_vblank_init(drm, MAX_CRTC);
254	if (ret < 0)
255		goto err_component_unbind;
256
257	drm_kms_helper_poll_init(drm);
258	drm_mode_config_reset(drm);
259
260	return 0;
261
262err_component_unbind:
263	component_unbind_all(drm->dev, drm);
264err_config_cleanup:
265	drm_mode_config_cleanup(drm);
 
 
266
267	return ret;
268}
269
270static void mtk_drm_kms_deinit(struct drm_device *drm)
271{
272	drm_kms_helper_poll_fini(drm);
 
273
274	component_unbind_all(drm->dev, drm);
275	drm_mode_config_cleanup(drm);
276}
277
278static const struct file_operations mtk_drm_fops = {
279	.owner = THIS_MODULE,
280	.open = drm_open,
281	.release = drm_release,
282	.unlocked_ioctl = drm_ioctl,
283	.mmap = mtk_drm_gem_mmap,
284	.poll = drm_poll,
285	.read = drm_read,
286	.compat_ioctl = drm_compat_ioctl,
287};
288
289static struct drm_driver mtk_drm_driver = {
290	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
291			   DRIVER_ATOMIC,
 
 
292
293	.gem_free_object_unlocked = mtk_drm_gem_free_object,
294	.gem_vm_ops = &drm_gem_cma_vm_ops,
295	.dumb_create = mtk_drm_gem_dumb_create,
296
297	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
298	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
299	.gem_prime_export = drm_gem_prime_export,
300	.gem_prime_import = drm_gem_prime_import,
301	.gem_prime_get_sg_table = mtk_gem_prime_get_sg_table,
302	.gem_prime_import_sg_table = mtk_gem_prime_import_sg_table,
303	.gem_prime_mmap = mtk_drm_gem_mmap_buf,
304	.fops = &mtk_drm_fops,
305
306	.name = DRIVER_NAME,
307	.desc = DRIVER_DESC,
308	.date = DRIVER_DATE,
309	.major = DRIVER_MAJOR,
310	.minor = DRIVER_MINOR,
311};
312
313static int compare_of(struct device *dev, void *data)
314{
315	return dev->of_node == data;
316}
317
318static int mtk_drm_bind(struct device *dev)
319{
320	struct mtk_drm_private *private = dev_get_drvdata(dev);
 
321	struct drm_device *drm;
322	int ret;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
323
324	drm = drm_dev_alloc(&mtk_drm_driver, dev);
325	if (IS_ERR(drm))
326		return PTR_ERR(drm);
327
 
328	drm->dev_private = private;
329	private->drm = drm;
 
330
331	ret = mtk_drm_kms_init(drm);
332	if (ret < 0)
333		goto err_free;
334
335	ret = drm_dev_register(drm, 0);
336	if (ret < 0)
337		goto err_deinit;
338
 
 
339	return 0;
340
341err_deinit:
342	mtk_drm_kms_deinit(drm);
343err_free:
344	drm_dev_unref(drm);
 
345	return ret;
346}
347
348static void mtk_drm_unbind(struct device *dev)
349{
350	struct mtk_drm_private *private = dev_get_drvdata(dev);
351
352	drm_dev_unregister(private->drm);
353	drm_dev_unref(private->drm);
 
 
 
 
 
 
354	private->drm = NULL;
355}
356
357static const struct component_master_ops mtk_drm_ops = {
358	.bind		= mtk_drm_bind,
359	.unbind		= mtk_drm_unbind,
360};
361
362static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
363	{ .compatible = "mediatek,mt2701-disp-ovl",   .data = (void *)MTK_DISP_OVL },
364	{ .compatible = "mediatek,mt8173-disp-ovl",   .data = (void *)MTK_DISP_OVL },
365	{ .compatible = "mediatek,mt2701-disp-rdma",  .data = (void *)MTK_DISP_RDMA },
366	{ .compatible = "mediatek,mt8173-disp-rdma",  .data = (void *)MTK_DISP_RDMA },
367	{ .compatible = "mediatek,mt8173-disp-wdma",  .data = (void *)MTK_DISP_WDMA },
368	{ .compatible = "mediatek,mt2701-disp-color", .data = (void *)MTK_DISP_COLOR },
369	{ .compatible = "mediatek,mt8173-disp-color", .data = (void *)MTK_DISP_COLOR },
370	{ .compatible = "mediatek,mt8173-disp-aal",   .data = (void *)MTK_DISP_AAL},
371	{ .compatible = "mediatek,mt8173-disp-gamma", .data = (void *)MTK_DISP_GAMMA, },
372	{ .compatible = "mediatek,mt8173-disp-ufoe",  .data = (void *)MTK_DISP_UFOE },
373	{ .compatible = "mediatek,mt2701-dsi",	      .data = (void *)MTK_DSI },
374	{ .compatible = "mediatek,mt8173-dsi",        .data = (void *)MTK_DSI },
375	{ .compatible = "mediatek,mt8173-dpi",        .data = (void *)MTK_DPI },
376	{ .compatible = "mediatek,mt2701-disp-mutex", .data = (void *)MTK_DISP_MUTEX },
377	{ .compatible = "mediatek,mt8173-disp-mutex", .data = (void *)MTK_DISP_MUTEX },
378	{ .compatible = "mediatek,mt2701-disp-pwm",   .data = (void *)MTK_DISP_BLS },
379	{ .compatible = "mediatek,mt8173-disp-pwm",   .data = (void *)MTK_DISP_PWM },
380	{ .compatible = "mediatek,mt8173-disp-od",    .data = (void *)MTK_DISP_OD },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
381	{ }
382};
383
384static int mtk_drm_probe(struct platform_device *pdev)
385{
386	struct device *dev = &pdev->dev;
 
 
387	struct mtk_drm_private *private;
388	struct resource *mem;
389	struct device_node *node;
390	struct component_match *match = NULL;
 
391	int ret;
392	int i;
393
394	private = devm_kzalloc(dev, sizeof(*private), GFP_KERNEL);
395	if (!private)
396		return -ENOMEM;
397
398	mutex_init(&private->commit.lock);
399	INIT_WORK(&private->commit.work, mtk_atomic_work);
400	private->data = of_device_get_match_data(dev);
401
402	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
403	private->config_regs = devm_ioremap_resource(dev, mem);
404	if (IS_ERR(private->config_regs)) {
405		ret = PTR_ERR(private->config_regs);
406		dev_err(dev, "Failed to ioremap mmsys-config resource: %d\n",
407			ret);
408		return ret;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
409	}
410
411	/* Iterate over sibling DISP function blocks */
412	for_each_child_of_node(dev->of_node->parent, node) {
413		const struct of_device_id *of_id;
414		enum mtk_ddp_comp_type comp_type;
415		int comp_id;
416
417		of_id = of_match_node(mtk_ddp_comp_dt_ids, node);
418		if (!of_id)
419			continue;
420
421		if (!of_device_is_available(node)) {
422			dev_dbg(dev, "Skipping disabled component %pOF\n",
423				node);
424			continue;
425		}
426
427		comp_type = (enum mtk_ddp_comp_type)of_id->data;
428
429		if (comp_type == MTK_DISP_MUTEX) {
430			private->mutex_node = of_node_get(node);
 
 
 
 
 
 
431			continue;
432		}
433
434		comp_id = mtk_ddp_comp_get_id(node, comp_type);
435		if (comp_id < 0) {
436			dev_warn(dev, "Skipping unknown component %pOF\n",
437				 node);
438			continue;
439		}
440
 
 
 
441		private->comp_node[comp_id] = of_node_get(node);
442
443		/*
444		 * Currently only the COLOR, OVL, RDMA, DSI, and DPI blocks have
445		 * separate component platform drivers and initialize their own
446		 * DDP component structure. The others are initialized here.
447		 */
448		if (comp_type == MTK_DISP_COLOR ||
 
 
 
 
449		    comp_type == MTK_DISP_OVL ||
 
 
450		    comp_type == MTK_DISP_RDMA ||
451		    comp_type == MTK_DSI ||
452		    comp_type == MTK_DPI) {
 
453			dev_info(dev, "Adding component match for %pOF\n",
454				 node);
455			drm_of_component_match_add(dev, &match, compare_of,
456						   node);
457		} else {
458			struct mtk_ddp_comp *comp;
459
460			comp = devm_kzalloc(dev, sizeof(*comp), GFP_KERNEL);
461			if (!comp) {
462				ret = -ENOMEM;
463				goto err_node;
464			}
465
466			ret = mtk_ddp_comp_init(dev, node, comp, comp_id, NULL);
467			if (ret)
468				goto err_node;
469
470			private->ddp_comp[comp_id] = comp;
 
 
 
471		}
472	}
473
474	if (!private->mutex_node) {
475		dev_err(dev, "Failed to find disp-mutex node\n");
476		ret = -ENODEV;
477		goto err_node;
478	}
479
480	pm_runtime_enable(dev);
481
482	platform_set_drvdata(pdev, private);
483
484	ret = component_master_add_with_match(dev, &mtk_drm_ops, match);
485	if (ret)
486		goto err_pm;
487
488	return 0;
489
490err_pm:
491	pm_runtime_disable(dev);
492err_node:
493	of_node_put(private->mutex_node);
494	for (i = 0; i < DDP_COMPONENT_ID_MAX; i++)
495		of_node_put(private->comp_node[i]);
496	return ret;
497}
498
499static int mtk_drm_remove(struct platform_device *pdev)
500{
501	struct mtk_drm_private *private = platform_get_drvdata(pdev);
502	struct drm_device *drm = private->drm;
503	int i;
504
505	drm_dev_unregister(drm);
506	mtk_drm_kms_deinit(drm);
507	drm_dev_unref(drm);
508
509	component_master_del(&pdev->dev, &mtk_drm_ops);
510	pm_runtime_disable(&pdev->dev);
511	of_node_put(private->mutex_node);
512	for (i = 0; i < DDP_COMPONENT_ID_MAX; i++)
513		of_node_put(private->comp_node[i]);
514
515	return 0;
516}
517
518#ifdef CONFIG_PM_SLEEP
519static int mtk_drm_sys_suspend(struct device *dev)
520{
521	struct mtk_drm_private *private = dev_get_drvdata(dev);
522	struct drm_device *drm = private->drm;
523
524	drm_kms_helper_poll_disable(drm);
525
526	private->suspend_state = drm_atomic_helper_suspend(drm);
527	if (IS_ERR(private->suspend_state)) {
528		drm_kms_helper_poll_enable(drm);
529		return PTR_ERR(private->suspend_state);
530	}
531
532	DRM_DEBUG_DRIVER("mtk_drm_sys_suspend\n");
533	return 0;
534}
535
536static int mtk_drm_sys_resume(struct device *dev)
537{
538	struct mtk_drm_private *private = dev_get_drvdata(dev);
539	struct drm_device *drm = private->drm;
 
540
541	drm_atomic_helper_resume(drm, private->suspend_state);
542	drm_kms_helper_poll_enable(drm);
543
544	DRM_DEBUG_DRIVER("mtk_drm_sys_resume\n");
545	return 0;
546}
547#endif
548
549static SIMPLE_DEV_PM_OPS(mtk_drm_pm_ops, mtk_drm_sys_suspend,
550			 mtk_drm_sys_resume);
551
552static const struct of_device_id mtk_drm_of_ids[] = {
553	{ .compatible = "mediatek,mt2701-mmsys",
554	  .data = &mt2701_mmsys_driver_data},
555	{ .compatible = "mediatek,mt8173-mmsys",
556	  .data = &mt8173_mmsys_driver_data},
557	{ }
558};
559
560static struct platform_driver mtk_drm_platform_driver = {
561	.probe	= mtk_drm_probe,
562	.remove	= mtk_drm_remove,
563	.driver	= {
564		.name	= "mediatek-drm",
565		.of_match_table = mtk_drm_of_ids,
566		.pm     = &mtk_drm_pm_ops,
567	},
568};
569
570static struct platform_driver * const mtk_drm_drivers[] = {
571	&mtk_ddp_driver,
 
572	&mtk_disp_color_driver,
 
 
 
573	&mtk_disp_ovl_driver,
574	&mtk_disp_rdma_driver,
575	&mtk_dpi_driver,
576	&mtk_drm_platform_driver,
577	&mtk_dsi_driver,
578	&mtk_mipi_tx_driver,
 
 
579};
580
581static int __init mtk_drm_init(void)
582{
583	return platform_register_drivers(mtk_drm_drivers,
584					 ARRAY_SIZE(mtk_drm_drivers));
585}
586
587static void __exit mtk_drm_exit(void)
588{
589	platform_unregister_drivers(mtk_drm_drivers,
590				    ARRAY_SIZE(mtk_drm_drivers));
591}
592
593module_init(mtk_drm_init);
594module_exit(mtk_drm_exit);
595
596MODULE_AUTHOR("YT SHEN <yt.shen@mediatek.com>");
597MODULE_DESCRIPTION("Mediatek SoC DRM driver");
598MODULE_LICENSE("GPL v2");