1/* 2 * Freescale i.MX drm driver 3 * 4 * Copyright (C) 2011 Sascha Hauer, Pengutronix 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 2 9 * of the License, or (at your option) any later version. 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 */ 16#include <linux/component.h> 17#include <linux/device.h> 18#include <linux/fb.h> 19#include <linux/module.h> 20#include <linux/of_graph.h> 21#include <linux/platform_device.h> 22#include <drm/drmP.h> 23#include <drm/drm_fb_helper.h> 24#include <drm/drm_crtc_helper.h> 25#include <drm/drm_gem_cma_helper.h> 26#include <drm/drm_fb_cma_helper.h> 27#include <drm/drm_plane_helper.h> 28#include <drm/drm_of.h> 29 30#include "imx-drm.h" 31 32#define MAX_CRTC 4 33 34struct imx_drm_component { 35 struct device_node *of_node; 36 struct list_head list; 37}; 38 39struct imx_drm_device { 40 struct drm_device *drm; 41 struct imx_drm_crtc *crtc[MAX_CRTC]; 42 int pipes; 43 struct drm_fbdev_cma *fbhelper; 44}; 45 46struct imx_drm_crtc { 47 struct drm_crtc *crtc; 48 int pipe; 49 struct imx_drm_crtc_helper_funcs imx_drm_helper_funcs; 50}; 51 52static int legacyfb_depth = 16; 53module_param(legacyfb_depth, int, 0444); 54 55int imx_drm_crtc_id(struct imx_drm_crtc *crtc) 56{ 57 return crtc->pipe; 58} 59EXPORT_SYMBOL_GPL(imx_drm_crtc_id); 60 61static void imx_drm_driver_lastclose(struct drm_device *drm) 62{ 63#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER) 64 struct imx_drm_device *imxdrm = drm->dev_private; 65 66 if (imxdrm->fbhelper) 67 drm_fbdev_cma_restore_mode(imxdrm->fbhelper); 68#endif 69} 70 71static int imx_drm_driver_unload(struct drm_device *drm) 72{ 73#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER) 74 struct imx_drm_device *imxdrm = drm->dev_private; 75#endif 76 77 drm_kms_helper_poll_fini(drm); 78 79#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER) 80 if (imxdrm->fbhelper) 81 drm_fbdev_cma_fini(imxdrm->fbhelper); 82#endif 83 84 component_unbind_all(drm->dev, drm); 85 86 drm_vblank_cleanup(drm); 87 drm_mode_config_cleanup(drm); 88 89 platform_set_drvdata(drm->platformdev, NULL); 90 91 return 0; 92} 93 94static struct imx_drm_crtc *imx_drm_find_crtc(struct drm_crtc *crtc) 95{ 96 struct imx_drm_device *imxdrm = crtc->dev->dev_private; 97 unsigned i; 98 99 for (i = 0; i < MAX_CRTC; i++) 100 if (imxdrm->crtc[i] && imxdrm->crtc[i]->crtc == crtc) 101 return imxdrm->crtc[i]; 102 103 return NULL; 104} 105 106int imx_drm_set_bus_format_pins(struct drm_encoder *encoder, u32 bus_format, 107 int hsync_pin, int vsync_pin) 108{ 109 struct imx_drm_crtc_helper_funcs *helper; 110 struct imx_drm_crtc *imx_crtc; 111 112 imx_crtc = imx_drm_find_crtc(encoder->crtc); 113 if (!imx_crtc) 114 return -EINVAL; 115 116 helper = &imx_crtc->imx_drm_helper_funcs; 117 if (helper->set_interface_pix_fmt) 118 return helper->set_interface_pix_fmt(encoder->crtc, 119 bus_format, hsync_pin, vsync_pin); 120 return 0; 121} 122EXPORT_SYMBOL_GPL(imx_drm_set_bus_format_pins); 123 124int imx_drm_set_bus_format(struct drm_encoder *encoder, u32 bus_format) 125{ 126 return imx_drm_set_bus_format_pins(encoder, bus_format, 2, 3); 127} 128EXPORT_SYMBOL_GPL(imx_drm_set_bus_format); 129 130int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc) 131{ 132 return drm_vblank_get(imx_drm_crtc->crtc->dev, imx_drm_crtc->pipe); 133} 134EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_get); 135 136void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc) 137{ 138 drm_vblank_put(imx_drm_crtc->crtc->dev, imx_drm_crtc->pipe); 139} 140EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_put); 141 142void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc) 143{ 144 drm_handle_vblank(imx_drm_crtc->crtc->dev, imx_drm_crtc->pipe); 145} 146EXPORT_SYMBOL_GPL(imx_drm_handle_vblank); 147 148static int imx_drm_enable_vblank(struct drm_device *drm, int crtc) 149{ 150 struct imx_drm_device *imxdrm = drm->dev_private; 151 struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[crtc]; 152 int ret; 153 154 if (!imx_drm_crtc) 155 return -EINVAL; 156 157 if (!imx_drm_crtc->imx_drm_helper_funcs.enable_vblank) 158 return -ENOSYS; 159 160 ret = imx_drm_crtc->imx_drm_helper_funcs.enable_vblank( 161 imx_drm_crtc->crtc); 162 163 return ret; 164} 165 166static void imx_drm_disable_vblank(struct drm_device *drm, int crtc) 167{ 168 struct imx_drm_device *imxdrm = drm->dev_private; 169 struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[crtc]; 170 171 if (!imx_drm_crtc) 172 return; 173 174 if (!imx_drm_crtc->imx_drm_helper_funcs.disable_vblank) 175 return; 176 177 imx_drm_crtc->imx_drm_helper_funcs.disable_vblank(imx_drm_crtc->crtc); 178} 179 180static void imx_drm_driver_preclose(struct drm_device *drm, 181 struct drm_file *file) 182{ 183 int i; 184 185 if (!file->is_master) 186 return; 187 188 for (i = 0; i < MAX_CRTC; i++) 189 imx_drm_disable_vblank(drm, i); 190} 191 192static const struct file_operations imx_drm_driver_fops = { 193 .owner = THIS_MODULE, 194 .open = drm_open, 195 .release = drm_release, 196 .unlocked_ioctl = drm_ioctl, 197 .mmap = drm_gem_cma_mmap, 198 .poll = drm_poll, 199 .read = drm_read, 200 .llseek = noop_llseek, 201}; 202 203void imx_drm_connector_destroy(struct drm_connector *connector) 204{ 205 drm_connector_unregister(connector); 206 drm_connector_cleanup(connector); 207} 208EXPORT_SYMBOL_GPL(imx_drm_connector_destroy); 209 210void imx_drm_encoder_destroy(struct drm_encoder *encoder) 211{ 212 drm_encoder_cleanup(encoder); 213} 214EXPORT_SYMBOL_GPL(imx_drm_encoder_destroy); 215 216static void imx_drm_output_poll_changed(struct drm_device *drm) 217{ 218#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER) 219 struct imx_drm_device *imxdrm = drm->dev_private; 220 221 drm_fbdev_cma_hotplug_event(imxdrm->fbhelper); 222#endif 223} 224 225static struct drm_mode_config_funcs imx_drm_mode_config_funcs = { 226 .fb_create = drm_fb_cma_create, 227 .output_poll_changed = imx_drm_output_poll_changed, 228}; 229 230/* 231 * Main DRM initialisation. This binds, initialises and registers 232 * with DRM the subcomponents of the driver. 233 */ 234static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags) 235{ 236 struct imx_drm_device *imxdrm; 237 struct drm_connector *connector; 238 int ret; 239 240 imxdrm = devm_kzalloc(drm->dev, sizeof(*imxdrm), GFP_KERNEL); 241 if (!imxdrm) 242 return -ENOMEM; 243 244 imxdrm->drm = drm; 245 246 drm->dev_private = imxdrm; 247 248 /* 249 * enable drm irq mode. 250 * - with irq_enabled = true, we can use the vblank feature. 251 * 252 * P.S. note that we wouldn't use drm irq handler but 253 * just specific driver own one instead because 254 * drm framework supports only one irq handler and 255 * drivers can well take care of their interrupts 256 */ 257 drm->irq_enabled = true; 258 259 /* 260 * set max width and height as default value(4096x4096). 261 * this value would be used to check framebuffer size limitation 262 * at drm_mode_addfb(). 263 */ 264 drm->mode_config.min_width = 64; 265 drm->mode_config.min_height = 64; 266 drm->mode_config.max_width = 4096; 267 drm->mode_config.max_height = 4096; 268 drm->mode_config.funcs = &imx_drm_mode_config_funcs; 269 270 drm_mode_config_init(drm); 271 272 ret = drm_vblank_init(drm, MAX_CRTC); 273 if (ret) 274 goto err_kms; 275 276 /* 277 * with vblank_disable_allowed = true, vblank interrupt will be 278 * disabled by drm timer once a current process gives up ownership 279 * of vblank event. (after drm_vblank_put function is called) 280 */ 281 drm->vblank_disable_allowed = true; 282 283 platform_set_drvdata(drm->platformdev, drm); 284 285 /* Now try and bind all our sub-components */ 286 ret = component_bind_all(drm->dev, drm); 287 if (ret) 288 goto err_vblank; 289 290 /* 291 * All components are now added, we can publish the connector sysfs 292 * entries to userspace. This will generate hotplug events and so 293 * userspace will expect to be able to access DRM at this point. 294 */ 295 list_for_each_entry(connector, &drm->mode_config.connector_list, head) { 296 ret = drm_connector_register(connector); 297 if (ret) { 298 dev_err(drm->dev, 299 "[CONNECTOR:%d:%s] drm_connector_register failed: %d\n", 300 connector->base.id, 301 connector->name, ret); 302 goto err_unbind; 303 } 304 } 305 306 /* 307 * All components are now initialised, so setup the fb helper. 308 * The fb helper takes copies of key hardware information, so the 309 * crtcs/connectors/encoders must not change after this point. 310 */ 311#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER) 312 if (legacyfb_depth != 16 && legacyfb_depth != 32) { 313 dev_warn(drm->dev, "Invalid legacyfb_depth. Defaulting to 16bpp\n"); 314 legacyfb_depth = 16; 315 } 316 imxdrm->fbhelper = drm_fbdev_cma_init(drm, legacyfb_depth, 317 drm->mode_config.num_crtc, MAX_CRTC); 318 if (IS_ERR(imxdrm->fbhelper)) { 319 ret = PTR_ERR(imxdrm->fbhelper); 320 imxdrm->fbhelper = NULL; 321 goto err_unbind; 322 } 323#endif 324 325 drm_kms_helper_poll_init(drm); 326 327 return 0; 328 329err_unbind: 330 component_unbind_all(drm->dev, drm); 331err_vblank: 332 drm_vblank_cleanup(drm); 333err_kms: 334 drm_mode_config_cleanup(drm); 335 336 return ret; 337} 338 339/* 340 * imx_drm_add_crtc - add a new crtc 341 */ 342int imx_drm_add_crtc(struct drm_device *drm, struct drm_crtc *crtc, 343 struct imx_drm_crtc **new_crtc, 344 const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs, 345 struct device_node *port) 346{ 347 struct imx_drm_device *imxdrm = drm->dev_private; 348 struct imx_drm_crtc *imx_drm_crtc; 349 int ret; 350 351 /* 352 * The vblank arrays are dimensioned by MAX_CRTC - we can't 353 * pass IDs greater than this to those functions. 354 */ 355 if (imxdrm->pipes >= MAX_CRTC) 356 return -EINVAL; 357 358 if (imxdrm->drm->open_count) 359 return -EBUSY; 360 361 imx_drm_crtc = kzalloc(sizeof(*imx_drm_crtc), GFP_KERNEL); 362 if (!imx_drm_crtc) 363 return -ENOMEM; 364 365 imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs; 366 imx_drm_crtc->pipe = imxdrm->pipes++; 367 imx_drm_crtc->crtc = crtc; 368 369 crtc->port = port; 370 371 imxdrm->crtc[imx_drm_crtc->pipe] = imx_drm_crtc; 372 373 *new_crtc = imx_drm_crtc; 374 375 ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, 256); 376 if (ret) 377 goto err_register; 378 379 drm_crtc_helper_add(crtc, 380 imx_drm_crtc->imx_drm_helper_funcs.crtc_helper_funcs); 381 382 drm_crtc_init(drm, crtc, 383 imx_drm_crtc->imx_drm_helper_funcs.crtc_funcs); 384 385 return 0; 386 387err_register: 388 imxdrm->crtc[imx_drm_crtc->pipe] = NULL; 389 kfree(imx_drm_crtc); 390 return ret; 391} 392EXPORT_SYMBOL_GPL(imx_drm_add_crtc); 393 394/* 395 * imx_drm_remove_crtc - remove a crtc 396 */ 397int imx_drm_remove_crtc(struct imx_drm_crtc *imx_drm_crtc) 398{ 399 struct imx_drm_device *imxdrm = imx_drm_crtc->crtc->dev->dev_private; 400 401 drm_crtc_cleanup(imx_drm_crtc->crtc); 402 403 imxdrm->crtc[imx_drm_crtc->pipe] = NULL; 404 405 kfree(imx_drm_crtc); 406 407 return 0; 408} 409EXPORT_SYMBOL_GPL(imx_drm_remove_crtc); 410 411int imx_drm_encoder_parse_of(struct drm_device *drm, 412 struct drm_encoder *encoder, struct device_node *np) 413{ 414 uint32_t crtc_mask = drm_of_find_possible_crtcs(drm, np); 415 416 /* 417 * If we failed to find the CRTC(s) which this encoder is 418 * supposed to be connected to, it's because the CRTC has 419 * not been registered yet. Defer probing, and hope that 420 * the required CRTC is added later. 421 */ 422 if (crtc_mask == 0) 423 return -EPROBE_DEFER; 424 425 encoder->possible_crtcs = crtc_mask; 426 427 /* FIXME: this is the mask of outputs which can clone this output. */ 428 encoder->possible_clones = ~0; 429 430 return 0; 431} 432EXPORT_SYMBOL_GPL(imx_drm_encoder_parse_of); 433 434/* 435 * @node: device tree node containing encoder input ports 436 * @encoder: drm_encoder 437 */ 438int imx_drm_encoder_get_mux_id(struct device_node *node, 439 struct drm_encoder *encoder) 440{ 441 struct imx_drm_crtc *imx_crtc = imx_drm_find_crtc(encoder->crtc); 442 struct device_node *ep; 443 struct of_endpoint endpoint; 444 struct device_node *port; 445 int ret; 446 447 if (!node || !imx_crtc) 448 return -EINVAL; 449 450 for_each_endpoint_of_node(node, ep) { 451 port = of_graph_get_remote_port(ep); 452 of_node_put(port); 453 if (port == imx_crtc->crtc->port) { 454 ret = of_graph_parse_endpoint(ep, &endpoint); 455 of_node_put(ep); 456 return ret ? ret : endpoint.port; 457 } 458 } 459 460 return -EINVAL; 461} 462EXPORT_SYMBOL_GPL(imx_drm_encoder_get_mux_id); 463 464static const struct drm_ioctl_desc imx_drm_ioctls[] = { 465 /* none so far */ 466}; 467 468static struct drm_driver imx_drm_driver = { 469 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME, 470 .load = imx_drm_driver_load, 471 .unload = imx_drm_driver_unload, 472 .lastclose = imx_drm_driver_lastclose, 473 .preclose = imx_drm_driver_preclose, 474 .set_busid = drm_platform_set_busid, 475 .gem_free_object = drm_gem_cma_free_object, 476 .gem_vm_ops = &drm_gem_cma_vm_ops, 477 .dumb_create = drm_gem_cma_dumb_create, 478 .dumb_map_offset = drm_gem_cma_dumb_map_offset, 479 .dumb_destroy = drm_gem_dumb_destroy, 480 481 .prime_handle_to_fd = drm_gem_prime_handle_to_fd, 482 .prime_fd_to_handle = drm_gem_prime_fd_to_handle, 483 .gem_prime_import = drm_gem_prime_import, 484 .gem_prime_export = drm_gem_prime_export, 485 .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, 486 .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, 487 .gem_prime_vmap = drm_gem_cma_prime_vmap, 488 .gem_prime_vunmap = drm_gem_cma_prime_vunmap, 489 .gem_prime_mmap = drm_gem_cma_prime_mmap, 490 .get_vblank_counter = drm_vblank_count, 491 .enable_vblank = imx_drm_enable_vblank, 492 .disable_vblank = imx_drm_disable_vblank, 493 .ioctls = imx_drm_ioctls, 494 .num_ioctls = ARRAY_SIZE(imx_drm_ioctls), 495 .fops = &imx_drm_driver_fops, 496 .name = "imx-drm", 497 .desc = "i.MX DRM graphics", 498 .date = "20120507", 499 .major = 1, 500 .minor = 0, 501 .patchlevel = 0, 502}; 503 504static int compare_of(struct device *dev, void *data) 505{ 506 struct device_node *np = data; 507 508 /* Special case for LDB, one device for two channels */ 509 if (of_node_cmp(np->name, "lvds-channel") == 0) { 510 np = of_get_parent(np); 511 of_node_put(np); 512 } 513 514 return dev->of_node == np; 515} 516 517static int imx_drm_bind(struct device *dev) 518{ 519 return drm_platform_init(&imx_drm_driver, to_platform_device(dev)); 520} 521 522static void imx_drm_unbind(struct device *dev) 523{ 524 drm_put_dev(dev_get_drvdata(dev)); 525} 526 527static const struct component_master_ops imx_drm_ops = { 528 .bind = imx_drm_bind, 529 .unbind = imx_drm_unbind, 530}; 531 532static int imx_drm_platform_probe(struct platform_device *pdev) 533{ 534 struct device_node *ep, *port, *remote; 535 struct component_match *match = NULL; 536 int ret; 537 int i; 538 539 /* 540 * Bind the IPU display interface ports first, so that 541 * imx_drm_encoder_parse_of called from encoder .bind callbacks 542 * works as expected. 543 */ 544 for (i = 0; ; i++) { 545 port = of_parse_phandle(pdev->dev.of_node, "ports", i); 546 if (!port) 547 break; 548 549 component_match_add(&pdev->dev, &match, compare_of, port); 550 } 551 552 if (i == 0) { 553 dev_err(&pdev->dev, "missing 'ports' property\n"); 554 return -ENODEV; 555 } 556 557 /* Then bind all encoders */ 558 for (i = 0; ; i++) { 559 port = of_parse_phandle(pdev->dev.of_node, "ports", i); 560 if (!port) 561 break; 562 563 for_each_child_of_node(port, ep) { 564 remote = of_graph_get_remote_port_parent(ep); 565 if (!remote || !of_device_is_available(remote)) { 566 of_node_put(remote); 567 continue; 568 } else if (!of_device_is_available(remote->parent)) { 569 dev_warn(&pdev->dev, "parent device of %s is not available\n", 570 remote->full_name); 571 of_node_put(remote); 572 continue; 573 } 574 575 component_match_add(&pdev->dev, &match, compare_of, 576 remote); 577 of_node_put(remote); 578 } 579 of_node_put(port); 580 } 581 582 ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); 583 if (ret) 584 return ret; 585 586 return component_master_add_with_match(&pdev->dev, &imx_drm_ops, match); 587} 588 589static int imx_drm_platform_remove(struct platform_device *pdev) 590{ 591 component_master_del(&pdev->dev, &imx_drm_ops); 592 return 0; 593} 594 595#ifdef CONFIG_PM_SLEEP 596static int imx_drm_suspend(struct device *dev) 597{ 598 struct drm_device *drm_dev = dev_get_drvdata(dev); 599 600 /* The drm_dev is NULL before .load hook is called */ 601 if (drm_dev == NULL) 602 return 0; 603 604 drm_kms_helper_poll_disable(drm_dev); 605 606 return 0; 607} 608 609static int imx_drm_resume(struct device *dev) 610{ 611 struct drm_device *drm_dev = dev_get_drvdata(dev); 612 613 if (drm_dev == NULL) 614 return 0; 615 616 drm_helper_resume_force_mode(drm_dev); 617 drm_kms_helper_poll_enable(drm_dev); 618 619 return 0; 620} 621#endif 622 623static SIMPLE_DEV_PM_OPS(imx_drm_pm_ops, imx_drm_suspend, imx_drm_resume); 624 625static const struct of_device_id imx_drm_dt_ids[] = { 626 { .compatible = "fsl,imx-display-subsystem", }, 627 { /* sentinel */ }, 628}; 629MODULE_DEVICE_TABLE(of, imx_drm_dt_ids); 630 631static struct platform_driver imx_drm_pdrv = { 632 .probe = imx_drm_platform_probe, 633 .remove = imx_drm_platform_remove, 634 .driver = { 635 .name = "imx-drm", 636 .pm = &imx_drm_pm_ops, 637 .of_match_table = imx_drm_dt_ids, 638 }, 639}; 640module_platform_driver(imx_drm_pdrv); 641 642MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); 643MODULE_DESCRIPTION("i.MX drm driver core"); 644MODULE_LICENSE("GPL"); 645