Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.7-rc1 595 lines 15 kB view raw
1/* 2 * i.MX IPUv3 Graphics 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#include <linux/component.h> 16#include <linux/module.h> 17#include <linux/export.h> 18#include <linux/device.h> 19#include <linux/platform_device.h> 20#include <drm/drmP.h> 21#include <drm/drm_crtc_helper.h> 22#include <linux/fb.h> 23#include <linux/clk.h> 24#include <linux/errno.h> 25#include <linux/reservation.h> 26#include <linux/dma-buf.h> 27#include <drm/drm_gem_cma_helper.h> 28#include <drm/drm_fb_cma_helper.h> 29 30#include <video/imx-ipu-v3.h> 31#include "imx-drm.h" 32#include "ipuv3-plane.h" 33 34#define DRIVER_DESC "i.MX IPUv3 Graphics" 35 36enum ipu_flip_status { 37 IPU_FLIP_NONE, 38 IPU_FLIP_PENDING, 39 IPU_FLIP_SUBMITTED, 40}; 41 42struct ipu_flip_work { 43 struct work_struct unref_work; 44 struct drm_gem_object *bo; 45 struct drm_pending_vblank_event *page_flip_event; 46 struct work_struct fence_work; 47 struct ipu_crtc *crtc; 48 struct fence *excl; 49 unsigned shared_count; 50 struct fence **shared; 51}; 52 53struct ipu_crtc { 54 struct device *dev; 55 struct drm_crtc base; 56 struct imx_drm_crtc *imx_crtc; 57 58 /* plane[0] is the full plane, plane[1] is the partial plane */ 59 struct ipu_plane *plane[2]; 60 61 struct ipu_dc *dc; 62 struct ipu_di *di; 63 int enabled; 64 enum ipu_flip_status flip_state; 65 struct workqueue_struct *flip_queue; 66 struct ipu_flip_work *flip_work; 67 int irq; 68 u32 bus_format; 69 int di_hsync_pin; 70 int di_vsync_pin; 71}; 72 73#define to_ipu_crtc(x) container_of(x, struct ipu_crtc, base) 74 75static void ipu_fb_enable(struct ipu_crtc *ipu_crtc) 76{ 77 struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); 78 79 if (ipu_crtc->enabled) 80 return; 81 82 ipu_dc_enable(ipu); 83 ipu_plane_enable(ipu_crtc->plane[0]); 84 /* Start DC channel and DI after IDMAC */ 85 ipu_dc_enable_channel(ipu_crtc->dc); 86 ipu_di_enable(ipu_crtc->di); 87 drm_crtc_vblank_on(&ipu_crtc->base); 88 89 ipu_crtc->enabled = 1; 90} 91 92static void ipu_fb_disable(struct ipu_crtc *ipu_crtc) 93{ 94 struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); 95 96 if (!ipu_crtc->enabled) 97 return; 98 99 /* Stop DC channel and DI before IDMAC */ 100 ipu_dc_disable_channel(ipu_crtc->dc); 101 ipu_di_disable(ipu_crtc->di); 102 ipu_plane_disable(ipu_crtc->plane[0]); 103 ipu_dc_disable(ipu); 104 drm_crtc_vblank_off(&ipu_crtc->base); 105 106 ipu_crtc->enabled = 0; 107} 108 109static void ipu_crtc_dpms(struct drm_crtc *crtc, int mode) 110{ 111 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 112 113 dev_dbg(ipu_crtc->dev, "%s mode: %d\n", __func__, mode); 114 115 switch (mode) { 116 case DRM_MODE_DPMS_ON: 117 ipu_fb_enable(ipu_crtc); 118 break; 119 case DRM_MODE_DPMS_STANDBY: 120 case DRM_MODE_DPMS_SUSPEND: 121 case DRM_MODE_DPMS_OFF: 122 ipu_fb_disable(ipu_crtc); 123 break; 124 } 125} 126 127static void ipu_flip_unref_work_func(struct work_struct *__work) 128{ 129 struct ipu_flip_work *work = 130 container_of(__work, struct ipu_flip_work, unref_work); 131 132 drm_gem_object_unreference_unlocked(work->bo); 133 kfree(work); 134} 135 136static void ipu_flip_fence_work_func(struct work_struct *__work) 137{ 138 struct ipu_flip_work *work = 139 container_of(__work, struct ipu_flip_work, fence_work); 140 int i; 141 142 /* wait for all fences attached to the FB obj to signal */ 143 if (work->excl) { 144 fence_wait(work->excl, false); 145 fence_put(work->excl); 146 } 147 for (i = 0; i < work->shared_count; i++) { 148 fence_wait(work->shared[i], false); 149 fence_put(work->shared[i]); 150 } 151 152 work->crtc->flip_state = IPU_FLIP_SUBMITTED; 153} 154 155static int ipu_page_flip(struct drm_crtc *crtc, 156 struct drm_framebuffer *fb, 157 struct drm_pending_vblank_event *event, 158 uint32_t page_flip_flags) 159{ 160 struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); 161 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 162 struct ipu_flip_work *flip_work; 163 int ret; 164 165 if (ipu_crtc->flip_state != IPU_FLIP_NONE) 166 return -EBUSY; 167 168 ret = imx_drm_crtc_vblank_get(ipu_crtc->imx_crtc); 169 if (ret) { 170 dev_dbg(ipu_crtc->dev, "failed to acquire vblank counter\n"); 171 list_del(&event->base.link); 172 173 return ret; 174 } 175 176 flip_work = kzalloc(sizeof *flip_work, GFP_KERNEL); 177 if (!flip_work) { 178 ret = -ENOMEM; 179 goto put_vblank; 180 } 181 INIT_WORK(&flip_work->unref_work, ipu_flip_unref_work_func); 182 flip_work->page_flip_event = event; 183 184 /* get BO backing the old framebuffer and take a reference */ 185 flip_work->bo = &drm_fb_cma_get_gem_obj(crtc->primary->fb, 0)->base; 186 drm_gem_object_reference(flip_work->bo); 187 188 ipu_crtc->flip_work = flip_work; 189 /* 190 * If the object has a DMABUF attached, we need to wait on its fences 191 * if there are any. 192 */ 193 if (cma_obj->base.dma_buf) { 194 INIT_WORK(&flip_work->fence_work, ipu_flip_fence_work_func); 195 flip_work->crtc = ipu_crtc; 196 197 ret = reservation_object_get_fences_rcu( 198 cma_obj->base.dma_buf->resv, &flip_work->excl, 199 &flip_work->shared_count, &flip_work->shared); 200 201 if (unlikely(ret)) { 202 DRM_ERROR("failed to get fences for buffer\n"); 203 goto free_flip_work; 204 } 205 206 /* No need to queue the worker if the are no fences */ 207 if (!flip_work->excl && !flip_work->shared_count) { 208 ipu_crtc->flip_state = IPU_FLIP_SUBMITTED; 209 } else { 210 ipu_crtc->flip_state = IPU_FLIP_PENDING; 211 queue_work(ipu_crtc->flip_queue, 212 &flip_work->fence_work); 213 } 214 } else { 215 ipu_crtc->flip_state = IPU_FLIP_SUBMITTED; 216 } 217 218 return 0; 219 220free_flip_work: 221 drm_gem_object_unreference_unlocked(flip_work->bo); 222 kfree(flip_work); 223 ipu_crtc->flip_work = NULL; 224put_vblank: 225 imx_drm_crtc_vblank_put(ipu_crtc->imx_crtc); 226 227 return ret; 228} 229 230static const struct drm_crtc_funcs ipu_crtc_funcs = { 231 .set_config = drm_crtc_helper_set_config, 232 .destroy = drm_crtc_cleanup, 233 .page_flip = ipu_page_flip, 234}; 235 236static int ipu_crtc_mode_set(struct drm_crtc *crtc, 237 struct drm_display_mode *orig_mode, 238 struct drm_display_mode *mode, 239 int x, int y, 240 struct drm_framebuffer *old_fb) 241{ 242 struct drm_device *dev = crtc->dev; 243 struct drm_encoder *encoder; 244 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 245 struct ipu_di_signal_cfg sig_cfg = {}; 246 unsigned long encoder_types = 0; 247 int ret; 248 249 dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__, 250 mode->hdisplay); 251 dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__, 252 mode->vdisplay); 253 254 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) 255 if (encoder->crtc == crtc) 256 encoder_types |= BIT(encoder->encoder_type); 257 258 dev_dbg(ipu_crtc->dev, "%s: attached to encoder types 0x%lx\n", 259 __func__, encoder_types); 260 261 /* 262 * If we have DAC or LDB, then we need the IPU DI clock to be 263 * the same as the LDB DI clock. For TVDAC, derive the IPU DI 264 * clock from 27 MHz TVE_DI clock, but allow to divide it. 265 */ 266 if (encoder_types & (BIT(DRM_MODE_ENCODER_DAC) | 267 BIT(DRM_MODE_ENCODER_LVDS))) 268 sig_cfg.clkflags = IPU_DI_CLKMODE_SYNC | IPU_DI_CLKMODE_EXT; 269 else if (encoder_types & BIT(DRM_MODE_ENCODER_TVDAC)) 270 sig_cfg.clkflags = IPU_DI_CLKMODE_EXT; 271 else 272 sig_cfg.clkflags = 0; 273 274 sig_cfg.enable_pol = 1; 275 sig_cfg.clk_pol = 0; 276 sig_cfg.bus_format = ipu_crtc->bus_format; 277 sig_cfg.v_to_h_sync = 0; 278 sig_cfg.hsync_pin = ipu_crtc->di_hsync_pin; 279 sig_cfg.vsync_pin = ipu_crtc->di_vsync_pin; 280 281 drm_display_mode_to_videomode(mode, &sig_cfg.mode); 282 283 ret = ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di, 284 mode->flags & DRM_MODE_FLAG_INTERLACE, 285 ipu_crtc->bus_format, mode->hdisplay); 286 if (ret) { 287 dev_err(ipu_crtc->dev, 288 "initializing display controller failed with %d\n", 289 ret); 290 return ret; 291 } 292 293 ret = ipu_di_init_sync_panel(ipu_crtc->di, &sig_cfg); 294 if (ret) { 295 dev_err(ipu_crtc->dev, 296 "initializing panel failed with %d\n", ret); 297 return ret; 298 } 299 300 return ipu_plane_mode_set(ipu_crtc->plane[0], crtc, mode, 301 crtc->primary->fb, 302 0, 0, mode->hdisplay, mode->vdisplay, 303 x, y, mode->hdisplay, mode->vdisplay, 304 mode->flags & DRM_MODE_FLAG_INTERLACE); 305} 306 307static void ipu_crtc_handle_pageflip(struct ipu_crtc *ipu_crtc) 308{ 309 unsigned long flags; 310 struct drm_device *drm = ipu_crtc->base.dev; 311 struct ipu_flip_work *work = ipu_crtc->flip_work; 312 313 spin_lock_irqsave(&drm->event_lock, flags); 314 if (work->page_flip_event) 315 drm_crtc_send_vblank_event(&ipu_crtc->base, 316 work->page_flip_event); 317 imx_drm_crtc_vblank_put(ipu_crtc->imx_crtc); 318 spin_unlock_irqrestore(&drm->event_lock, flags); 319} 320 321static irqreturn_t ipu_irq_handler(int irq, void *dev_id) 322{ 323 struct ipu_crtc *ipu_crtc = dev_id; 324 325 imx_drm_handle_vblank(ipu_crtc->imx_crtc); 326 327 if (ipu_crtc->flip_state == IPU_FLIP_SUBMITTED) { 328 struct ipu_plane *plane = ipu_crtc->plane[0]; 329 330 ipu_plane_set_base(plane, ipu_crtc->base.primary->fb, 331 plane->x, plane->y); 332 ipu_crtc_handle_pageflip(ipu_crtc); 333 queue_work(ipu_crtc->flip_queue, 334 &ipu_crtc->flip_work->unref_work); 335 ipu_crtc->flip_state = IPU_FLIP_NONE; 336 } 337 338 return IRQ_HANDLED; 339} 340 341static bool ipu_crtc_mode_fixup(struct drm_crtc *crtc, 342 const struct drm_display_mode *mode, 343 struct drm_display_mode *adjusted_mode) 344{ 345 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 346 struct videomode vm; 347 int ret; 348 349 drm_display_mode_to_videomode(adjusted_mode, &vm); 350 351 ret = ipu_di_adjust_videomode(ipu_crtc->di, &vm); 352 if (ret) 353 return false; 354 355 drm_display_mode_from_videomode(&vm, adjusted_mode); 356 357 return true; 358} 359 360static void ipu_crtc_prepare(struct drm_crtc *crtc) 361{ 362 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 363 364 ipu_fb_disable(ipu_crtc); 365} 366 367static void ipu_crtc_commit(struct drm_crtc *crtc) 368{ 369 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 370 371 ipu_fb_enable(ipu_crtc); 372} 373 374static const struct drm_crtc_helper_funcs ipu_helper_funcs = { 375 .dpms = ipu_crtc_dpms, 376 .mode_fixup = ipu_crtc_mode_fixup, 377 .mode_set = ipu_crtc_mode_set, 378 .prepare = ipu_crtc_prepare, 379 .commit = ipu_crtc_commit, 380}; 381 382static int ipu_enable_vblank(struct drm_crtc *crtc) 383{ 384 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 385 386 enable_irq(ipu_crtc->irq); 387 388 return 0; 389} 390 391static void ipu_disable_vblank(struct drm_crtc *crtc) 392{ 393 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 394 395 disable_irq_nosync(ipu_crtc->irq); 396} 397 398static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, 399 u32 bus_format, int hsync_pin, int vsync_pin) 400{ 401 struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); 402 403 ipu_crtc->bus_format = bus_format; 404 ipu_crtc->di_hsync_pin = hsync_pin; 405 ipu_crtc->di_vsync_pin = vsync_pin; 406 407 return 0; 408} 409 410static const struct imx_drm_crtc_helper_funcs ipu_crtc_helper_funcs = { 411 .enable_vblank = ipu_enable_vblank, 412 .disable_vblank = ipu_disable_vblank, 413 .set_interface_pix_fmt = ipu_set_interface_pix_fmt, 414 .crtc_funcs = &ipu_crtc_funcs, 415 .crtc_helper_funcs = &ipu_helper_funcs, 416}; 417 418static void ipu_put_resources(struct ipu_crtc *ipu_crtc) 419{ 420 if (!IS_ERR_OR_NULL(ipu_crtc->dc)) 421 ipu_dc_put(ipu_crtc->dc); 422 if (!IS_ERR_OR_NULL(ipu_crtc->di)) 423 ipu_di_put(ipu_crtc->di); 424} 425 426static int ipu_get_resources(struct ipu_crtc *ipu_crtc, 427 struct ipu_client_platformdata *pdata) 428{ 429 struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); 430 int ret; 431 432 ipu_crtc->dc = ipu_dc_get(ipu, pdata->dc); 433 if (IS_ERR(ipu_crtc->dc)) { 434 ret = PTR_ERR(ipu_crtc->dc); 435 goto err_out; 436 } 437 438 ipu_crtc->di = ipu_di_get(ipu, pdata->di); 439 if (IS_ERR(ipu_crtc->di)) { 440 ret = PTR_ERR(ipu_crtc->di); 441 goto err_out; 442 } 443 444 return 0; 445err_out: 446 ipu_put_resources(ipu_crtc); 447 448 return ret; 449} 450 451static int ipu_crtc_init(struct ipu_crtc *ipu_crtc, 452 struct ipu_client_platformdata *pdata, struct drm_device *drm) 453{ 454 struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); 455 int dp = -EINVAL; 456 int ret; 457 458 ret = ipu_get_resources(ipu_crtc, pdata); 459 if (ret) { 460 dev_err(ipu_crtc->dev, "getting resources failed with %d.\n", 461 ret); 462 return ret; 463 } 464 465 if (pdata->dp >= 0) 466 dp = IPU_DP_FLOW_SYNC_BG; 467 ipu_crtc->plane[0] = ipu_plane_init(drm, ipu, pdata->dma[0], dp, 0, 468 DRM_PLANE_TYPE_PRIMARY); 469 if (IS_ERR(ipu_crtc->plane[0])) { 470 ret = PTR_ERR(ipu_crtc->plane[0]); 471 goto err_put_resources; 472 } 473 474 ret = imx_drm_add_crtc(drm, &ipu_crtc->base, &ipu_crtc->imx_crtc, 475 &ipu_crtc->plane[0]->base, &ipu_crtc_helper_funcs, 476 pdata->of_node); 477 if (ret) { 478 dev_err(ipu_crtc->dev, "adding crtc failed with %d.\n", ret); 479 goto err_put_resources; 480 } 481 482 ret = ipu_plane_get_resources(ipu_crtc->plane[0]); 483 if (ret) { 484 dev_err(ipu_crtc->dev, "getting plane 0 resources failed with %d.\n", 485 ret); 486 goto err_remove_crtc; 487 } 488 489 /* If this crtc is using the DP, add an overlay plane */ 490 if (pdata->dp >= 0 && pdata->dma[1] > 0) { 491 ipu_crtc->plane[1] = ipu_plane_init(drm, ipu, pdata->dma[1], 492 IPU_DP_FLOW_SYNC_FG, 493 drm_crtc_mask(&ipu_crtc->base), 494 DRM_PLANE_TYPE_OVERLAY); 495 if (IS_ERR(ipu_crtc->plane[1])) 496 ipu_crtc->plane[1] = NULL; 497 } 498 499 ipu_crtc->irq = ipu_plane_irq(ipu_crtc->plane[0]); 500 ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0, 501 "imx_drm", ipu_crtc); 502 if (ret < 0) { 503 dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret); 504 goto err_put_plane_res; 505 } 506 /* Only enable IRQ when we actually need it to trigger work. */ 507 disable_irq(ipu_crtc->irq); 508 509 ipu_crtc->flip_queue = create_singlethread_workqueue("ipu-crtc-flip"); 510 511 return 0; 512 513err_put_plane_res: 514 ipu_plane_put_resources(ipu_crtc->plane[0]); 515err_remove_crtc: 516 imx_drm_remove_crtc(ipu_crtc->imx_crtc); 517err_put_resources: 518 ipu_put_resources(ipu_crtc); 519 520 return ret; 521} 522 523static int ipu_drm_bind(struct device *dev, struct device *master, void *data) 524{ 525 struct ipu_client_platformdata *pdata = dev->platform_data; 526 struct drm_device *drm = data; 527 struct ipu_crtc *ipu_crtc; 528 int ret; 529 530 ipu_crtc = devm_kzalloc(dev, sizeof(*ipu_crtc), GFP_KERNEL); 531 if (!ipu_crtc) 532 return -ENOMEM; 533 534 ipu_crtc->dev = dev; 535 536 ret = ipu_crtc_init(ipu_crtc, pdata, drm); 537 if (ret) 538 return ret; 539 540 dev_set_drvdata(dev, ipu_crtc); 541 542 return 0; 543} 544 545static void ipu_drm_unbind(struct device *dev, struct device *master, 546 void *data) 547{ 548 struct ipu_crtc *ipu_crtc = dev_get_drvdata(dev); 549 550 imx_drm_remove_crtc(ipu_crtc->imx_crtc); 551 552 destroy_workqueue(ipu_crtc->flip_queue); 553 ipu_plane_put_resources(ipu_crtc->plane[0]); 554 ipu_put_resources(ipu_crtc); 555} 556 557static const struct component_ops ipu_crtc_ops = { 558 .bind = ipu_drm_bind, 559 .unbind = ipu_drm_unbind, 560}; 561 562static int ipu_drm_probe(struct platform_device *pdev) 563{ 564 struct device *dev = &pdev->dev; 565 int ret; 566 567 if (!dev->platform_data) 568 return -EINVAL; 569 570 ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32)); 571 if (ret) 572 return ret; 573 574 return component_add(dev, &ipu_crtc_ops); 575} 576 577static int ipu_drm_remove(struct platform_device *pdev) 578{ 579 component_del(&pdev->dev, &ipu_crtc_ops); 580 return 0; 581} 582 583static struct platform_driver ipu_drm_driver = { 584 .driver = { 585 .name = "imx-ipuv3-crtc", 586 }, 587 .probe = ipu_drm_probe, 588 .remove = ipu_drm_remove, 589}; 590module_platform_driver(ipu_drm_driver); 591 592MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); 593MODULE_DESCRIPTION(DRIVER_DESC); 594MODULE_LICENSE("GPL"); 595MODULE_ALIAS("platform:imx-ipuv3-crtc");