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#include <video/imx-ipu-v3.h> 30 31#include "imx-drm.h" 32 33#define MAX_CRTC 4 34 35struct imx_drm_component { 36 struct device_node *of_node; 37 struct list_head list; 38}; 39 40struct imx_drm_device { 41 struct drm_device *drm; 42 struct imx_drm_crtc *crtc[MAX_CRTC]; 43 int pipes; 44 struct drm_fbdev_cma *fbhelper; 45}; 46 47struct imx_drm_crtc { 48 struct drm_crtc *crtc; 49 int pipe; 50 struct imx_drm_crtc_helper_funcs imx_drm_helper_funcs; 51}; 52 53static int legacyfb_depth = 16; 54module_param(legacyfb_depth, int, 0444); 55 56int imx_drm_crtc_id(struct imx_drm_crtc *crtc) 57{ 58 return crtc->pipe; 59} 60EXPORT_SYMBOL_GPL(imx_drm_crtc_id); 61 62static void imx_drm_driver_lastclose(struct drm_device *drm) 63{ 64#if IS_ENABLED(CONFIG_DRM_IMX_FB_HELPER) 65 struct imx_drm_device *imxdrm = drm->dev_private; 66 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, unsigned int pipe) 149{ 150 struct imx_drm_device *imxdrm = drm->dev_private; 151 struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[pipe]; 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, unsigned int pipe) 167{ 168 struct imx_drm_device *imxdrm = drm->dev_private; 169 struct imx_drm_crtc *imx_drm_crtc = imxdrm->crtc[pipe]; 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, struct drm_plane *primary_plane, 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_with_planes(drm, crtc, primary_plane, NULL, 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_no_hw_counter, 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 DI, dev->of_node may not be set yet */ 509 if (strcmp(dev->driver->name, "imx-ipuv3-crtc") == 0) { 510 struct ipu_client_platformdata *pdata = dev->platform_data; 511 512 return pdata->of_node == np; 513 } 514 515 /* Special case for LDB, one device for two channels */ 516 if (of_node_cmp(np->name, "lvds-channel") == 0) { 517 np = of_get_parent(np); 518 of_node_put(np); 519 } 520 521 return dev->of_node == np; 522} 523 524static int imx_drm_bind(struct device *dev) 525{ 526 return drm_platform_init(&imx_drm_driver, to_platform_device(dev)); 527} 528 529static void imx_drm_unbind(struct device *dev) 530{ 531 drm_put_dev(dev_get_drvdata(dev)); 532} 533 534static const struct component_master_ops imx_drm_ops = { 535 .bind = imx_drm_bind, 536 .unbind = imx_drm_unbind, 537}; 538 539static int imx_drm_platform_probe(struct platform_device *pdev) 540{ 541 int ret = drm_of_component_probe(&pdev->dev, compare_of, &imx_drm_ops); 542 543 if (!ret) 544 ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); 545 546 return ret; 547} 548 549static int imx_drm_platform_remove(struct platform_device *pdev) 550{ 551 component_master_del(&pdev->dev, &imx_drm_ops); 552 return 0; 553} 554 555#ifdef CONFIG_PM_SLEEP 556static int imx_drm_suspend(struct device *dev) 557{ 558 struct drm_device *drm_dev = dev_get_drvdata(dev); 559 560 /* The drm_dev is NULL before .load hook is called */ 561 if (drm_dev == NULL) 562 return 0; 563 564 drm_kms_helper_poll_disable(drm_dev); 565 566 return 0; 567} 568 569static int imx_drm_resume(struct device *dev) 570{ 571 struct drm_device *drm_dev = dev_get_drvdata(dev); 572 573 if (drm_dev == NULL) 574 return 0; 575 576 drm_helper_resume_force_mode(drm_dev); 577 drm_kms_helper_poll_enable(drm_dev); 578 579 return 0; 580} 581#endif 582 583static SIMPLE_DEV_PM_OPS(imx_drm_pm_ops, imx_drm_suspend, imx_drm_resume); 584 585static const struct of_device_id imx_drm_dt_ids[] = { 586 { .compatible = "fsl,imx-display-subsystem", }, 587 { /* sentinel */ }, 588}; 589MODULE_DEVICE_TABLE(of, imx_drm_dt_ids); 590 591static struct platform_driver imx_drm_pdrv = { 592 .probe = imx_drm_platform_probe, 593 .remove = imx_drm_platform_remove, 594 .driver = { 595 .name = "imx-drm", 596 .pm = &imx_drm_pm_ops, 597 .of_match_table = imx_drm_dt_ids, 598 }, 599}; 600module_platform_driver(imx_drm_pdrv); 601 602MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); 603MODULE_DESCRIPTION("i.MX drm driver core"); 604MODULE_LICENSE("GPL"); 605