.. | .. |
---|
20 | 20 | * OTHER DEALINGS IN THE SOFTWARE. |
---|
21 | 21 | * |
---|
22 | 22 | */ |
---|
23 | | -#include <drm/drmP.h> |
---|
| 23 | + |
---|
| 24 | +#include <drm/drm_vblank.h> |
---|
| 25 | + |
---|
24 | 26 | #include "amdgpu.h" |
---|
25 | 27 | #include "amdgpu_pm.h" |
---|
26 | 28 | #include "amdgpu_i2c.h" |
---|
.. | .. |
---|
45 | 47 | static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev); |
---|
46 | 48 | static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev, |
---|
47 | 49 | int index); |
---|
| 50 | +static int dce_virtual_pageflip(struct amdgpu_device *adev, |
---|
| 51 | + unsigned crtc_id); |
---|
| 52 | +static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer); |
---|
48 | 53 | static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev, |
---|
49 | 54 | int crtc, |
---|
50 | 55 | enum amdgpu_interrupt_state state); |
---|
.. | .. |
---|
121 | 126 | .set_config = amdgpu_display_crtc_set_config, |
---|
122 | 127 | .destroy = dce_virtual_crtc_destroy, |
---|
123 | 128 | .page_flip_target = amdgpu_display_crtc_page_flip_target, |
---|
| 129 | + .get_vblank_counter = amdgpu_get_vblank_counter_kms, |
---|
| 130 | + .enable_vblank = amdgpu_enable_vblank_kms, |
---|
| 131 | + .disable_vblank = amdgpu_disable_vblank_kms, |
---|
| 132 | + .get_vblank_timestamp = drm_crtc_vblank_helper_get_vblank_timestamp, |
---|
124 | 133 | }; |
---|
125 | 134 | |
---|
126 | 135 | static void dce_virtual_crtc_dpms(struct drm_crtc *crtc, int mode) |
---|
127 | 136 | { |
---|
128 | 137 | struct drm_device *dev = crtc->dev; |
---|
129 | | - struct amdgpu_device *adev = dev->dev_private; |
---|
| 138 | + struct amdgpu_device *adev = drm_to_adev(dev); |
---|
130 | 139 | struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); |
---|
131 | 140 | unsigned type; |
---|
132 | 141 | |
---|
.. | .. |
---|
165 | 174 | static void dce_virtual_crtc_disable(struct drm_crtc *crtc) |
---|
166 | 175 | { |
---|
167 | 176 | struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); |
---|
| 177 | + struct drm_device *dev = crtc->dev; |
---|
168 | 178 | |
---|
169 | | - dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); |
---|
170 | | - if (crtc->primary->fb) { |
---|
171 | | - int r; |
---|
172 | | - struct amdgpu_bo *abo; |
---|
| 179 | + if (dev->num_crtcs) |
---|
| 180 | + drm_crtc_vblank_off(crtc); |
---|
173 | 181 | |
---|
174 | | - abo = gem_to_amdgpu_bo(crtc->primary->fb->obj[0]); |
---|
175 | | - r = amdgpu_bo_reserve(abo, true); |
---|
176 | | - if (unlikely(r)) |
---|
177 | | - DRM_ERROR("failed to reserve abo before unpin\n"); |
---|
178 | | - else { |
---|
179 | | - amdgpu_bo_unpin(abo); |
---|
180 | | - amdgpu_bo_unreserve(abo); |
---|
181 | | - } |
---|
182 | | - } |
---|
183 | | - |
---|
| 182 | + amdgpu_crtc->enabled = false; |
---|
184 | 183 | amdgpu_crtc->pll_id = ATOM_PPLL_INVALID; |
---|
185 | 184 | amdgpu_crtc->encoder = NULL; |
---|
186 | 185 | amdgpu_crtc->connector = NULL; |
---|
.. | .. |
---|
229 | 228 | .prepare = dce_virtual_crtc_prepare, |
---|
230 | 229 | .commit = dce_virtual_crtc_commit, |
---|
231 | 230 | .disable = dce_virtual_crtc_disable, |
---|
| 231 | + .get_scanout_position = amdgpu_crtc_get_scanout_position, |
---|
232 | 232 | }; |
---|
233 | 233 | |
---|
234 | 234 | static int dce_virtual_crtc_init(struct amdgpu_device *adev, int index) |
---|
.. | .. |
---|
240 | 240 | if (amdgpu_crtc == NULL) |
---|
241 | 241 | return -ENOMEM; |
---|
242 | 242 | |
---|
243 | | - drm_crtc_init(adev->ddev, &amdgpu_crtc->base, &dce_virtual_crtc_funcs); |
---|
| 243 | + drm_crtc_init(adev_to_drm(adev), &amdgpu_crtc->base, &dce_virtual_crtc_funcs); |
---|
244 | 244 | |
---|
245 | 245 | drm_mode_crtc_set_gamma_size(&amdgpu_crtc->base, 256); |
---|
246 | 246 | amdgpu_crtc->crtc_id = index; |
---|
.. | .. |
---|
252 | 252 | amdgpu_crtc->vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE; |
---|
253 | 253 | drm_crtc_helper_add(&amdgpu_crtc->base, &dce_virtual_crtc_helper_funcs); |
---|
254 | 254 | |
---|
| 255 | + hrtimer_init(&amdgpu_crtc->vblank_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); |
---|
| 256 | + hrtimer_set_expires(&amdgpu_crtc->vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD); |
---|
| 257 | + amdgpu_crtc->vblank_timer.function = dce_virtual_vblank_timer_handle; |
---|
| 258 | + hrtimer_start(&amdgpu_crtc->vblank_timer, |
---|
| 259 | + DCE_VIRTUAL_VBLANK_PERIOD, HRTIMER_MODE_REL); |
---|
255 | 260 | return 0; |
---|
256 | 261 | } |
---|
257 | 262 | |
---|
.. | .. |
---|
271 | 276 | dce_virtual_encoder(struct drm_connector *connector) |
---|
272 | 277 | { |
---|
273 | 278 | struct drm_encoder *encoder; |
---|
274 | | - int i; |
---|
275 | 279 | |
---|
276 | | - drm_connector_for_each_possible_encoder(connector, encoder, i) { |
---|
| 280 | + drm_connector_for_each_possible_encoder(connector, encoder) { |
---|
277 | 281 | if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL) |
---|
278 | 282 | return encoder; |
---|
279 | 283 | } |
---|
280 | 284 | |
---|
281 | 285 | /* pick the first one */ |
---|
282 | | - drm_connector_for_each_possible_encoder(connector, encoder, i) |
---|
| 286 | + drm_connector_for_each_possible_encoder(connector, encoder) |
---|
283 | 287 | return encoder; |
---|
284 | 288 | |
---|
285 | 289 | return NULL; |
---|
.. | .. |
---|
293 | 297 | static const struct mode_size { |
---|
294 | 298 | int w; |
---|
295 | 299 | int h; |
---|
296 | | - } common_modes[17] = { |
---|
| 300 | + } common_modes[21] = { |
---|
297 | 301 | { 640, 480}, |
---|
298 | 302 | { 720, 480}, |
---|
299 | 303 | { 800, 600}, |
---|
.. | .. |
---|
310 | 314 | {1680, 1050}, |
---|
311 | 315 | {1600, 1200}, |
---|
312 | 316 | {1920, 1080}, |
---|
313 | | - {1920, 1200} |
---|
| 317 | + {1920, 1200}, |
---|
| 318 | + {4096, 3112}, |
---|
| 319 | + {3656, 2664}, |
---|
| 320 | + {3840, 2160}, |
---|
| 321 | + {4096, 2160}, |
---|
314 | 322 | }; |
---|
315 | 323 | |
---|
316 | | - for (i = 0; i < 17; i++) { |
---|
| 324 | + for (i = 0; i < 21; i++) { |
---|
317 | 325 | mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false); |
---|
318 | 326 | drm_mode_probed_add(connector, mode); |
---|
319 | 327 | } |
---|
.. | .. |
---|
372 | 380 | int r, i; |
---|
373 | 381 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
---|
374 | 382 | |
---|
375 | | - r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, VISLANDS30_IV_SRCID_SMU_DISP_TIMER2_TRIGGER, &adev->crtc_irq); |
---|
| 383 | + r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, VISLANDS30_IV_SRCID_SMU_DISP_TIMER2_TRIGGER, &adev->crtc_irq); |
---|
376 | 384 | if (r) |
---|
377 | 385 | return r; |
---|
378 | 386 | |
---|
379 | | - adev->ddev->max_vblank_count = 0; |
---|
| 387 | + adev_to_drm(adev)->max_vblank_count = 0; |
---|
380 | 388 | |
---|
381 | | - adev->ddev->mode_config.funcs = &amdgpu_mode_funcs; |
---|
| 389 | + adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs; |
---|
382 | 390 | |
---|
383 | | - adev->ddev->mode_config.max_width = 16384; |
---|
384 | | - adev->ddev->mode_config.max_height = 16384; |
---|
| 391 | + adev_to_drm(adev)->mode_config.max_width = 16384; |
---|
| 392 | + adev_to_drm(adev)->mode_config.max_height = 16384; |
---|
385 | 393 | |
---|
386 | | - adev->ddev->mode_config.preferred_depth = 24; |
---|
387 | | - adev->ddev->mode_config.prefer_shadow = 1; |
---|
| 394 | + adev_to_drm(adev)->mode_config.preferred_depth = 24; |
---|
| 395 | + adev_to_drm(adev)->mode_config.prefer_shadow = 1; |
---|
388 | 396 | |
---|
389 | | - adev->ddev->mode_config.fb_base = adev->gmc.aper_base; |
---|
| 397 | + adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base; |
---|
390 | 398 | |
---|
391 | 399 | r = amdgpu_display_modeset_create_props(adev); |
---|
392 | 400 | if (r) |
---|
393 | 401 | return r; |
---|
394 | 402 | |
---|
395 | | - adev->ddev->mode_config.max_width = 16384; |
---|
396 | | - adev->ddev->mode_config.max_height = 16384; |
---|
| 403 | + adev_to_drm(adev)->mode_config.max_width = 16384; |
---|
| 404 | + adev_to_drm(adev)->mode_config.max_height = 16384; |
---|
397 | 405 | |
---|
398 | 406 | /* allocate crtcs, encoders, connectors */ |
---|
399 | 407 | for (i = 0; i < adev->mode_info.num_crtc; i++) { |
---|
.. | .. |
---|
405 | 413 | return r; |
---|
406 | 414 | } |
---|
407 | 415 | |
---|
408 | | - drm_kms_helper_poll_init(adev->ddev); |
---|
| 416 | + drm_kms_helper_poll_init(adev_to_drm(adev)); |
---|
409 | 417 | |
---|
410 | 418 | adev->mode_info.mode_config_initialized = true; |
---|
411 | 419 | return 0; |
---|
.. | .. |
---|
417 | 425 | |
---|
418 | 426 | kfree(adev->mode_info.bios_hardcoded_edid); |
---|
419 | 427 | |
---|
420 | | - drm_kms_helper_poll_fini(adev->ddev); |
---|
| 428 | + drm_kms_helper_poll_fini(adev_to_drm(adev)); |
---|
421 | 429 | |
---|
422 | | - drm_mode_config_cleanup(adev->ddev); |
---|
| 430 | + drm_mode_config_cleanup(adev_to_drm(adev)); |
---|
423 | 431 | /* clear crtcs pointer to avoid dce irq finish routine access freed data */ |
---|
424 | 432 | memset(adev->mode_info.crtcs, 0, sizeof(adev->mode_info.crtcs[0]) * AMDGPU_MAX_CRTCS); |
---|
425 | 433 | adev->mode_info.mode_config_initialized = false; |
---|
.. | .. |
---|
465 | 473 | #endif |
---|
466 | 474 | /* no DCE */ |
---|
467 | 475 | break; |
---|
468 | | - case CHIP_VEGA10: |
---|
469 | | - case CHIP_VEGA12: |
---|
470 | | - case CHIP_VEGA20: |
---|
471 | | - break; |
---|
472 | 476 | default: |
---|
473 | | - DRM_ERROR("Virtual display unsupported ASIC type: 0x%X\n", adev->asic_type); |
---|
| 477 | + break; |
---|
474 | 478 | } |
---|
475 | 479 | return 0; |
---|
476 | 480 | } |
---|
.. | .. |
---|
482 | 486 | |
---|
483 | 487 | for (i = 0; i<adev->mode_info.num_crtc; i++) |
---|
484 | 488 | if (adev->mode_info.crtcs[i]) |
---|
485 | | - dce_virtual_set_crtc_vblank_interrupt_state(adev, i, AMDGPU_IRQ_STATE_DISABLE); |
---|
| 489 | + hrtimer_cancel(&adev->mode_info.crtcs[i]->vblank_timer); |
---|
486 | 490 | |
---|
487 | 491 | return 0; |
---|
488 | 492 | } |
---|
.. | .. |
---|
608 | 612 | if (!encoder) |
---|
609 | 613 | return -ENOMEM; |
---|
610 | 614 | encoder->possible_crtcs = 1 << index; |
---|
611 | | - drm_encoder_init(adev->ddev, encoder, &dce_virtual_encoder_funcs, |
---|
| 615 | + drm_encoder_init(adev_to_drm(adev), encoder, &dce_virtual_encoder_funcs, |
---|
612 | 616 | DRM_MODE_ENCODER_VIRTUAL, NULL); |
---|
613 | 617 | drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs); |
---|
614 | 618 | |
---|
.. | .. |
---|
619 | 623 | } |
---|
620 | 624 | |
---|
621 | 625 | /* add a new connector */ |
---|
622 | | - drm_connector_init(adev->ddev, connector, &dce_virtual_connector_funcs, |
---|
| 626 | + drm_connector_init(adev_to_drm(adev), connector, &dce_virtual_connector_funcs, |
---|
623 | 627 | DRM_MODE_CONNECTOR_VIRTUAL); |
---|
624 | 628 | drm_connector_helper_add(connector, &dce_virtual_connector_helper_funcs); |
---|
625 | 629 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; |
---|
626 | 630 | connector->interlace_allowed = false; |
---|
627 | 631 | connector->doublescan_allowed = false; |
---|
628 | | - drm_connector_register(connector); |
---|
629 | 632 | |
---|
630 | 633 | /* link them */ |
---|
631 | 634 | drm_connector_attach_encoder(connector, encoder); |
---|
.. | .. |
---|
649 | 652 | |
---|
650 | 653 | static void dce_virtual_set_display_funcs(struct amdgpu_device *adev) |
---|
651 | 654 | { |
---|
652 | | - if (adev->mode_info.funcs == NULL) |
---|
653 | | - adev->mode_info.funcs = &dce_virtual_display_funcs; |
---|
| 655 | + adev->mode_info.funcs = &dce_virtual_display_funcs; |
---|
654 | 656 | } |
---|
655 | 657 | |
---|
656 | 658 | static int dce_virtual_pageflip(struct amdgpu_device *adev, |
---|
.. | .. |
---|
671 | 673 | if (amdgpu_crtc == NULL) |
---|
672 | 674 | return 0; |
---|
673 | 675 | |
---|
674 | | - spin_lock_irqsave(&adev->ddev->event_lock, flags); |
---|
| 676 | + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); |
---|
675 | 677 | works = amdgpu_crtc->pflip_works; |
---|
676 | 678 | if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) { |
---|
677 | 679 | DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != " |
---|
678 | 680 | "AMDGPU_FLIP_SUBMITTED(%d)\n", |
---|
679 | 681 | amdgpu_crtc->pflip_status, |
---|
680 | 682 | AMDGPU_FLIP_SUBMITTED); |
---|
681 | | - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); |
---|
| 683 | + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); |
---|
682 | 684 | return 0; |
---|
683 | 685 | } |
---|
684 | 686 | |
---|
.. | .. |
---|
690 | 692 | if (works->event) |
---|
691 | 693 | drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event); |
---|
692 | 694 | |
---|
693 | | - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); |
---|
| 695 | + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); |
---|
694 | 696 | |
---|
695 | 697 | drm_crtc_vblank_put(&amdgpu_crtc->base); |
---|
696 | | - schedule_work(&works->unpin_work); |
---|
| 698 | + amdgpu_bo_unref(&works->old_abo); |
---|
| 699 | + kfree(works->shared); |
---|
| 700 | + kfree(works); |
---|
697 | 701 | |
---|
698 | 702 | return 0; |
---|
699 | 703 | } |
---|
.. | .. |
---|
703 | 707 | struct amdgpu_crtc *amdgpu_crtc = container_of(vblank_timer, |
---|
704 | 708 | struct amdgpu_crtc, vblank_timer); |
---|
705 | 709 | struct drm_device *ddev = amdgpu_crtc->base.dev; |
---|
706 | | - struct amdgpu_device *adev = ddev->dev_private; |
---|
| 710 | + struct amdgpu_device *adev = drm_to_adev(ddev); |
---|
| 711 | + struct amdgpu_irq_src *source = adev->irq.client[AMDGPU_IRQ_CLIENTID_LEGACY].sources |
---|
| 712 | + [VISLANDS30_IV_SRCID_SMU_DISP_TIMER2_TRIGGER]; |
---|
| 713 | + int irq_type = amdgpu_display_crtc_idx_to_irq_type(adev, |
---|
| 714 | + amdgpu_crtc->crtc_id); |
---|
707 | 715 | |
---|
708 | | - drm_handle_vblank(ddev, amdgpu_crtc->crtc_id); |
---|
709 | | - dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id); |
---|
| 716 | + if (amdgpu_irq_enabled(adev, source, irq_type)) { |
---|
| 717 | + drm_handle_vblank(ddev, amdgpu_crtc->crtc_id); |
---|
| 718 | + dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id); |
---|
| 719 | + } |
---|
710 | 720 | hrtimer_start(vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD, |
---|
711 | 721 | HRTIMER_MODE_REL); |
---|
712 | 722 | |
---|
.. | .. |
---|
720 | 730 | if (crtc >= adev->mode_info.num_crtc || !adev->mode_info.crtcs[crtc]) { |
---|
721 | 731 | DRM_DEBUG("invalid crtc %d\n", crtc); |
---|
722 | 732 | return; |
---|
723 | | - } |
---|
724 | | - |
---|
725 | | - if (state && !adev->mode_info.crtcs[crtc]->vsync_timer_enabled) { |
---|
726 | | - DRM_DEBUG("Enable software vsync timer\n"); |
---|
727 | | - hrtimer_init(&adev->mode_info.crtcs[crtc]->vblank_timer, |
---|
728 | | - CLOCK_MONOTONIC, HRTIMER_MODE_REL); |
---|
729 | | - hrtimer_set_expires(&adev->mode_info.crtcs[crtc]->vblank_timer, |
---|
730 | | - DCE_VIRTUAL_VBLANK_PERIOD); |
---|
731 | | - adev->mode_info.crtcs[crtc]->vblank_timer.function = |
---|
732 | | - dce_virtual_vblank_timer_handle; |
---|
733 | | - hrtimer_start(&adev->mode_info.crtcs[crtc]->vblank_timer, |
---|
734 | | - DCE_VIRTUAL_VBLANK_PERIOD, HRTIMER_MODE_REL); |
---|
735 | | - } else if (!state && adev->mode_info.crtcs[crtc]->vsync_timer_enabled) { |
---|
736 | | - DRM_DEBUG("Disable software vsync timer\n"); |
---|
737 | | - hrtimer_cancel(&adev->mode_info.crtcs[crtc]->vblank_timer); |
---|
738 | 733 | } |
---|
739 | 734 | |
---|
740 | 735 | adev->mode_info.crtcs[crtc]->vsync_timer_enabled = state; |
---|