diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_display.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 127 |
1 files changed, 72 insertions, 55 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 38d47559f098..93f700ab1bfb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "amdgpu_i2c.h" | 29 | #include "amdgpu_i2c.h" |
30 | #include "atom.h" | 30 | #include "atom.h" |
31 | #include "amdgpu_connectors.h" | 31 | #include "amdgpu_connectors.h" |
32 | #include "amdgpu_display.h" | ||
32 | #include <asm/div64.h> | 33 | #include <asm/div64.h> |
33 | 34 | ||
34 | #include <linux/pm_runtime.h> | 35 | #include <linux/pm_runtime.h> |
@@ -36,7 +37,8 @@ | |||
36 | #include <drm/drm_edid.h> | 37 | #include <drm/drm_edid.h> |
37 | #include <drm/drm_fb_helper.h> | 38 | #include <drm/drm_fb_helper.h> |
38 | 39 | ||
39 | static void amdgpu_flip_callback(struct dma_fence *f, struct dma_fence_cb *cb) | 40 | static void amdgpu_display_flip_callback(struct dma_fence *f, |
41 | struct dma_fence_cb *cb) | ||
40 | { | 42 | { |
41 | struct amdgpu_flip_work *work = | 43 | struct amdgpu_flip_work *work = |
42 | container_of(cb, struct amdgpu_flip_work, cb); | 44 | container_of(cb, struct amdgpu_flip_work, cb); |
@@ -45,8 +47,8 @@ static void amdgpu_flip_callback(struct dma_fence *f, struct dma_fence_cb *cb) | |||
45 | schedule_work(&work->flip_work.work); | 47 | schedule_work(&work->flip_work.work); |
46 | } | 48 | } |
47 | 49 | ||
48 | static bool amdgpu_flip_handle_fence(struct amdgpu_flip_work *work, | 50 | static bool amdgpu_display_flip_handle_fence(struct amdgpu_flip_work *work, |
49 | struct dma_fence **f) | 51 | struct dma_fence **f) |
50 | { | 52 | { |
51 | struct dma_fence *fence= *f; | 53 | struct dma_fence *fence= *f; |
52 | 54 | ||
@@ -55,14 +57,15 @@ static bool amdgpu_flip_handle_fence(struct amdgpu_flip_work *work, | |||
55 | 57 | ||
56 | *f = NULL; | 58 | *f = NULL; |
57 | 59 | ||
58 | if (!dma_fence_add_callback(fence, &work->cb, amdgpu_flip_callback)) | 60 | if (!dma_fence_add_callback(fence, &work->cb, |
61 | amdgpu_display_flip_callback)) | ||
59 | return true; | 62 | return true; |
60 | 63 | ||
61 | dma_fence_put(fence); | 64 | dma_fence_put(fence); |
62 | return false; | 65 | return false; |
63 | } | 66 | } |
64 | 67 | ||
65 | static void amdgpu_flip_work_func(struct work_struct *__work) | 68 | static void amdgpu_display_flip_work_func(struct work_struct *__work) |
66 | { | 69 | { |
67 | struct delayed_work *delayed_work = | 70 | struct delayed_work *delayed_work = |
68 | container_of(__work, struct delayed_work, work); | 71 | container_of(__work, struct delayed_work, work); |
@@ -76,20 +79,20 @@ static void amdgpu_flip_work_func(struct work_struct *__work) | |||
76 | unsigned i; | 79 | unsigned i; |
77 | int vpos, hpos; | 80 | int vpos, hpos; |
78 | 81 | ||
79 | if (amdgpu_flip_handle_fence(work, &work->excl)) | 82 | if (amdgpu_display_flip_handle_fence(work, &work->excl)) |
80 | return; | 83 | return; |
81 | 84 | ||
82 | for (i = 0; i < work->shared_count; ++i) | 85 | for (i = 0; i < work->shared_count; ++i) |
83 | if (amdgpu_flip_handle_fence(work, &work->shared[i])) | 86 | if (amdgpu_display_flip_handle_fence(work, &work->shared[i])) |
84 | return; | 87 | return; |
85 | 88 | ||
86 | /* Wait until we're out of the vertical blank period before the one | 89 | /* Wait until we're out of the vertical blank period before the one |
87 | * targeted by the flip | 90 | * targeted by the flip |
88 | */ | 91 | */ |
89 | if (amdgpu_crtc->enabled && | 92 | if (amdgpu_crtc->enabled && |
90 | (amdgpu_get_crtc_scanoutpos(adev->ddev, work->crtc_id, 0, | 93 | (amdgpu_display_get_crtc_scanoutpos(adev->ddev, work->crtc_id, 0, |
91 | &vpos, &hpos, NULL, NULL, | 94 | &vpos, &hpos, NULL, NULL, |
92 | &crtc->hwmode) | 95 | &crtc->hwmode) |
93 | & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) == | 96 | & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) == |
94 | (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) && | 97 | (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) && |
95 | (int)(work->target_vblank - | 98 | (int)(work->target_vblank - |
@@ -117,7 +120,7 @@ static void amdgpu_flip_work_func(struct work_struct *__work) | |||
117 | /* | 120 | /* |
118 | * Handle unpin events outside the interrupt handler proper. | 121 | * Handle unpin events outside the interrupt handler proper. |
119 | */ | 122 | */ |
120 | static void amdgpu_unpin_work_func(struct work_struct *__work) | 123 | static void amdgpu_display_unpin_work_func(struct work_struct *__work) |
121 | { | 124 | { |
122 | struct amdgpu_flip_work *work = | 125 | struct amdgpu_flip_work *work = |
123 | container_of(__work, struct amdgpu_flip_work, unpin_work); | 126 | container_of(__work, struct amdgpu_flip_work, unpin_work); |
@@ -139,11 +142,11 @@ static void amdgpu_unpin_work_func(struct work_struct *__work) | |||
139 | kfree(work); | 142 | kfree(work); |
140 | } | 143 | } |
141 | 144 | ||
142 | int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, | 145 | int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc, |
143 | struct drm_framebuffer *fb, | 146 | struct drm_framebuffer *fb, |
144 | struct drm_pending_vblank_event *event, | 147 | struct drm_pending_vblank_event *event, |
145 | uint32_t page_flip_flags, uint32_t target, | 148 | uint32_t page_flip_flags, uint32_t target, |
146 | struct drm_modeset_acquire_ctx *ctx) | 149 | struct drm_modeset_acquire_ctx *ctx) |
147 | { | 150 | { |
148 | struct drm_device *dev = crtc->dev; | 151 | struct drm_device *dev = crtc->dev; |
149 | struct amdgpu_device *adev = dev->dev_private; | 152 | struct amdgpu_device *adev = dev->dev_private; |
@@ -162,8 +165,8 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, | |||
162 | if (work == NULL) | 165 | if (work == NULL) |
163 | return -ENOMEM; | 166 | return -ENOMEM; |
164 | 167 | ||
165 | INIT_DELAYED_WORK(&work->flip_work, amdgpu_flip_work_func); | 168 | INIT_DELAYED_WORK(&work->flip_work, amdgpu_display_flip_work_func); |
166 | INIT_WORK(&work->unpin_work, amdgpu_unpin_work_func); | 169 | INIT_WORK(&work->unpin_work, amdgpu_display_unpin_work_func); |
167 | 170 | ||
168 | work->event = event; | 171 | work->event = event; |
169 | work->adev = adev; | 172 | work->adev = adev; |
@@ -189,7 +192,7 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, | |||
189 | goto cleanup; | 192 | goto cleanup; |
190 | } | 193 | } |
191 | 194 | ||
192 | r = amdgpu_bo_pin(new_abo, AMDGPU_GEM_DOMAIN_VRAM, &base); | 195 | r = amdgpu_bo_pin(new_abo, amdgpu_display_framebuffer_domains(adev), &base); |
193 | if (unlikely(r != 0)) { | 196 | if (unlikely(r != 0)) { |
194 | DRM_ERROR("failed to pin new abo buffer before flip\n"); | 197 | DRM_ERROR("failed to pin new abo buffer before flip\n"); |
195 | goto unreserve; | 198 | goto unreserve; |
@@ -207,7 +210,7 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, | |||
207 | amdgpu_bo_unreserve(new_abo); | 210 | amdgpu_bo_unreserve(new_abo); |
208 | 211 | ||
209 | work->base = base; | 212 | work->base = base; |
210 | work->target_vblank = target - drm_crtc_vblank_count(crtc) + | 213 | work->target_vblank = target - (uint32_t)drm_crtc_vblank_count(crtc) + |
211 | amdgpu_get_vblank_counter_kms(dev, work->crtc_id); | 214 | amdgpu_get_vblank_counter_kms(dev, work->crtc_id); |
212 | 215 | ||
213 | /* we borrow the event spin lock for protecting flip_wrok */ | 216 | /* we borrow the event spin lock for protecting flip_wrok */ |
@@ -228,7 +231,7 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, | |||
228 | /* update crtc fb */ | 231 | /* update crtc fb */ |
229 | crtc->primary->fb = fb; | 232 | crtc->primary->fb = fb; |
230 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); | 233 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); |
231 | amdgpu_flip_work_func(&work->flip_work.work); | 234 | amdgpu_display_flip_work_func(&work->flip_work.work); |
232 | return 0; | 235 | return 0; |
233 | 236 | ||
234 | pflip_cleanup: | 237 | pflip_cleanup: |
@@ -254,8 +257,8 @@ cleanup: | |||
254 | return r; | 257 | return r; |
255 | } | 258 | } |
256 | 259 | ||
257 | int amdgpu_crtc_set_config(struct drm_mode_set *set, | 260 | int amdgpu_display_crtc_set_config(struct drm_mode_set *set, |
258 | struct drm_modeset_acquire_ctx *ctx) | 261 | struct drm_modeset_acquire_ctx *ctx) |
259 | { | 262 | { |
260 | struct drm_device *dev; | 263 | struct drm_device *dev; |
261 | struct amdgpu_device *adev; | 264 | struct amdgpu_device *adev; |
@@ -352,7 +355,7 @@ static const char *hpd_names[6] = { | |||
352 | "HPD6", | 355 | "HPD6", |
353 | }; | 356 | }; |
354 | 357 | ||
355 | void amdgpu_print_display_setup(struct drm_device *dev) | 358 | void amdgpu_display_print_display_setup(struct drm_device *dev) |
356 | { | 359 | { |
357 | struct drm_connector *connector; | 360 | struct drm_connector *connector; |
358 | struct amdgpu_connector *amdgpu_connector; | 361 | struct amdgpu_connector *amdgpu_connector; |
@@ -429,11 +432,11 @@ void amdgpu_print_display_setup(struct drm_device *dev) | |||
429 | } | 432 | } |
430 | 433 | ||
431 | /** | 434 | /** |
432 | * amdgpu_ddc_probe | 435 | * amdgpu_display_ddc_probe |
433 | * | 436 | * |
434 | */ | 437 | */ |
435 | bool amdgpu_ddc_probe(struct amdgpu_connector *amdgpu_connector, | 438 | bool amdgpu_display_ddc_probe(struct amdgpu_connector *amdgpu_connector, |
436 | bool use_aux) | 439 | bool use_aux) |
437 | { | 440 | { |
438 | u8 out = 0x0; | 441 | u8 out = 0x0; |
439 | u8 buf[8]; | 442 | u8 buf[8]; |
@@ -479,7 +482,7 @@ bool amdgpu_ddc_probe(struct amdgpu_connector *amdgpu_connector, | |||
479 | return true; | 482 | return true; |
480 | } | 483 | } |
481 | 484 | ||
482 | static void amdgpu_user_framebuffer_destroy(struct drm_framebuffer *fb) | 485 | static void amdgpu_display_user_framebuffer_destroy(struct drm_framebuffer *fb) |
483 | { | 486 | { |
484 | struct amdgpu_framebuffer *amdgpu_fb = to_amdgpu_framebuffer(fb); | 487 | struct amdgpu_framebuffer *amdgpu_fb = to_amdgpu_framebuffer(fb); |
485 | 488 | ||
@@ -488,9 +491,10 @@ static void amdgpu_user_framebuffer_destroy(struct drm_framebuffer *fb) | |||
488 | kfree(amdgpu_fb); | 491 | kfree(amdgpu_fb); |
489 | } | 492 | } |
490 | 493 | ||
491 | static int amdgpu_user_framebuffer_create_handle(struct drm_framebuffer *fb, | 494 | static int amdgpu_display_user_framebuffer_create_handle( |
492 | struct drm_file *file_priv, | 495 | struct drm_framebuffer *fb, |
493 | unsigned int *handle) | 496 | struct drm_file *file_priv, |
497 | unsigned int *handle) | ||
494 | { | 498 | { |
495 | struct amdgpu_framebuffer *amdgpu_fb = to_amdgpu_framebuffer(fb); | 499 | struct amdgpu_framebuffer *amdgpu_fb = to_amdgpu_framebuffer(fb); |
496 | 500 | ||
@@ -498,15 +502,28 @@ static int amdgpu_user_framebuffer_create_handle(struct drm_framebuffer *fb, | |||
498 | } | 502 | } |
499 | 503 | ||
500 | static const struct drm_framebuffer_funcs amdgpu_fb_funcs = { | 504 | static const struct drm_framebuffer_funcs amdgpu_fb_funcs = { |
501 | .destroy = amdgpu_user_framebuffer_destroy, | 505 | .destroy = amdgpu_display_user_framebuffer_destroy, |
502 | .create_handle = amdgpu_user_framebuffer_create_handle, | 506 | .create_handle = amdgpu_display_user_framebuffer_create_handle, |
503 | }; | 507 | }; |
504 | 508 | ||
505 | int | 509 | uint32_t amdgpu_display_framebuffer_domains(struct amdgpu_device *adev) |
506 | amdgpu_framebuffer_init(struct drm_device *dev, | 510 | { |
507 | struct amdgpu_framebuffer *rfb, | 511 | uint32_t domain = AMDGPU_GEM_DOMAIN_VRAM; |
508 | const struct drm_mode_fb_cmd2 *mode_cmd, | 512 | |
509 | struct drm_gem_object *obj) | 513 | #if defined(CONFIG_DRM_AMD_DC) |
514 | if (adev->asic_type >= CHIP_CARRIZO && adev->asic_type < CHIP_RAVEN && | ||
515 | adev->flags & AMD_IS_APU && | ||
516 | amdgpu_device_asic_has_dc_support(adev->asic_type)) | ||
517 | domain |= AMDGPU_GEM_DOMAIN_GTT; | ||
518 | #endif | ||
519 | |||
520 | return domain; | ||
521 | } | ||
522 | |||
523 | int amdgpu_display_framebuffer_init(struct drm_device *dev, | ||
524 | struct amdgpu_framebuffer *rfb, | ||
525 | const struct drm_mode_fb_cmd2 *mode_cmd, | ||
526 | struct drm_gem_object *obj) | ||
510 | { | 527 | { |
511 | int ret; | 528 | int ret; |
512 | rfb->obj = obj; | 529 | rfb->obj = obj; |
@@ -520,9 +537,9 @@ amdgpu_framebuffer_init(struct drm_device *dev, | |||
520 | } | 537 | } |
521 | 538 | ||
522 | struct drm_framebuffer * | 539 | struct drm_framebuffer * |
523 | amdgpu_user_framebuffer_create(struct drm_device *dev, | 540 | amdgpu_display_user_framebuffer_create(struct drm_device *dev, |
524 | struct drm_file *file_priv, | 541 | struct drm_file *file_priv, |
525 | const struct drm_mode_fb_cmd2 *mode_cmd) | 542 | const struct drm_mode_fb_cmd2 *mode_cmd) |
526 | { | 543 | { |
527 | struct drm_gem_object *obj; | 544 | struct drm_gem_object *obj; |
528 | struct amdgpu_framebuffer *amdgpu_fb; | 545 | struct amdgpu_framebuffer *amdgpu_fb; |
@@ -547,7 +564,7 @@ amdgpu_user_framebuffer_create(struct drm_device *dev, | |||
547 | return ERR_PTR(-ENOMEM); | 564 | return ERR_PTR(-ENOMEM); |
548 | } | 565 | } |
549 | 566 | ||
550 | ret = amdgpu_framebuffer_init(dev, amdgpu_fb, mode_cmd, obj); | 567 | ret = amdgpu_display_framebuffer_init(dev, amdgpu_fb, mode_cmd, obj); |
551 | if (ret) { | 568 | if (ret) { |
552 | kfree(amdgpu_fb); | 569 | kfree(amdgpu_fb); |
553 | drm_gem_object_put_unlocked(obj); | 570 | drm_gem_object_put_unlocked(obj); |
@@ -558,7 +575,7 @@ amdgpu_user_framebuffer_create(struct drm_device *dev, | |||
558 | } | 575 | } |
559 | 576 | ||
560 | const struct drm_mode_config_funcs amdgpu_mode_funcs = { | 577 | const struct drm_mode_config_funcs amdgpu_mode_funcs = { |
561 | .fb_create = amdgpu_user_framebuffer_create, | 578 | .fb_create = amdgpu_display_user_framebuffer_create, |
562 | .output_poll_changed = drm_fb_helper_output_poll_changed, | 579 | .output_poll_changed = drm_fb_helper_output_poll_changed, |
563 | }; | 580 | }; |
564 | 581 | ||
@@ -580,7 +597,7 @@ static const struct drm_prop_enum_list amdgpu_dither_enum_list[] = | |||
580 | { AMDGPU_FMT_DITHER_ENABLE, "on" }, | 597 | { AMDGPU_FMT_DITHER_ENABLE, "on" }, |
581 | }; | 598 | }; |
582 | 599 | ||
583 | int amdgpu_modeset_create_props(struct amdgpu_device *adev) | 600 | int amdgpu_display_modeset_create_props(struct amdgpu_device *adev) |
584 | { | 601 | { |
585 | int sz; | 602 | int sz; |
586 | 603 | ||
@@ -629,7 +646,7 @@ int amdgpu_modeset_create_props(struct amdgpu_device *adev) | |||
629 | return 0; | 646 | return 0; |
630 | } | 647 | } |
631 | 648 | ||
632 | void amdgpu_update_display_priority(struct amdgpu_device *adev) | 649 | void amdgpu_display_update_priority(struct amdgpu_device *adev) |
633 | { | 650 | { |
634 | /* adjustment options for the display watermarks */ | 651 | /* adjustment options for the display watermarks */ |
635 | if ((amdgpu_disp_priority == 0) || (amdgpu_disp_priority > 2)) | 652 | if ((amdgpu_disp_priority == 0) || (amdgpu_disp_priority > 2)) |
@@ -639,7 +656,7 @@ void amdgpu_update_display_priority(struct amdgpu_device *adev) | |||
639 | 656 | ||
640 | } | 657 | } |
641 | 658 | ||
642 | static bool is_hdtv_mode(const struct drm_display_mode *mode) | 659 | static bool amdgpu_display_is_hdtv_mode(const struct drm_display_mode *mode) |
643 | { | 660 | { |
644 | /* try and guess if this is a tv or a monitor */ | 661 | /* try and guess if this is a tv or a monitor */ |
645 | if ((mode->vdisplay == 480 && mode->hdisplay == 720) || /* 480p */ | 662 | if ((mode->vdisplay == 480 && mode->hdisplay == 720) || /* 480p */ |
@@ -651,9 +668,9 @@ static bool is_hdtv_mode(const struct drm_display_mode *mode) | |||
651 | return false; | 668 | return false; |
652 | } | 669 | } |
653 | 670 | ||
654 | bool amdgpu_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | 671 | bool amdgpu_display_crtc_scaling_mode_fixup(struct drm_crtc *crtc, |
655 | const struct drm_display_mode *mode, | 672 | const struct drm_display_mode *mode, |
656 | struct drm_display_mode *adjusted_mode) | 673 | struct drm_display_mode *adjusted_mode) |
657 | { | 674 | { |
658 | struct drm_device *dev = crtc->dev; | 675 | struct drm_device *dev = crtc->dev; |
659 | struct drm_encoder *encoder; | 676 | struct drm_encoder *encoder; |
@@ -696,7 +713,7 @@ bool amdgpu_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | |||
696 | ((amdgpu_encoder->underscan_type == UNDERSCAN_ON) || | 713 | ((amdgpu_encoder->underscan_type == UNDERSCAN_ON) || |
697 | ((amdgpu_encoder->underscan_type == UNDERSCAN_AUTO) && | 714 | ((amdgpu_encoder->underscan_type == UNDERSCAN_AUTO) && |
698 | drm_detect_hdmi_monitor(amdgpu_connector_edid(connector)) && | 715 | drm_detect_hdmi_monitor(amdgpu_connector_edid(connector)) && |
699 | is_hdtv_mode(mode)))) { | 716 | amdgpu_display_is_hdtv_mode(mode)))) { |
700 | if (amdgpu_encoder->underscan_hborder != 0) | 717 | if (amdgpu_encoder->underscan_hborder != 0) |
701 | amdgpu_crtc->h_border = amdgpu_encoder->underscan_hborder; | 718 | amdgpu_crtc->h_border = amdgpu_encoder->underscan_hborder; |
702 | else | 719 | else |
@@ -764,10 +781,10 @@ bool amdgpu_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | |||
764 | * unknown small number of scanlines wrt. real scanout position. | 781 | * unknown small number of scanlines wrt. real scanout position. |
765 | * | 782 | * |
766 | */ | 783 | */ |
767 | int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, | 784 | int amdgpu_display_get_crtc_scanoutpos(struct drm_device *dev, |
768 | unsigned int flags, int *vpos, int *hpos, | 785 | unsigned int pipe, unsigned int flags, int *vpos, |
769 | ktime_t *stime, ktime_t *etime, | 786 | int *hpos, ktime_t *stime, ktime_t *etime, |
770 | const struct drm_display_mode *mode) | 787 | const struct drm_display_mode *mode) |
771 | { | 788 | { |
772 | u32 vbl = 0, position = 0; | 789 | u32 vbl = 0, position = 0; |
773 | int vbl_start, vbl_end, vtotal, ret = 0; | 790 | int vbl_start, vbl_end, vtotal, ret = 0; |
@@ -859,7 +876,7 @@ int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, | |||
859 | return ret; | 876 | return ret; |
860 | } | 877 | } |
861 | 878 | ||
862 | int amdgpu_crtc_idx_to_irq_type(struct amdgpu_device *adev, int crtc) | 879 | int amdgpu_display_crtc_idx_to_irq_type(struct amdgpu_device *adev, int crtc) |
863 | { | 880 | { |
864 | if (crtc < 0 || crtc >= adev->mode_info.num_crtc) | 881 | if (crtc < 0 || crtc >= adev->mode_info.num_crtc) |
865 | return AMDGPU_CRTC_IRQ_NONE; | 882 | return AMDGPU_CRTC_IRQ_NONE; |