1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2021 MediaTek Inc. 4 */ 5 6 #include <drm/drm_fourcc.h> 7 #include <drm/drm_of.h> 8 #include <linux/clk.h> 9 #include <linux/component.h> 10 #include <linux/of.h> 11 #include <linux/of_address.h> 12 #include <linux/of_platform.h> 13 #include <linux/platform_device.h> 14 #include <linux/pm_runtime.h> 15 #include <linux/reset.h> 16 #include <linux/soc/mediatek/mtk-cmdq.h> 17 #include <linux/soc/mediatek/mtk-mmsys.h> 18 #include <linux/soc/mediatek/mtk-mutex.h> 19 20 #include "mtk_disp_drv.h" 21 #include "mtk_drm_crtc.h" 22 #include "mtk_drm_ddp_comp.h" 23 #include "mtk_drm_drv.h" 24 #include "mtk_ethdr.h" 25 26 #define MTK_OVL_ADAPTOR_RDMA_MAX_WIDTH 1920 27 #define MTK_OVL_ADAPTOR_LAYER_NUM 4 28 29 enum mtk_ovl_adaptor_comp_type { 30 OVL_ADAPTOR_TYPE_ETHDR, 31 OVL_ADAPTOR_TYPE_MDP_RDMA, 32 OVL_ADAPTOR_TYPE_MERGE, 33 OVL_ADAPTOR_TYPE_NUM, 34 }; 35 36 enum mtk_ovl_adaptor_comp_id { 37 OVL_ADAPTOR_ETHDR0, 38 OVL_ADAPTOR_MDP_RDMA0, 39 OVL_ADAPTOR_MDP_RDMA1, 40 OVL_ADAPTOR_MDP_RDMA2, 41 OVL_ADAPTOR_MDP_RDMA3, 42 OVL_ADAPTOR_MDP_RDMA4, 43 OVL_ADAPTOR_MDP_RDMA5, 44 OVL_ADAPTOR_MDP_RDMA6, 45 OVL_ADAPTOR_MDP_RDMA7, 46 OVL_ADAPTOR_MERGE0, 47 OVL_ADAPTOR_MERGE1, 48 OVL_ADAPTOR_MERGE2, 49 OVL_ADAPTOR_MERGE3, 50 OVL_ADAPTOR_ID_MAX 51 }; 52 53 struct ovl_adaptor_comp_match { 54 enum mtk_ovl_adaptor_comp_type type; 55 enum mtk_ddp_comp_id comp_id; 56 int alias_id; 57 const struct mtk_ddp_comp_funcs *funcs; 58 }; 59 60 struct mtk_disp_ovl_adaptor { 61 struct device *ovl_adaptor_comp[OVL_ADAPTOR_ID_MAX]; 62 struct device *mmsys_dev; 63 bool children_bound; 64 }; 65 66 static const char * const private_comp_stem[OVL_ADAPTOR_TYPE_NUM] = { 67 [OVL_ADAPTOR_TYPE_ETHDR] = "ethdr", 68 [OVL_ADAPTOR_TYPE_MDP_RDMA] = "vdo1-rdma", 69 [OVL_ADAPTOR_TYPE_MERGE] = "merge", 70 }; 71 72 static const struct mtk_ddp_comp_funcs ethdr = { 73 .clk_enable = mtk_ethdr_clk_enable, 74 .clk_disable = mtk_ethdr_clk_disable, 75 .start = mtk_ethdr_start, 76 .stop = mtk_ethdr_stop, 77 }; 78 79 static const struct mtk_ddp_comp_funcs merge = { 80 .clk_enable = mtk_merge_clk_enable, 81 .clk_disable = mtk_merge_clk_disable, 82 }; 83 84 static const struct mtk_ddp_comp_funcs rdma = { 85 .power_on = mtk_mdp_rdma_power_on, 86 .power_off = mtk_mdp_rdma_power_off, 87 .clk_enable = mtk_mdp_rdma_clk_enable, 88 .clk_disable = mtk_mdp_rdma_clk_disable, 89 }; 90 91 static const struct ovl_adaptor_comp_match comp_matches[OVL_ADAPTOR_ID_MAX] = { 92 [OVL_ADAPTOR_ETHDR0] = { OVL_ADAPTOR_TYPE_ETHDR, DDP_COMPONENT_ETHDR_MIXER, 0, ðdr }, 93 [OVL_ADAPTOR_MDP_RDMA0] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA0, 0, &rdma }, 94 [OVL_ADAPTOR_MDP_RDMA1] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA1, 1, &rdma }, 95 [OVL_ADAPTOR_MDP_RDMA2] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA2, 2, &rdma }, 96 [OVL_ADAPTOR_MDP_RDMA3] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA3, 3, &rdma }, 97 [OVL_ADAPTOR_MDP_RDMA4] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA4, 4, &rdma }, 98 [OVL_ADAPTOR_MDP_RDMA5] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA5, 5, &rdma }, 99 [OVL_ADAPTOR_MDP_RDMA6] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA6, 6, &rdma }, 100 [OVL_ADAPTOR_MDP_RDMA7] = { OVL_ADAPTOR_TYPE_MDP_RDMA, DDP_COMPONENT_MDP_RDMA7, 7, &rdma }, 101 [OVL_ADAPTOR_MERGE0] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE1, 1, &merge }, 102 [OVL_ADAPTOR_MERGE1] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE2, 2, &merge }, 103 [OVL_ADAPTOR_MERGE2] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE3, 3, &merge }, 104 [OVL_ADAPTOR_MERGE3] = { OVL_ADAPTOR_TYPE_MERGE, DDP_COMPONENT_MERGE4, 4, &merge }, 105 }; 106 107 void mtk_ovl_adaptor_layer_config(struct device *dev, unsigned int idx, 108 struct mtk_plane_state *state, 109 struct cmdq_pkt *cmdq_pkt) 110 { 111 struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev); 112 struct mtk_plane_pending_state *pending = &state->pending; 113 struct mtk_mdp_rdma_cfg rdma_config = {0}; 114 struct device *rdma_l; 115 struct device *rdma_r; 116 struct device *merge; 117 struct device *ethdr; 118 const struct drm_format_info *fmt_info = drm_format_info(pending->format); 119 bool use_dual_pipe = false; 120 unsigned int align_width; 121 unsigned int l_w = 0; 122 unsigned int r_w = 0; 123 124 dev_dbg(dev, "%s+ idx:%d, enable:%d, fmt:0x%x\n", __func__, idx, 125 pending->enable, pending->format); 126 dev_dbg(dev, "addr 0x%pad, fb w:%d, {%d,%d,%d,%d}\n", 127 &pending->addr, (pending->pitch / fmt_info->cpp[0]), 128 pending->x, pending->y, pending->width, pending->height); 129 130 rdma_l = ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_MDP_RDMA0 + 2 * idx]; 131 rdma_r = ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_MDP_RDMA0 + 2 * idx + 1]; 132 merge = ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_MERGE0 + idx]; 133 ethdr = ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0]; 134 135 if (!pending->enable) { 136 mtk_merge_stop_cmdq(merge, cmdq_pkt); 137 mtk_mdp_rdma_stop(rdma_l, cmdq_pkt); 138 mtk_mdp_rdma_stop(rdma_r, cmdq_pkt); 139 mtk_ethdr_layer_config(ethdr, idx, state, cmdq_pkt); 140 return; 141 } 142 143 /* ETHDR is in 1T2P domain, width needs to be 2 pixels align */ 144 align_width = ALIGN_DOWN(pending->width, 2); 145 146 if (align_width > MTK_OVL_ADAPTOR_RDMA_MAX_WIDTH) 147 use_dual_pipe = true; 148 149 if (use_dual_pipe) { 150 l_w = (align_width / 2) + ((pending->width / 2) % 2); 151 r_w = align_width - l_w; 152 } else { 153 l_w = align_width; 154 } 155 mtk_merge_advance_config(merge, l_w, r_w, pending->height, 0, 0, cmdq_pkt); 156 mtk_mmsys_merge_async_config(ovl_adaptor->mmsys_dev, idx, align_width / 2, 157 pending->height, cmdq_pkt); 158 159 rdma_config.width = l_w; 160 rdma_config.height = pending->height; 161 rdma_config.addr0 = pending->addr; 162 rdma_config.pitch = pending->pitch; 163 rdma_config.fmt = pending->format; 164 rdma_config.color_encoding = pending->color_encoding; 165 mtk_mdp_rdma_config(rdma_l, &rdma_config, cmdq_pkt); 166 167 if (use_dual_pipe) { 168 rdma_config.x_left = l_w; 169 rdma_config.width = r_w; 170 mtk_mdp_rdma_config(rdma_r, &rdma_config, cmdq_pkt); 171 } 172 173 mtk_merge_start_cmdq(merge, cmdq_pkt); 174 175 mtk_mdp_rdma_start(rdma_l, cmdq_pkt); 176 if (use_dual_pipe) 177 mtk_mdp_rdma_start(rdma_r, cmdq_pkt); 178 else 179 mtk_mdp_rdma_stop(rdma_r, cmdq_pkt); 180 181 mtk_ethdr_layer_config(ethdr, idx, state, cmdq_pkt); 182 } 183 184 void mtk_ovl_adaptor_config(struct device *dev, unsigned int w, 185 unsigned int h, unsigned int vrefresh, 186 unsigned int bpc, struct cmdq_pkt *cmdq_pkt) 187 { 188 struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev); 189 190 mtk_ethdr_config(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0], w, h, 191 vrefresh, bpc, cmdq_pkt); 192 } 193 194 void mtk_ovl_adaptor_start(struct device *dev) 195 { 196 int i; 197 struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev); 198 199 for (i = 0; i < OVL_ADAPTOR_ID_MAX; i++) { 200 if (!ovl_adaptor->ovl_adaptor_comp[i] || 201 !comp_matches[i].funcs->start) 202 continue; 203 204 comp_matches[i].funcs->start(ovl_adaptor->ovl_adaptor_comp[i]); 205 } 206 } 207 208 void mtk_ovl_adaptor_stop(struct device *dev) 209 { 210 int i; 211 struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev); 212 213 for (i = 0; i < OVL_ADAPTOR_ID_MAX; i++) { 214 if (!ovl_adaptor->ovl_adaptor_comp[i] || 215 !comp_matches[i].funcs->stop) 216 continue; 217 218 comp_matches[i].funcs->stop(ovl_adaptor->ovl_adaptor_comp[i]); 219 } 220 } 221 222 /** 223 * power_off - Power off the devices in OVL adaptor 224 * @dev: Device to be powered off 225 * @num: Number of the devices to be powered off 226 * 227 * Calls the .power_off() ovl_adaptor component callback if it is present. 228 */ 229 static inline void power_off(struct device *dev, int num) 230 { 231 struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev); 232 int i; 233 234 if (num > OVL_ADAPTOR_ID_MAX) 235 num = OVL_ADAPTOR_ID_MAX; 236 237 for (i = num - 1; i >= 0; i--) { 238 if (!ovl_adaptor->ovl_adaptor_comp[i] || 239 !comp_matches[i].funcs->power_off) 240 continue; 241 242 comp_matches[i].funcs->power_off(ovl_adaptor->ovl_adaptor_comp[i]); 243 } 244 } 245 246 /** 247 * mtk_ovl_adaptor_power_on - Power on the devices in OVL adaptor 248 * @dev: Device to be powered on 249 * 250 * Different from OVL, OVL adaptor is a pseudo device so 251 * we didn't define it in the device tree, pm_runtime_resume_and_get() 252 * called by .atomic_enable() power on no device in OVL adaptor, 253 * we have to implement a function to do the job instead. 254 * 255 * Return: Zero for success or negative number for failure. 256 */ 257 int mtk_ovl_adaptor_power_on(struct device *dev) 258 { 259 struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev); 260 int i, ret; 261 262 for (i = 0; i < OVL_ADAPTOR_ID_MAX; i++) { 263 if (!ovl_adaptor->ovl_adaptor_comp[i] || 264 !comp_matches[i].funcs->power_on) 265 continue; 266 267 ret = comp_matches[i].funcs->power_on(ovl_adaptor->ovl_adaptor_comp[i]); 268 if (ret < 0) { 269 dev_err(dev, "Failed to enable power domain %d, err %d\n", i, ret); 270 power_off(dev, i); 271 return ret; 272 } 273 } 274 return 0; 275 } 276 277 void mtk_ovl_adaptor_power_off(struct device *dev) 278 { 279 power_off(dev, OVL_ADAPTOR_ID_MAX); 280 } 281 282 int mtk_ovl_adaptor_clk_enable(struct device *dev) 283 { 284 struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev); 285 struct device *comp; 286 int ret; 287 int i; 288 289 for (i = 0; i < OVL_ADAPTOR_ID_MAX; i++) { 290 comp = ovl_adaptor->ovl_adaptor_comp[i]; 291 if (!comp || !comp_matches[i].funcs->clk_enable) 292 continue; 293 ret = comp_matches[i].funcs->clk_enable(comp); 294 if (ret) { 295 dev_err(dev, "Failed to enable clock %d, err %d\n", i, ret); 296 while (--i >= 0) 297 comp_matches[i].funcs->clk_disable(comp); 298 return ret; 299 } 300 } 301 return 0; 302 } 303 304 void mtk_ovl_adaptor_clk_disable(struct device *dev) 305 { 306 struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev); 307 struct device *comp; 308 int i; 309 310 for (i = 0; i < OVL_ADAPTOR_ID_MAX; i++) { 311 comp = ovl_adaptor->ovl_adaptor_comp[i]; 312 if (!comp || !comp_matches[i].funcs->clk_disable) 313 continue; 314 comp_matches[i].funcs->clk_disable(comp); 315 if (i < OVL_ADAPTOR_MERGE0) 316 pm_runtime_put(comp); 317 } 318 } 319 320 unsigned int mtk_ovl_adaptor_layer_nr(struct device *dev) 321 { 322 return MTK_OVL_ADAPTOR_LAYER_NUM; 323 } 324 325 struct device *mtk_ovl_adaptor_dma_dev_get(struct device *dev) 326 { 327 struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev); 328 329 return ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_MDP_RDMA0]; 330 } 331 332 void mtk_ovl_adaptor_register_vblank_cb(struct device *dev, void (*vblank_cb)(void *), 333 void *vblank_cb_data) 334 { 335 struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev); 336 337 mtk_ethdr_register_vblank_cb(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0], 338 vblank_cb, vblank_cb_data); 339 } 340 341 void mtk_ovl_adaptor_unregister_vblank_cb(struct device *dev) 342 { 343 struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev); 344 345 mtk_ethdr_unregister_vblank_cb(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0]); 346 } 347 348 void mtk_ovl_adaptor_enable_vblank(struct device *dev) 349 { 350 struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev); 351 352 mtk_ethdr_enable_vblank(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0]); 353 } 354 355 void mtk_ovl_adaptor_disable_vblank(struct device *dev) 356 { 357 struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev); 358 359 mtk_ethdr_disable_vblank(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_ETHDR0]); 360 } 361 362 const u32 *mtk_ovl_adaptor_get_formats(struct device *dev) 363 { 364 struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev); 365 366 return mtk_mdp_rdma_get_formats(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_MDP_RDMA0]); 367 } 368 369 size_t mtk_ovl_adaptor_get_num_formats(struct device *dev) 370 { 371 struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev); 372 373 return mtk_mdp_rdma_get_num_formats(ovl_adaptor->ovl_adaptor_comp[OVL_ADAPTOR_MDP_RDMA0]); 374 } 375 376 void mtk_ovl_adaptor_add_comp(struct device *dev, struct mtk_mutex *mutex) 377 { 378 int i; 379 struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev); 380 381 for (i = 0; i < OVL_ADAPTOR_ID_MAX; i++) { 382 if (!ovl_adaptor->ovl_adaptor_comp[i]) 383 continue; 384 mtk_mutex_add_comp(mutex, comp_matches[i].comp_id); 385 } 386 } 387 388 void mtk_ovl_adaptor_remove_comp(struct device *dev, struct mtk_mutex *mutex) 389 { 390 int i; 391 struct mtk_disp_ovl_adaptor *ovl_adaptor = dev_get_drvdata(dev); 392 393 for (i = 0; i < OVL_ADAPTOR_ID_MAX; i++) { 394 if (!ovl_adaptor->ovl_adaptor_comp[i]) 395 continue; 396 mtk_mutex_remove_comp(mutex, comp_matches[i].comp_id); 397 } 398 } 399 400 void mtk_ovl_adaptor_connect(struct device *dev, struct device *mmsys_dev, unsigned int next) 401 { 402 mtk_mmsys_ddp_connect(mmsys_dev, DDP_COMPONENT_ETHDR_MIXER, next); 403 mtk_mmsys_ddp_connect(mmsys_dev, DDP_COMPONENT_MDP_RDMA0, DDP_COMPONENT_MERGE1); 404 mtk_mmsys_ddp_connect(mmsys_dev, DDP_COMPONENT_MDP_RDMA1, DDP_COMPONENT_MERGE1); 405 mtk_mmsys_ddp_connect(mmsys_dev, DDP_COMPONENT_MDP_RDMA2, DDP_COMPONENT_MERGE2); 406 mtk_mmsys_ddp_connect(mmsys_dev, DDP_COMPONENT_MERGE1, DDP_COMPONENT_ETHDR_MIXER); 407 mtk_mmsys_ddp_connect(mmsys_dev, DDP_COMPONENT_MERGE2, DDP_COMPONENT_ETHDR_MIXER); 408 mtk_mmsys_ddp_connect(mmsys_dev, DDP_COMPONENT_MERGE3, DDP_COMPONENT_ETHDR_MIXER); 409 mtk_mmsys_ddp_connect(mmsys_dev, DDP_COMPONENT_MERGE4, DDP_COMPONENT_ETHDR_MIXER); 410 } 411 412 void mtk_ovl_adaptor_disconnect(struct device *dev, struct device *mmsys_dev, unsigned int next) 413 { 414 mtk_mmsys_ddp_disconnect(mmsys_dev, DDP_COMPONENT_ETHDR_MIXER, next); 415 mtk_mmsys_ddp_disconnect(mmsys_dev, DDP_COMPONENT_MDP_RDMA0, DDP_COMPONENT_MERGE1); 416 mtk_mmsys_ddp_disconnect(mmsys_dev, DDP_COMPONENT_MDP_RDMA1, DDP_COMPONENT_MERGE1); 417 mtk_mmsys_ddp_disconnect(mmsys_dev, DDP_COMPONENT_MDP_RDMA2, DDP_COMPONENT_MERGE2); 418 mtk_mmsys_ddp_disconnect(mmsys_dev, DDP_COMPONENT_MERGE1, DDP_COMPONENT_ETHDR_MIXER); 419 mtk_mmsys_ddp_disconnect(mmsys_dev, DDP_COMPONENT_MERGE2, DDP_COMPONENT_ETHDR_MIXER); 420 mtk_mmsys_ddp_disconnect(mmsys_dev, DDP_COMPONENT_MERGE3, DDP_COMPONENT_ETHDR_MIXER); 421 mtk_mmsys_ddp_disconnect(mmsys_dev, DDP_COMPONENT_MERGE4, DDP_COMPONENT_ETHDR_MIXER); 422 } 423 424 static int ovl_adaptor_comp_get_id(struct device *dev, struct device_node *node, 425 enum mtk_ovl_adaptor_comp_type type) 426 { 427 int alias_id = of_alias_get_id(node, private_comp_stem[type]); 428 int i; 429 430 for (i = 0; i < ARRAY_SIZE(comp_matches); i++) 431 if (comp_matches[i].type == type && 432 comp_matches[i].alias_id == alias_id) 433 return i; 434 435 dev_warn(dev, "Failed to get id. type: %d, alias: %d\n", type, alias_id); 436 return -EINVAL; 437 } 438 439 static const struct of_device_id mtk_ovl_adaptor_comp_dt_ids[] = { 440 { .compatible = "mediatek,mt8195-disp-ethdr", .data = (void *)OVL_ADAPTOR_TYPE_ETHDR }, 441 { .compatible = "mediatek,mt8195-disp-merge", .data = (void *)OVL_ADAPTOR_TYPE_MERGE }, 442 { .compatible = "mediatek,mt8195-vdo1-rdma", .data = (void *)OVL_ADAPTOR_TYPE_MDP_RDMA }, 443 { /* sentinel */ } 444 }; 445 446 static int compare_of(struct device *dev, void *data) 447 { 448 return dev->of_node == data; 449 } 450 451 static int ovl_adaptor_comp_init(struct device *dev, struct component_match **match) 452 { 453 struct mtk_disp_ovl_adaptor *priv = dev_get_drvdata(dev); 454 struct device_node *node, *parent; 455 struct platform_device *comp_pdev; 456 457 parent = dev->parent->parent->of_node->parent; 458 459 for_each_child_of_node(parent, node) { 460 const struct of_device_id *of_id; 461 enum mtk_ovl_adaptor_comp_type type; 462 int id; 463 464 of_id = of_match_node(mtk_ovl_adaptor_comp_dt_ids, node); 465 if (!of_id) 466 continue; 467 468 if (!of_device_is_available(node)) { 469 dev_dbg(dev, "Skipping disabled component %pOF\n", 470 node); 471 continue; 472 } 473 474 type = (enum mtk_ovl_adaptor_comp_type)(uintptr_t)of_id->data; 475 id = ovl_adaptor_comp_get_id(dev, node, type); 476 if (id < 0) { 477 dev_warn(dev, "Skipping unknown component %pOF\n", 478 node); 479 continue; 480 } 481 482 comp_pdev = of_find_device_by_node(node); 483 if (!comp_pdev) 484 return -EPROBE_DEFER; 485 486 priv->ovl_adaptor_comp[id] = &comp_pdev->dev; 487 488 drm_of_component_match_add(dev, match, compare_of, node); 489 dev_dbg(dev, "Adding component match for %pOF\n", node); 490 } 491 492 if (!*match) { 493 dev_err(dev, "No match device for ovl_adaptor\n"); 494 return -ENODEV; 495 } 496 497 return 0; 498 } 499 500 static int mtk_disp_ovl_adaptor_comp_bind(struct device *dev, struct device *master, 501 void *data) 502 { 503 struct mtk_disp_ovl_adaptor *priv = dev_get_drvdata(dev); 504 505 if (!priv->children_bound) 506 return -EPROBE_DEFER; 507 508 return 0; 509 } 510 511 static void mtk_disp_ovl_adaptor_comp_unbind(struct device *dev, struct device *master, 512 void *data) 513 { 514 } 515 516 static const struct component_ops mtk_disp_ovl_adaptor_comp_ops = { 517 .bind = mtk_disp_ovl_adaptor_comp_bind, 518 .unbind = mtk_disp_ovl_adaptor_comp_unbind, 519 }; 520 521 static int mtk_disp_ovl_adaptor_master_bind(struct device *dev) 522 { 523 struct mtk_disp_ovl_adaptor *priv = dev_get_drvdata(dev); 524 int ret; 525 526 ret = component_bind_all(dev, priv->mmsys_dev); 527 if (ret) 528 return dev_err_probe(dev, ret, "component_bind_all failed!\n"); 529 530 priv->children_bound = true; 531 return 0; 532 } 533 534 static void mtk_disp_ovl_adaptor_master_unbind(struct device *dev) 535 { 536 struct mtk_disp_ovl_adaptor *priv = dev_get_drvdata(dev); 537 538 priv->children_bound = false; 539 } 540 541 static const struct component_master_ops mtk_disp_ovl_adaptor_master_ops = { 542 .bind = mtk_disp_ovl_adaptor_master_bind, 543 .unbind = mtk_disp_ovl_adaptor_master_unbind, 544 }; 545 546 static int mtk_disp_ovl_adaptor_probe(struct platform_device *pdev) 547 { 548 struct mtk_disp_ovl_adaptor *priv; 549 struct device *dev = &pdev->dev; 550 struct component_match *match = NULL; 551 int ret; 552 553 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 554 if (!priv) 555 return -ENOMEM; 556 557 platform_set_drvdata(pdev, priv); 558 559 ret = ovl_adaptor_comp_init(dev, &match); 560 if (ret < 0) 561 return ret; 562 563 priv->mmsys_dev = pdev->dev.platform_data; 564 565 component_master_add_with_match(dev, &mtk_disp_ovl_adaptor_master_ops, match); 566 567 pm_runtime_enable(dev); 568 569 ret = component_add(dev, &mtk_disp_ovl_adaptor_comp_ops); 570 if (ret != 0) { 571 pm_runtime_disable(dev); 572 dev_err(dev, "Failed to add component: %d\n", ret); 573 } 574 575 return ret; 576 } 577 578 static void mtk_disp_ovl_adaptor_remove(struct platform_device *pdev) 579 { 580 component_master_del(&pdev->dev, &mtk_disp_ovl_adaptor_master_ops); 581 pm_runtime_disable(&pdev->dev); 582 } 583 584 struct platform_driver mtk_disp_ovl_adaptor_driver = { 585 .probe = mtk_disp_ovl_adaptor_probe, 586 .remove_new = mtk_disp_ovl_adaptor_remove, 587 .driver = { 588 .name = "mediatek-disp-ovl-adaptor", 589 .owner = THIS_MODULE, 590 }, 591 }; 592