1 /* exynos_drm_crtc.c 2 * 3 * Copyright (c) 2011 Samsung Electronics Co., Ltd. 4 * Authors: 5 * Inki Dae <inki.dae@samsung.com> 6 * Joonyoung Shim <jy0922.shim@samsung.com> 7 * Seung-Woo Kim <sw0312.kim@samsung.com> 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the 11 * Free Software Foundation; either version 2 of the License, or (at your 12 * option) any later version. 13 */ 14 15 #include <drm/drmP.h> 16 #include <drm/drm_crtc_helper.h> 17 18 #include "exynos_drm_crtc.h" 19 #include "exynos_drm_drv.h" 20 #include "exynos_drm_encoder.h" 21 #include "exynos_drm_plane.h" 22 23 #define to_exynos_crtc(x) container_of(x, struct exynos_drm_crtc,\ 24 drm_crtc) 25 26 enum exynos_crtc_mode { 27 CRTC_MODE_NORMAL, /* normal mode */ 28 CRTC_MODE_BLANK, /* The private plane of crtc is blank */ 29 }; 30 31 /* 32 * Exynos specific crtc structure. 33 * 34 * @drm_crtc: crtc object. 35 * @manager: the manager associated with this crtc 36 * @pipe: a crtc index created at load() with a new crtc object creation 37 * and the crtc object would be set to private->crtc array 38 * to get a crtc object corresponding to this pipe from private->crtc 39 * array when irq interrupt occurred. the reason of using this pipe is that 40 * drm framework doesn't support multiple irq yet. 41 * we can refer to the crtc to current hardware interrupt occurred through 42 * this pipe value. 43 * @dpms: store the crtc dpms value 44 * @mode: store the crtc mode value 45 */ 46 struct exynos_drm_crtc { 47 struct drm_crtc drm_crtc; 48 struct exynos_drm_manager *manager; 49 unsigned int pipe; 50 unsigned int dpms; 51 enum exynos_crtc_mode mode; 52 wait_queue_head_t pending_flip_queue; 53 atomic_t pending_flip; 54 }; 55 56 static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) 57 { 58 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 59 struct exynos_drm_manager *manager = exynos_crtc->manager; 60 61 DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode); 62 63 if (exynos_crtc->dpms == mode) { 64 DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n"); 65 return; 66 } 67 68 if (mode > DRM_MODE_DPMS_ON) { 69 /* wait for the completion of page flip. */ 70 if (!wait_event_timeout(exynos_crtc->pending_flip_queue, 71 !atomic_read(&exynos_crtc->pending_flip), 72 HZ/20)) 73 atomic_set(&exynos_crtc->pending_flip, 0); 74 drm_crtc_vblank_off(crtc); 75 } 76 77 if (manager->ops->dpms) 78 manager->ops->dpms(manager, mode); 79 80 exynos_crtc->dpms = mode; 81 82 if (mode == DRM_MODE_DPMS_ON) 83 drm_crtc_vblank_on(crtc); 84 } 85 86 static void exynos_drm_crtc_prepare(struct drm_crtc *crtc) 87 { 88 /* drm framework doesn't check NULL. */ 89 } 90 91 static void exynos_drm_crtc_commit(struct drm_crtc *crtc) 92 { 93 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 94 struct exynos_drm_manager *manager = exynos_crtc->manager; 95 96 exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON); 97 98 exynos_plane_commit(crtc->primary); 99 100 if (manager->ops->commit) 101 manager->ops->commit(manager); 102 103 exynos_plane_dpms(crtc->primary, DRM_MODE_DPMS_ON); 104 } 105 106 static bool 107 exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc, 108 const struct drm_display_mode *mode, 109 struct drm_display_mode *adjusted_mode) 110 { 111 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 112 struct exynos_drm_manager *manager = exynos_crtc->manager; 113 114 if (manager->ops->mode_fixup) 115 return manager->ops->mode_fixup(manager, mode, adjusted_mode); 116 117 return true; 118 } 119 120 static int 121 exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, 122 struct drm_display_mode *adjusted_mode, int x, int y, 123 struct drm_framebuffer *old_fb) 124 { 125 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 126 struct exynos_drm_manager *manager = exynos_crtc->manager; 127 struct drm_framebuffer *fb = crtc->primary->fb; 128 unsigned int crtc_w; 129 unsigned int crtc_h; 130 131 /* 132 * copy the mode data adjusted by mode_fixup() into crtc->mode 133 * so that hardware can be seet to proper mode. 134 */ 135 memcpy(&crtc->mode, adjusted_mode, sizeof(*adjusted_mode)); 136 137 crtc_w = fb->width - x; 138 crtc_h = fb->height - y; 139 140 if (manager->ops->mode_set) 141 manager->ops->mode_set(manager, &crtc->mode); 142 143 return exynos_plane_mode_set(crtc->primary, crtc, fb, 0, 0, 144 crtc_w, crtc_h, x, y, crtc_w, crtc_h); 145 } 146 147 static int exynos_drm_crtc_mode_set_commit(struct drm_crtc *crtc, int x, int y, 148 struct drm_framebuffer *old_fb) 149 { 150 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 151 struct drm_framebuffer *fb = crtc->primary->fb; 152 unsigned int crtc_w; 153 unsigned int crtc_h; 154 int ret; 155 156 /* when framebuffer changing is requested, crtc's dpms should be on */ 157 if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) { 158 DRM_ERROR("failed framebuffer changing request.\n"); 159 return -EPERM; 160 } 161 162 crtc_w = fb->width - x; 163 crtc_h = fb->height - y; 164 165 ret = exynos_plane_mode_set(crtc->primary, crtc, fb, 0, 0, 166 crtc_w, crtc_h, x, y, crtc_w, crtc_h); 167 if (ret) 168 return ret; 169 170 exynos_drm_crtc_commit(crtc); 171 172 return 0; 173 } 174 175 static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, 176 struct drm_framebuffer *old_fb) 177 { 178 return exynos_drm_crtc_mode_set_commit(crtc, x, y, old_fb); 179 } 180 181 static void exynos_drm_crtc_disable(struct drm_crtc *crtc) 182 { 183 struct drm_plane *plane; 184 int ret; 185 186 exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); 187 188 drm_for_each_legacy_plane(plane, &crtc->dev->mode_config.plane_list) { 189 if (plane->crtc != crtc) 190 continue; 191 192 ret = plane->funcs->disable_plane(plane); 193 if (ret) 194 DRM_ERROR("Failed to disable plane %d\n", ret); 195 } 196 } 197 198 static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = { 199 .dpms = exynos_drm_crtc_dpms, 200 .prepare = exynos_drm_crtc_prepare, 201 .commit = exynos_drm_crtc_commit, 202 .mode_fixup = exynos_drm_crtc_mode_fixup, 203 .mode_set = exynos_drm_crtc_mode_set, 204 .mode_set_base = exynos_drm_crtc_mode_set_base, 205 .disable = exynos_drm_crtc_disable, 206 }; 207 208 static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc, 209 struct drm_framebuffer *fb, 210 struct drm_pending_vblank_event *event, 211 uint32_t page_flip_flags) 212 { 213 struct drm_device *dev = crtc->dev; 214 struct exynos_drm_private *dev_priv = dev->dev_private; 215 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 216 struct drm_framebuffer *old_fb = crtc->primary->fb; 217 int ret = -EINVAL; 218 219 /* when the page flip is requested, crtc's dpms should be on */ 220 if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) { 221 DRM_ERROR("failed page flip request.\n"); 222 return -EINVAL; 223 } 224 225 mutex_lock(&dev->struct_mutex); 226 227 if (event) { 228 /* 229 * the pipe from user always is 0 so we can set pipe number 230 * of current owner to event. 231 */ 232 event->pipe = exynos_crtc->pipe; 233 234 ret = drm_vblank_get(dev, exynos_crtc->pipe); 235 if (ret) { 236 DRM_DEBUG("failed to acquire vblank counter\n"); 237 238 goto out; 239 } 240 241 spin_lock_irq(&dev->event_lock); 242 list_add_tail(&event->base.link, 243 &dev_priv->pageflip_event_list); 244 atomic_set(&exynos_crtc->pending_flip, 1); 245 spin_unlock_irq(&dev->event_lock); 246 247 crtc->primary->fb = fb; 248 ret = exynos_drm_crtc_mode_set_commit(crtc, crtc->x, crtc->y, 249 NULL); 250 if (ret) { 251 crtc->primary->fb = old_fb; 252 253 spin_lock_irq(&dev->event_lock); 254 drm_vblank_put(dev, exynos_crtc->pipe); 255 list_del(&event->base.link); 256 atomic_set(&exynos_crtc->pending_flip, 0); 257 spin_unlock_irq(&dev->event_lock); 258 259 goto out; 260 } 261 } 262 out: 263 mutex_unlock(&dev->struct_mutex); 264 return ret; 265 } 266 267 static void exynos_drm_crtc_destroy(struct drm_crtc *crtc) 268 { 269 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 270 struct exynos_drm_private *private = crtc->dev->dev_private; 271 272 private->crtc[exynos_crtc->pipe] = NULL; 273 274 drm_crtc_cleanup(crtc); 275 kfree(exynos_crtc); 276 } 277 278 static int exynos_drm_crtc_set_property(struct drm_crtc *crtc, 279 struct drm_property *property, 280 uint64_t val) 281 { 282 struct drm_device *dev = crtc->dev; 283 struct exynos_drm_private *dev_priv = dev->dev_private; 284 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 285 286 if (property == dev_priv->crtc_mode_property) { 287 enum exynos_crtc_mode mode = val; 288 289 if (mode == exynos_crtc->mode) 290 return 0; 291 292 exynos_crtc->mode = mode; 293 294 switch (mode) { 295 case CRTC_MODE_NORMAL: 296 exynos_drm_crtc_commit(crtc); 297 break; 298 case CRTC_MODE_BLANK: 299 exynos_plane_dpms(crtc->primary, DRM_MODE_DPMS_OFF); 300 break; 301 default: 302 break; 303 } 304 305 return 0; 306 } 307 308 return -EINVAL; 309 } 310 311 static struct drm_crtc_funcs exynos_crtc_funcs = { 312 .set_config = drm_crtc_helper_set_config, 313 .page_flip = exynos_drm_crtc_page_flip, 314 .destroy = exynos_drm_crtc_destroy, 315 .set_property = exynos_drm_crtc_set_property, 316 }; 317 318 static const struct drm_prop_enum_list mode_names[] = { 319 { CRTC_MODE_NORMAL, "normal" }, 320 { CRTC_MODE_BLANK, "blank" }, 321 }; 322 323 static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc) 324 { 325 struct drm_device *dev = crtc->dev; 326 struct exynos_drm_private *dev_priv = dev->dev_private; 327 struct drm_property *prop; 328 329 prop = dev_priv->crtc_mode_property; 330 if (!prop) { 331 prop = drm_property_create_enum(dev, 0, "mode", mode_names, 332 ARRAY_SIZE(mode_names)); 333 if (!prop) 334 return; 335 336 dev_priv->crtc_mode_property = prop; 337 } 338 339 drm_object_attach_property(&crtc->base, prop, 0); 340 } 341 342 int exynos_drm_crtc_create(struct exynos_drm_manager *manager) 343 { 344 struct exynos_drm_crtc *exynos_crtc; 345 struct drm_plane *plane; 346 struct exynos_drm_private *private = manager->drm_dev->dev_private; 347 struct drm_crtc *crtc; 348 int ret; 349 350 exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL); 351 if (!exynos_crtc) 352 return -ENOMEM; 353 354 init_waitqueue_head(&exynos_crtc->pending_flip_queue); 355 atomic_set(&exynos_crtc->pending_flip, 0); 356 357 exynos_crtc->dpms = DRM_MODE_DPMS_OFF; 358 exynos_crtc->manager = manager; 359 exynos_crtc->pipe = manager->pipe; 360 plane = exynos_plane_init(manager->drm_dev, 1 << manager->pipe, 361 DRM_PLANE_TYPE_PRIMARY); 362 if (IS_ERR(plane)) { 363 ret = PTR_ERR(plane); 364 goto err_plane; 365 } 366 367 manager->crtc = &exynos_crtc->drm_crtc; 368 crtc = &exynos_crtc->drm_crtc; 369 370 private->crtc[manager->pipe] = crtc; 371 372 ret = drm_crtc_init_with_planes(manager->drm_dev, crtc, plane, NULL, 373 &exynos_crtc_funcs); 374 if (ret < 0) 375 goto err_crtc; 376 377 drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs); 378 379 exynos_drm_crtc_attach_mode_property(crtc); 380 381 return 0; 382 383 err_crtc: 384 plane->funcs->destroy(plane); 385 err_plane: 386 kfree(exynos_crtc); 387 return ret; 388 } 389 390 int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe) 391 { 392 struct exynos_drm_private *private = dev->dev_private; 393 struct exynos_drm_crtc *exynos_crtc = 394 to_exynos_crtc(private->crtc[pipe]); 395 struct exynos_drm_manager *manager = exynos_crtc->manager; 396 397 if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) 398 return -EPERM; 399 400 if (manager->ops->enable_vblank) 401 manager->ops->enable_vblank(manager); 402 403 return 0; 404 } 405 406 void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe) 407 { 408 struct exynos_drm_private *private = dev->dev_private; 409 struct exynos_drm_crtc *exynos_crtc = 410 to_exynos_crtc(private->crtc[pipe]); 411 struct exynos_drm_manager *manager = exynos_crtc->manager; 412 413 if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) 414 return; 415 416 if (manager->ops->disable_vblank) 417 manager->ops->disable_vblank(manager); 418 } 419 420 void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe) 421 { 422 struct exynos_drm_private *dev_priv = dev->dev_private; 423 struct drm_pending_vblank_event *e, *t; 424 struct drm_crtc *drm_crtc = dev_priv->crtc[pipe]; 425 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(drm_crtc); 426 unsigned long flags; 427 428 spin_lock_irqsave(&dev->event_lock, flags); 429 430 list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list, 431 base.link) { 432 /* if event's pipe isn't same as crtc then ignore it. */ 433 if (pipe != e->pipe) 434 continue; 435 436 list_del(&e->base.link); 437 drm_send_vblank_event(dev, -1, e); 438 drm_vblank_put(dev, pipe); 439 atomic_set(&exynos_crtc->pending_flip, 0); 440 wake_up(&exynos_crtc->pending_flip_queue); 441 } 442 443 spin_unlock_irqrestore(&dev->event_lock, flags); 444 } 445 446 void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc, 447 struct exynos_drm_overlay *overlay) 448 { 449 struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager; 450 451 if (manager->ops->win_mode_set) 452 manager->ops->win_mode_set(manager, overlay); 453 } 454 455 void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos) 456 { 457 struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager; 458 459 if (manager->ops->win_commit) 460 manager->ops->win_commit(manager, zpos); 461 } 462 463 void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos) 464 { 465 struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager; 466 467 if (manager->ops->win_enable) 468 manager->ops->win_enable(manager, zpos); 469 } 470 471 void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos) 472 { 473 struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager; 474 475 if (manager->ops->win_disable) 476 manager->ops->win_disable(manager, zpos); 477 } 478 479 void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb) 480 { 481 struct exynos_drm_manager *manager; 482 struct drm_device *dev = fb->dev; 483 struct drm_crtc *crtc; 484 485 /* 486 * make sure that overlay data are updated to real hardware 487 * for all encoders. 488 */ 489 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 490 manager = to_exynos_crtc(crtc)->manager; 491 492 /* 493 * wait for vblank interrupt 494 * - this makes sure that overlay data are updated to 495 * real hardware. 496 */ 497 if (manager->ops->wait_for_vblank) 498 manager->ops->wait_for_vblank(manager); 499 } 500 } 501 502 int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev, 503 unsigned int out_type) 504 { 505 struct drm_crtc *crtc; 506 507 list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head) { 508 struct exynos_drm_crtc *exynos_crtc; 509 510 exynos_crtc = to_exynos_crtc(crtc); 511 if (exynos_crtc->manager->type == out_type) 512 return exynos_crtc->manager->pipe; 513 } 514 515 return -EPERM; 516 } 517 518 void exynos_drm_crtc_te_handler(struct drm_crtc *crtc) 519 { 520 struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager; 521 522 if (manager->ops->te_handler) 523 manager->ops->te_handler(manager); 524 } 525