diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_display.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_display.c | 211 |
1 files changed, 112 insertions, 99 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 8fc362aa6a1a..bf25061c8ac4 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -285,7 +285,6 @@ static void radeon_unpin_work_func(struct work_struct *__work) | |||
285 | void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) | 285 | void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) |
286 | { | 286 | { |
287 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; | 287 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; |
288 | struct radeon_flip_work *work; | ||
289 | unsigned long flags; | 288 | unsigned long flags; |
290 | u32 update_pending; | 289 | u32 update_pending; |
291 | int vpos, hpos; | 290 | int vpos, hpos; |
@@ -295,8 +294,11 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) | |||
295 | return; | 294 | return; |
296 | 295 | ||
297 | spin_lock_irqsave(&rdev->ddev->event_lock, flags); | 296 | spin_lock_irqsave(&rdev->ddev->event_lock, flags); |
298 | work = radeon_crtc->flip_work; | 297 | if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) { |
299 | if (work == NULL) { | 298 | DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != " |
299 | "RADEON_FLIP_SUBMITTED(%d)\n", | ||
300 | radeon_crtc->flip_status, | ||
301 | RADEON_FLIP_SUBMITTED); | ||
300 | spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); | 302 | spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); |
301 | return; | 303 | return; |
302 | } | 304 | } |
@@ -344,12 +346,17 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) | |||
344 | 346 | ||
345 | spin_lock_irqsave(&rdev->ddev->event_lock, flags); | 347 | spin_lock_irqsave(&rdev->ddev->event_lock, flags); |
346 | work = radeon_crtc->flip_work; | 348 | work = radeon_crtc->flip_work; |
347 | if (work == NULL) { | 349 | if (radeon_crtc->flip_status != RADEON_FLIP_SUBMITTED) { |
350 | DRM_DEBUG_DRIVER("radeon_crtc->flip_status = %d != " | ||
351 | "RADEON_FLIP_SUBMITTED(%d)\n", | ||
352 | radeon_crtc->flip_status, | ||
353 | RADEON_FLIP_SUBMITTED); | ||
348 | spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); | 354 | spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); |
349 | return; | 355 | return; |
350 | } | 356 | } |
351 | 357 | ||
352 | /* Pageflip completed. Clean up. */ | 358 | /* Pageflip completed. Clean up. */ |
359 | radeon_crtc->flip_status = RADEON_FLIP_NONE; | ||
353 | radeon_crtc->flip_work = NULL; | 360 | radeon_crtc->flip_work = NULL; |
354 | 361 | ||
355 | /* wakeup userspace */ | 362 | /* wakeup userspace */ |
@@ -359,7 +366,6 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) | |||
359 | spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); | 366 | spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); |
360 | 367 | ||
361 | drm_vblank_put(rdev->ddev, radeon_crtc->crtc_id); | 368 | drm_vblank_put(rdev->ddev, radeon_crtc->crtc_id); |
362 | radeon_fence_unref(&work->fence); | ||
363 | radeon_irq_kms_pflip_irq_put(rdev, work->crtc_id); | 369 | radeon_irq_kms_pflip_irq_put(rdev, work->crtc_id); |
364 | queue_work(radeon_crtc->flip_queue, &work->unpin_work); | 370 | queue_work(radeon_crtc->flip_queue, &work->unpin_work); |
365 | } | 371 | } |
@@ -379,51 +385,108 @@ static void radeon_flip_work_func(struct work_struct *__work) | |||
379 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[work->crtc_id]; | 385 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[work->crtc_id]; |
380 | 386 | ||
381 | struct drm_crtc *crtc = &radeon_crtc->base; | 387 | struct drm_crtc *crtc = &radeon_crtc->base; |
382 | struct drm_framebuffer *fb = work->fb; | ||
383 | |||
384 | uint32_t tiling_flags, pitch_pixels; | ||
385 | uint64_t base; | ||
386 | |||
387 | unsigned long flags; | 388 | unsigned long flags; |
388 | int r; | 389 | int r; |
389 | 390 | ||
390 | down_read(&rdev->exclusive_lock); | 391 | down_read(&rdev->exclusive_lock); |
391 | while (work->fence) { | 392 | if (work->fence) { |
392 | r = radeon_fence_wait(work->fence, false); | 393 | r = radeon_fence_wait(work->fence, false); |
393 | if (r == -EDEADLK) { | 394 | if (r == -EDEADLK) { |
394 | up_read(&rdev->exclusive_lock); | 395 | up_read(&rdev->exclusive_lock); |
395 | r = radeon_gpu_reset(rdev); | 396 | r = radeon_gpu_reset(rdev); |
396 | down_read(&rdev->exclusive_lock); | 397 | down_read(&rdev->exclusive_lock); |
397 | } | 398 | } |
399 | if (r) | ||
400 | DRM_ERROR("failed to wait on page flip fence (%d)!\n", r); | ||
398 | 401 | ||
399 | if (r) { | 402 | /* We continue with the page flip even if we failed to wait on |
400 | DRM_ERROR("failed to wait on page flip fence (%d)!\n", | 403 | * the fence, otherwise the DRM core and userspace will be |
401 | r); | 404 | * confused about which BO the CRTC is scanning out |
402 | goto cleanup; | 405 | */ |
403 | } else | 406 | |
404 | radeon_fence_unref(&work->fence); | 407 | radeon_fence_unref(&work->fence); |
405 | } | 408 | } |
406 | 409 | ||
410 | /* We borrow the event spin lock for protecting flip_status */ | ||
411 | spin_lock_irqsave(&crtc->dev->event_lock, flags); | ||
412 | |||
413 | /* set the proper interrupt */ | ||
414 | radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id); | ||
415 | |||
416 | /* do the flip (mmio) */ | ||
417 | radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base); | ||
418 | |||
419 | radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED; | ||
420 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); | ||
421 | up_read(&rdev->exclusive_lock); | ||
422 | } | ||
423 | |||
424 | static int radeon_crtc_page_flip(struct drm_crtc *crtc, | ||
425 | struct drm_framebuffer *fb, | ||
426 | struct drm_pending_vblank_event *event, | ||
427 | uint32_t page_flip_flags) | ||
428 | { | ||
429 | struct drm_device *dev = crtc->dev; | ||
430 | struct radeon_device *rdev = dev->dev_private; | ||
431 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
432 | struct radeon_framebuffer *old_radeon_fb; | ||
433 | struct radeon_framebuffer *new_radeon_fb; | ||
434 | struct drm_gem_object *obj; | ||
435 | struct radeon_flip_work *work; | ||
436 | struct radeon_bo *new_rbo; | ||
437 | uint32_t tiling_flags, pitch_pixels; | ||
438 | uint64_t base; | ||
439 | unsigned long flags; | ||
440 | int r; | ||
441 | |||
442 | work = kzalloc(sizeof *work, GFP_KERNEL); | ||
443 | if (work == NULL) | ||
444 | return -ENOMEM; | ||
445 | |||
446 | INIT_WORK(&work->flip_work, radeon_flip_work_func); | ||
447 | INIT_WORK(&work->unpin_work, radeon_unpin_work_func); | ||
448 | |||
449 | work->rdev = rdev; | ||
450 | work->crtc_id = radeon_crtc->crtc_id; | ||
451 | work->event = event; | ||
452 | |||
453 | /* schedule unpin of the old buffer */ | ||
454 | old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb); | ||
455 | obj = old_radeon_fb->obj; | ||
456 | |||
457 | /* take a reference to the old object */ | ||
458 | drm_gem_object_reference(obj); | ||
459 | work->old_rbo = gem_to_radeon_bo(obj); | ||
460 | |||
461 | new_radeon_fb = to_radeon_framebuffer(fb); | ||
462 | obj = new_radeon_fb->obj; | ||
463 | new_rbo = gem_to_radeon_bo(obj); | ||
464 | |||
465 | spin_lock(&new_rbo->tbo.bdev->fence_lock); | ||
466 | if (new_rbo->tbo.sync_obj) | ||
467 | work->fence = radeon_fence_ref(new_rbo->tbo.sync_obj); | ||
468 | spin_unlock(&new_rbo->tbo.bdev->fence_lock); | ||
469 | |||
407 | /* pin the new buffer */ | 470 | /* pin the new buffer */ |
408 | DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n", | 471 | DRM_DEBUG_DRIVER("flip-ioctl() cur_rbo = %p, new_rbo = %p\n", |
409 | work->old_rbo, work->new_rbo); | 472 | work->old_rbo, new_rbo); |
410 | 473 | ||
411 | r = radeon_bo_reserve(work->new_rbo, false); | 474 | r = radeon_bo_reserve(new_rbo, false); |
412 | if (unlikely(r != 0)) { | 475 | if (unlikely(r != 0)) { |
413 | DRM_ERROR("failed to reserve new rbo buffer before flip\n"); | 476 | DRM_ERROR("failed to reserve new rbo buffer before flip\n"); |
414 | goto cleanup; | 477 | goto cleanup; |
415 | } | 478 | } |
416 | /* Only 27 bit offset for legacy CRTC */ | 479 | /* Only 27 bit offset for legacy CRTC */ |
417 | r = radeon_bo_pin_restricted(work->new_rbo, RADEON_GEM_DOMAIN_VRAM, | 480 | r = radeon_bo_pin_restricted(new_rbo, RADEON_GEM_DOMAIN_VRAM, |
418 | ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, &base); | 481 | ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, &base); |
419 | if (unlikely(r != 0)) { | 482 | if (unlikely(r != 0)) { |
420 | radeon_bo_unreserve(work->new_rbo); | 483 | radeon_bo_unreserve(new_rbo); |
421 | r = -EINVAL; | 484 | r = -EINVAL; |
422 | DRM_ERROR("failed to pin new rbo buffer before flip\n"); | 485 | DRM_ERROR("failed to pin new rbo buffer before flip\n"); |
423 | goto cleanup; | 486 | goto cleanup; |
424 | } | 487 | } |
425 | radeon_bo_get_tiling_flags(work->new_rbo, &tiling_flags, NULL); | 488 | radeon_bo_get_tiling_flags(new_rbo, &tiling_flags, NULL); |
426 | radeon_bo_unreserve(work->new_rbo); | 489 | radeon_bo_unreserve(new_rbo); |
427 | 490 | ||
428 | if (!ASIC_IS_AVIVO(rdev)) { | 491 | if (!ASIC_IS_AVIVO(rdev)) { |
429 | /* crtc offset is from display base addr not FB location */ | 492 | /* crtc offset is from display base addr not FB location */ |
@@ -460,6 +523,7 @@ static void radeon_flip_work_func(struct work_struct *__work) | |||
460 | } | 523 | } |
461 | base &= ~7; | 524 | base &= ~7; |
462 | } | 525 | } |
526 | work->base = base; | ||
463 | 527 | ||
464 | r = drm_vblank_get(crtc->dev, radeon_crtc->crtc_id); | 528 | r = drm_vblank_get(crtc->dev, radeon_crtc->crtc_id); |
465 | if (r) { | 529 | if (r) { |
@@ -470,98 +534,42 @@ static void radeon_flip_work_func(struct work_struct *__work) | |||
470 | /* We borrow the event spin lock for protecting flip_work */ | 534 | /* We borrow the event spin lock for protecting flip_work */ |
471 | spin_lock_irqsave(&crtc->dev->event_lock, flags); | 535 | spin_lock_irqsave(&crtc->dev->event_lock, flags); |
472 | 536 | ||
473 | /* set the proper interrupt */ | 537 | if (radeon_crtc->flip_status != RADEON_FLIP_NONE) { |
474 | radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id); | 538 | DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); |
539 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); | ||
540 | r = -EBUSY; | ||
541 | goto vblank_cleanup; | ||
542 | } | ||
543 | radeon_crtc->flip_status = RADEON_FLIP_PENDING; | ||
544 | radeon_crtc->flip_work = work; | ||
475 | 545 | ||
476 | /* do the flip (mmio) */ | 546 | /* update crtc fb */ |
477 | radeon_page_flip(rdev, radeon_crtc->crtc_id, base); | 547 | crtc->primary->fb = fb; |
478 | 548 | ||
479 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); | 549 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); |
480 | up_read(&rdev->exclusive_lock); | ||
481 | 550 | ||
482 | return; | 551 | queue_work(radeon_crtc->flip_queue, &work->flip_work); |
552 | return 0; | ||
553 | |||
554 | vblank_cleanup: | ||
555 | drm_vblank_put(crtc->dev, radeon_crtc->crtc_id); | ||
483 | 556 | ||
484 | pflip_cleanup: | 557 | pflip_cleanup: |
485 | if (unlikely(radeon_bo_reserve(work->new_rbo, false) != 0)) { | 558 | if (unlikely(radeon_bo_reserve(new_rbo, false) != 0)) { |
486 | DRM_ERROR("failed to reserve new rbo in error path\n"); | 559 | DRM_ERROR("failed to reserve new rbo in error path\n"); |
487 | goto cleanup; | 560 | goto cleanup; |
488 | } | 561 | } |
489 | if (unlikely(radeon_bo_unpin(work->new_rbo) != 0)) { | 562 | if (unlikely(radeon_bo_unpin(new_rbo) != 0)) { |
490 | DRM_ERROR("failed to unpin new rbo in error path\n"); | 563 | DRM_ERROR("failed to unpin new rbo in error path\n"); |
491 | } | 564 | } |
492 | radeon_bo_unreserve(work->new_rbo); | 565 | radeon_bo_unreserve(new_rbo); |
493 | 566 | ||
494 | cleanup: | 567 | cleanup: |
495 | drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base); | 568 | drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base); |
496 | radeon_fence_unref(&work->fence); | 569 | radeon_fence_unref(&work->fence); |
497 | kfree(work); | 570 | kfree(work); |
498 | up_read(&rdev->exclusive_lock); | ||
499 | } | ||
500 | |||
501 | static int radeon_crtc_page_flip(struct drm_crtc *crtc, | ||
502 | struct drm_framebuffer *fb, | ||
503 | struct drm_pending_vblank_event *event, | ||
504 | uint32_t page_flip_flags) | ||
505 | { | ||
506 | struct drm_device *dev = crtc->dev; | ||
507 | struct radeon_device *rdev = dev->dev_private; | ||
508 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
509 | struct radeon_framebuffer *old_radeon_fb; | ||
510 | struct radeon_framebuffer *new_radeon_fb; | ||
511 | struct drm_gem_object *obj; | ||
512 | struct radeon_flip_work *work; | ||
513 | unsigned long flags; | ||
514 | |||
515 | work = kzalloc(sizeof *work, GFP_KERNEL); | ||
516 | if (work == NULL) | ||
517 | return -ENOMEM; | ||
518 | |||
519 | INIT_WORK(&work->flip_work, radeon_flip_work_func); | ||
520 | INIT_WORK(&work->unpin_work, radeon_unpin_work_func); | ||
521 | |||
522 | work->rdev = rdev; | ||
523 | work->crtc_id = radeon_crtc->crtc_id; | ||
524 | work->fb = fb; | ||
525 | work->event = event; | ||
526 | 571 | ||
527 | /* schedule unpin of the old buffer */ | 572 | return r; |
528 | old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb); | ||
529 | obj = old_radeon_fb->obj; | ||
530 | |||
531 | /* take a reference to the old object */ | ||
532 | drm_gem_object_reference(obj); | ||
533 | work->old_rbo = gem_to_radeon_bo(obj); | ||
534 | |||
535 | new_radeon_fb = to_radeon_framebuffer(fb); | ||
536 | obj = new_radeon_fb->obj; | ||
537 | work->new_rbo = gem_to_radeon_bo(obj); | ||
538 | |||
539 | spin_lock(&work->new_rbo->tbo.bdev->fence_lock); | ||
540 | if (work->new_rbo->tbo.sync_obj) | ||
541 | work->fence = radeon_fence_ref(work->new_rbo->tbo.sync_obj); | ||
542 | spin_unlock(&work->new_rbo->tbo.bdev->fence_lock); | ||
543 | |||
544 | /* We borrow the event spin lock for protecting flip_work */ | ||
545 | spin_lock_irqsave(&crtc->dev->event_lock, flags); | ||
546 | |||
547 | if (radeon_crtc->flip_work) { | ||
548 | DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); | ||
549 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); | ||
550 | drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base); | ||
551 | radeon_fence_unref(&work->fence); | ||
552 | kfree(work); | ||
553 | return -EBUSY; | ||
554 | } | ||
555 | radeon_crtc->flip_work = work; | ||
556 | |||
557 | /* update crtc fb */ | ||
558 | crtc->primary->fb = fb; | ||
559 | |||
560 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); | ||
561 | |||
562 | queue_work(radeon_crtc->flip_queue, &work->flip_work); | ||
563 | |||
564 | return 0; | ||
565 | } | 573 | } |
566 | 574 | ||
567 | static int | 575 | static int |
@@ -821,6 +829,10 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) | |||
821 | struct radeon_device *rdev = dev->dev_private; | 829 | struct radeon_device *rdev = dev->dev_private; |
822 | int ret = 0; | 830 | int ret = 0; |
823 | 831 | ||
832 | /* don't leak the edid if we already fetched it in detect() */ | ||
833 | if (radeon_connector->edid) | ||
834 | goto got_edid; | ||
835 | |||
824 | /* on hw with routers, select right port */ | 836 | /* on hw with routers, select right port */ |
825 | if (radeon_connector->router.ddc_valid) | 837 | if (radeon_connector->router.ddc_valid) |
826 | radeon_router_select_ddc_port(radeon_connector); | 838 | radeon_router_select_ddc_port(radeon_connector); |
@@ -859,6 +871,7 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) | |||
859 | radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev); | 871 | radeon_connector->edid = radeon_bios_get_hardcoded_edid(rdev); |
860 | } | 872 | } |
861 | if (radeon_connector->edid) { | 873 | if (radeon_connector->edid) { |
874 | got_edid: | ||
862 | drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid); | 875 | drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid); |
863 | ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid); | 876 | ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid); |
864 | drm_edid_to_eld(&radeon_connector->base, radeon_connector->edid); | 877 | drm_edid_to_eld(&radeon_connector->base, radeon_connector->edid); |