aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/dce_virtual.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_virtual.c432
1 files changed, 232 insertions, 200 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
index c2bd9f045532..cc85676a68d9 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
@@ -27,6 +27,9 @@
27#include "atom.h" 27#include "atom.h"
28#include "amdgpu_pll.h" 28#include "amdgpu_pll.h"
29#include "amdgpu_connectors.h" 29#include "amdgpu_connectors.h"
30#ifdef CONFIG_DRM_AMDGPU_SI
31#include "dce_v6_0.h"
32#endif
30#ifdef CONFIG_DRM_AMDGPU_CIK 33#ifdef CONFIG_DRM_AMDGPU_CIK
31#include "dce_v8_0.h" 34#include "dce_v8_0.h"
32#endif 35#endif
@@ -34,11 +37,13 @@
34#include "dce_v11_0.h" 37#include "dce_v11_0.h"
35#include "dce_virtual.h" 38#include "dce_virtual.h"
36 39
40#define DCE_VIRTUAL_VBLANK_PERIOD 16666666
41
42
37static void dce_virtual_set_display_funcs(struct amdgpu_device *adev); 43static void dce_virtual_set_display_funcs(struct amdgpu_device *adev);
38static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev); 44static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev);
39static int dce_virtual_pageflip_irq(struct amdgpu_device *adev, 45static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
40 struct amdgpu_irq_src *source, 46 int index);
41 struct amdgpu_iv_entry *entry);
42 47
43/** 48/**
44 * dce_virtual_vblank_wait - vblank wait asic callback. 49 * dce_virtual_vblank_wait - vblank wait asic callback.
@@ -99,6 +104,14 @@ static void dce_virtual_stop_mc_access(struct amdgpu_device *adev,
99 struct amdgpu_mode_mc_save *save) 104 struct amdgpu_mode_mc_save *save)
100{ 105{
101 switch (adev->asic_type) { 106 switch (adev->asic_type) {
107#ifdef CONFIG_DRM_AMDGPU_SI
108 case CHIP_TAHITI:
109 case CHIP_PITCAIRN:
110 case CHIP_VERDE:
111 case CHIP_OLAND:
112 dce_v6_0_disable_dce(adev);
113 break;
114#endif
102#ifdef CONFIG_DRM_AMDGPU_CIK 115#ifdef CONFIG_DRM_AMDGPU_CIK
103 case CHIP_BONAIRE: 116 case CHIP_BONAIRE:
104 case CHIP_HAWAII: 117 case CHIP_HAWAII:
@@ -119,6 +132,9 @@ static void dce_virtual_stop_mc_access(struct amdgpu_device *adev,
119 dce_v11_0_disable_dce(adev); 132 dce_v11_0_disable_dce(adev);
120 break; 133 break;
121 case CHIP_TOPAZ: 134 case CHIP_TOPAZ:
135#ifdef CONFIG_DRM_AMDGPU_SI
136 case CHIP_HAINAN:
137#endif
122 /* no DCE */ 138 /* no DCE */
123 return; 139 return;
124 default: 140 default:
@@ -195,10 +211,9 @@ static void dce_virtual_crtc_dpms(struct drm_crtc *crtc, int mode)
195 switch (mode) { 211 switch (mode) {
196 case DRM_MODE_DPMS_ON: 212 case DRM_MODE_DPMS_ON:
197 amdgpu_crtc->enabled = true; 213 amdgpu_crtc->enabled = true;
198 /* Make sure VBLANK and PFLIP interrupts are still enabled */ 214 /* Make sure VBLANK interrupts are still enabled */
199 type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id); 215 type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id);
200 amdgpu_irq_update(adev, &adev->crtc_irq, type); 216 amdgpu_irq_update(adev, &adev->crtc_irq, type);
201 amdgpu_irq_update(adev, &adev->pageflip_irq, type);
202 drm_vblank_on(dev, amdgpu_crtc->crtc_id); 217 drm_vblank_on(dev, amdgpu_crtc->crtc_id);
203 break; 218 break;
204 case DRM_MODE_DPMS_STANDBY: 219 case DRM_MODE_DPMS_STANDBY:
@@ -264,24 +279,6 @@ static bool dce_virtual_crtc_mode_fixup(struct drm_crtc *crtc,
264 const struct drm_display_mode *mode, 279 const struct drm_display_mode *mode,
265 struct drm_display_mode *adjusted_mode) 280 struct drm_display_mode *adjusted_mode)
266{ 281{
267 struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
268 struct drm_device *dev = crtc->dev;
269 struct drm_encoder *encoder;
270
271 /* assign the encoder to the amdgpu crtc to avoid repeated lookups later */
272 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
273 if (encoder->crtc == crtc) {
274 amdgpu_crtc->encoder = encoder;
275 amdgpu_crtc->connector = amdgpu_get_connector_for_encoder(encoder);
276 break;
277 }
278 }
279 if ((amdgpu_crtc->encoder == NULL) || (amdgpu_crtc->connector == NULL)) {
280 amdgpu_crtc->encoder = NULL;
281 amdgpu_crtc->connector = NULL;
282 return false;
283 }
284
285 return true; 282 return true;
286} 283}
287 284
@@ -341,6 +338,7 @@ static int dce_virtual_crtc_init(struct amdgpu_device *adev, int index)
341 amdgpu_crtc->pll_id = ATOM_PPLL_INVALID; 338 amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
342 amdgpu_crtc->encoder = NULL; 339 amdgpu_crtc->encoder = NULL;
343 amdgpu_crtc->connector = NULL; 340 amdgpu_crtc->connector = NULL;
341 amdgpu_crtc->vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE;
344 drm_crtc_helper_add(&amdgpu_crtc->base, &dce_virtual_crtc_helper_funcs); 342 drm_crtc_helper_add(&amdgpu_crtc->base, &dce_virtual_crtc_helper_funcs);
345 343
346 return 0; 344 return 0;
@@ -350,48 +348,128 @@ static int dce_virtual_early_init(void *handle)
350{ 348{
351 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 349 struct amdgpu_device *adev = (struct amdgpu_device *)handle;
352 350
353 adev->mode_info.vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE;
354 dce_virtual_set_display_funcs(adev); 351 dce_virtual_set_display_funcs(adev);
355 dce_virtual_set_irq_funcs(adev); 352 dce_virtual_set_irq_funcs(adev);
356 353
357 adev->mode_info.num_crtc = 1;
358 adev->mode_info.num_hpd = 1; 354 adev->mode_info.num_hpd = 1;
359 adev->mode_info.num_dig = 1; 355 adev->mode_info.num_dig = 1;
360 return 0; 356 return 0;
361} 357}
362 358
363static bool dce_virtual_get_connector_info(struct amdgpu_device *adev) 359static struct drm_encoder *
360dce_virtual_encoder(struct drm_connector *connector)
364{ 361{
365 struct amdgpu_i2c_bus_rec ddc_bus; 362 int enc_id = connector->encoder_ids[0];
366 struct amdgpu_router router; 363 struct drm_encoder *encoder;
367 struct amdgpu_hpd hpd; 364 int i;
368 365
369 /* look up gpio for ddc, hpd */ 366 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
370 ddc_bus.valid = false; 367 if (connector->encoder_ids[i] == 0)
371 hpd.hpd = AMDGPU_HPD_NONE; 368 break;
372 /* needed for aux chan transactions */
373 ddc_bus.hpd = hpd.hpd;
374 369
375 memset(&router, 0, sizeof(router)); 370 encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
376 router.ddc_valid = false; 371 if (!encoder)
377 router.cd_valid = false; 372 continue;
378 amdgpu_display_add_connector(adev,
379 0,
380 ATOM_DEVICE_CRT1_SUPPORT,
381 DRM_MODE_CONNECTOR_VIRTUAL, &ddc_bus,
382 CONNECTOR_OBJECT_ID_VIRTUAL,
383 &hpd,
384 &router);
385 373
386 amdgpu_display_add_encoder(adev, ENCODER_VIRTUAL_ENUM_VIRTUAL, 374 if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
387 ATOM_DEVICE_CRT1_SUPPORT, 375 return encoder;
388 0); 376 }
389 377
390 amdgpu_link_encoder_connector(adev->ddev); 378 /* pick the first one */
379 if (enc_id)
380 return drm_encoder_find(connector->dev, enc_id);
381 return NULL;
382}
383
384static int dce_virtual_get_modes(struct drm_connector *connector)
385{
386 struct drm_device *dev = connector->dev;
387 struct drm_display_mode *mode = NULL;
388 unsigned i;
389 static const struct mode_size {
390 int w;
391 int h;
392 } common_modes[17] = {
393 { 640, 480},
394 { 720, 480},
395 { 800, 600},
396 { 848, 480},
397 {1024, 768},
398 {1152, 768},
399 {1280, 720},
400 {1280, 800},
401 {1280, 854},
402 {1280, 960},
403 {1280, 1024},
404 {1440, 900},
405 {1400, 1050},
406 {1680, 1050},
407 {1600, 1200},
408 {1920, 1080},
409 {1920, 1200}
410 };
411
412 for (i = 0; i < 17; i++) {
413 mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
414 drm_mode_probed_add(connector, mode);
415 }
391 416
392 return true; 417 return 0;
418}
419
420static int dce_virtual_mode_valid(struct drm_connector *connector,
421 struct drm_display_mode *mode)
422{
423 return MODE_OK;
424}
425
426static int
427dce_virtual_dpms(struct drm_connector *connector, int mode)
428{
429 return 0;
393} 430}
394 431
432static enum drm_connector_status
433dce_virtual_detect(struct drm_connector *connector, bool force)
434{
435 return connector_status_connected;
436}
437
438static int
439dce_virtual_set_property(struct drm_connector *connector,
440 struct drm_property *property,
441 uint64_t val)
442{
443 return 0;
444}
445
446static void dce_virtual_destroy(struct drm_connector *connector)
447{
448 drm_connector_unregister(connector);
449 drm_connector_cleanup(connector);
450 kfree(connector);
451}
452
453static void dce_virtual_force(struct drm_connector *connector)
454{
455 return;
456}
457
458static const struct drm_connector_helper_funcs dce_virtual_connector_helper_funcs = {
459 .get_modes = dce_virtual_get_modes,
460 .mode_valid = dce_virtual_mode_valid,
461 .best_encoder = dce_virtual_encoder,
462};
463
464static const struct drm_connector_funcs dce_virtual_connector_funcs = {
465 .dpms = dce_virtual_dpms,
466 .detect = dce_virtual_detect,
467 .fill_modes = drm_helper_probe_single_connector_modes,
468 .set_property = dce_virtual_set_property,
469 .destroy = dce_virtual_destroy,
470 .force = dce_virtual_force,
471};
472
395static int dce_virtual_sw_init(void *handle) 473static int dce_virtual_sw_init(void *handle)
396{ 474{
397 int r, i; 475 int r, i;
@@ -420,16 +498,16 @@ static int dce_virtual_sw_init(void *handle)
420 adev->ddev->mode_config.max_width = 16384; 498 adev->ddev->mode_config.max_width = 16384;
421 adev->ddev->mode_config.max_height = 16384; 499 adev->ddev->mode_config.max_height = 16384;
422 500
423 /* allocate crtcs */ 501 /* allocate crtcs, encoders, connectors */
424 for (i = 0; i < adev->mode_info.num_crtc; i++) { 502 for (i = 0; i < adev->mode_info.num_crtc; i++) {
425 r = dce_virtual_crtc_init(adev, i); 503 r = dce_virtual_crtc_init(adev, i);
426 if (r) 504 if (r)
427 return r; 505 return r;
506 r = dce_virtual_connector_encoder_init(adev, i);
507 if (r)
508 return r;
428 } 509 }
429 510
430 dce_virtual_get_connector_info(adev);
431 amdgpu_print_display_setup(adev->ddev);
432
433 drm_kms_helper_poll_init(adev->ddev); 511 drm_kms_helper_poll_init(adev->ddev);
434 512
435 adev->mode_info.mode_config_initialized = true; 513 adev->mode_info.mode_config_initialized = true;
@@ -496,7 +574,7 @@ static int dce_virtual_set_powergating_state(void *handle,
496 return 0; 574 return 0;
497} 575}
498 576
499const struct amd_ip_funcs dce_virtual_ip_funcs = { 577static const struct amd_ip_funcs dce_virtual_ip_funcs = {
500 .name = "dce_virtual", 578 .name = "dce_virtual",
501 .early_init = dce_virtual_early_init, 579 .early_init = dce_virtual_early_init,
502 .late_init = NULL, 580 .late_init = NULL,
@@ -526,8 +604,8 @@ static void dce_virtual_encoder_commit(struct drm_encoder *encoder)
526 604
527static void 605static void
528dce_virtual_encoder_mode_set(struct drm_encoder *encoder, 606dce_virtual_encoder_mode_set(struct drm_encoder *encoder,
529 struct drm_display_mode *mode, 607 struct drm_display_mode *mode,
530 struct drm_display_mode *adjusted_mode) 608 struct drm_display_mode *adjusted_mode)
531{ 609{
532 return; 610 return;
533} 611}
@@ -547,10 +625,6 @@ static bool dce_virtual_encoder_mode_fixup(struct drm_encoder *encoder,
547 const struct drm_display_mode *mode, 625 const struct drm_display_mode *mode,
548 struct drm_display_mode *adjusted_mode) 626 struct drm_display_mode *adjusted_mode)
549{ 627{
550
551 /* set the active encoder to connector routing */
552 amdgpu_encoder_set_active_device(encoder);
553
554 return true; 628 return true;
555} 629}
556 630
@@ -576,45 +650,40 @@ static const struct drm_encoder_funcs dce_virtual_encoder_funcs = {
576 .destroy = dce_virtual_encoder_destroy, 650 .destroy = dce_virtual_encoder_destroy,
577}; 651};
578 652
579static void dce_virtual_encoder_add(struct amdgpu_device *adev, 653static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
580 uint32_t encoder_enum, 654 int index)
581 uint32_t supported_device,
582 u16 caps)
583{ 655{
584 struct drm_device *dev = adev->ddev;
585 struct drm_encoder *encoder; 656 struct drm_encoder *encoder;
586 struct amdgpu_encoder *amdgpu_encoder; 657 struct drm_connector *connector;
587 658
588 /* see if we already added it */ 659 /* add a new encoder */
589 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 660 encoder = kzalloc(sizeof(struct drm_encoder), GFP_KERNEL);
590 amdgpu_encoder = to_amdgpu_encoder(encoder); 661 if (!encoder)
591 if (amdgpu_encoder->encoder_enum == encoder_enum) { 662 return -ENOMEM;
592 amdgpu_encoder->devices |= supported_device; 663 encoder->possible_crtcs = 1 << index;
593 return; 664 drm_encoder_init(adev->ddev, encoder, &dce_virtual_encoder_funcs,
594 } 665 DRM_MODE_ENCODER_VIRTUAL, NULL);
666 drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs);
595 667
668 connector = kzalloc(sizeof(struct drm_connector), GFP_KERNEL);
669 if (!connector) {
670 kfree(encoder);
671 return -ENOMEM;
596 } 672 }
597 673
598 /* add a new one */ 674 /* add a new connector */
599 amdgpu_encoder = kzalloc(sizeof(struct amdgpu_encoder), GFP_KERNEL); 675 drm_connector_init(adev->ddev, connector, &dce_virtual_connector_funcs,
600 if (!amdgpu_encoder) 676 DRM_MODE_CONNECTOR_VIRTUAL);
601 return; 677 drm_connector_helper_add(connector, &dce_virtual_connector_helper_funcs);
678 connector->display_info.subpixel_order = SubPixelHorizontalRGB;
679 connector->interlace_allowed = false;
680 connector->doublescan_allowed = false;
681 drm_connector_register(connector);
602 682
603 encoder = &amdgpu_encoder->base; 683 /* link them */
604 encoder->possible_crtcs = 0x1; 684 drm_mode_connector_attach_encoder(connector, encoder);
605 amdgpu_encoder->enc_priv = NULL; 685
606 amdgpu_encoder->encoder_enum = encoder_enum; 686 return 0;
607 amdgpu_encoder->encoder_id = (encoder_enum & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
608 amdgpu_encoder->devices = supported_device;
609 amdgpu_encoder->rmx_type = RMX_OFF;
610 amdgpu_encoder->underscan_type = UNDERSCAN_OFF;
611 amdgpu_encoder->is_ext_encoder = false;
612 amdgpu_encoder->caps = caps;
613
614 drm_encoder_init(dev, encoder, &dce_virtual_encoder_funcs,
615 DRM_MODE_ENCODER_VIRTUAL, NULL);
616 drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs);
617 DRM_INFO("[FM]encoder: %d is VIRTUAL\n", amdgpu_encoder->encoder_id);
618} 687}
619 688
620static const struct amdgpu_display_funcs dce_virtual_display_funcs = { 689static const struct amdgpu_display_funcs dce_virtual_display_funcs = {
@@ -630,8 +699,8 @@ static const struct amdgpu_display_funcs dce_virtual_display_funcs = {
630 .hpd_get_gpio_reg = &dce_virtual_hpd_get_gpio_reg, 699 .hpd_get_gpio_reg = &dce_virtual_hpd_get_gpio_reg,
631 .page_flip = &dce_virtual_page_flip, 700 .page_flip = &dce_virtual_page_flip,
632 .page_flip_get_scanoutpos = &dce_virtual_crtc_get_scanoutpos, 701 .page_flip_get_scanoutpos = &dce_virtual_crtc_get_scanoutpos,
633 .add_encoder = &dce_virtual_encoder_add, 702 .add_encoder = NULL,
634 .add_connector = &amdgpu_connector_add, 703 .add_connector = NULL,
635 .stop_mc_access = &dce_virtual_stop_mc_access, 704 .stop_mc_access = &dce_virtual_stop_mc_access,
636 .resume_mc_access = &dce_virtual_resume_mc_access, 705 .resume_mc_access = &dce_virtual_resume_mc_access,
637}; 706};
@@ -642,107 +711,13 @@ static void dce_virtual_set_display_funcs(struct amdgpu_device *adev)
642 adev->mode_info.funcs = &dce_virtual_display_funcs; 711 adev->mode_info.funcs = &dce_virtual_display_funcs;
643} 712}
644 713
645static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer) 714static int dce_virtual_pageflip(struct amdgpu_device *adev,
646{ 715 unsigned crtc_id)
647 struct amdgpu_mode_info *mode_info = container_of(vblank_timer, struct amdgpu_mode_info ,vblank_timer);
648 struct amdgpu_device *adev = container_of(mode_info, struct amdgpu_device ,mode_info);
649 unsigned crtc = 0;
650 drm_handle_vblank(adev->ddev, crtc);
651 dce_virtual_pageflip_irq(adev, NULL, NULL);
652 hrtimer_start(vblank_timer, ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD), HRTIMER_MODE_REL);
653 return HRTIMER_NORESTART;
654}
655
656static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev,
657 int crtc,
658 enum amdgpu_interrupt_state state)
659{
660 if (crtc >= adev->mode_info.num_crtc) {
661 DRM_DEBUG("invalid crtc %d\n", crtc);
662 return;
663 }
664
665 if (state && !adev->mode_info.vsync_timer_enabled) {
666 DRM_DEBUG("Enable software vsync timer\n");
667 hrtimer_init(&adev->mode_info.vblank_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
668 hrtimer_set_expires(&adev->mode_info.vblank_timer, ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD));
669 adev->mode_info.vblank_timer.function = dce_virtual_vblank_timer_handle;
670 hrtimer_start(&adev->mode_info.vblank_timer, ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD), HRTIMER_MODE_REL);
671 } else if (!state && adev->mode_info.vsync_timer_enabled) {
672 DRM_DEBUG("Disable software vsync timer\n");
673 hrtimer_cancel(&adev->mode_info.vblank_timer);
674 }
675
676 adev->mode_info.vsync_timer_enabled = state;
677 DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state);
678}
679
680
681static int dce_virtual_set_crtc_irq_state(struct amdgpu_device *adev,
682 struct amdgpu_irq_src *source,
683 unsigned type,
684 enum amdgpu_interrupt_state state)
685{
686 switch (type) {
687 case AMDGPU_CRTC_IRQ_VBLANK1:
688 dce_virtual_set_crtc_vblank_interrupt_state(adev, 0, state);
689 break;
690 default:
691 break;
692 }
693 return 0;
694}
695
696static void dce_virtual_crtc_vblank_int_ack(struct amdgpu_device *adev,
697 int crtc)
698{
699 if (crtc >= adev->mode_info.num_crtc) {
700 DRM_DEBUG("invalid crtc %d\n", crtc);
701 return;
702 }
703}
704
705static int dce_virtual_crtc_irq(struct amdgpu_device *adev,
706 struct amdgpu_irq_src *source,
707 struct amdgpu_iv_entry *entry)
708{
709 unsigned crtc = 0;
710 unsigned irq_type = AMDGPU_CRTC_IRQ_VBLANK1;
711
712 dce_virtual_crtc_vblank_int_ack(adev, crtc);
713
714 if (amdgpu_irq_enabled(adev, source, irq_type)) {
715 drm_handle_vblank(adev->ddev, crtc);
716 }
717 dce_virtual_pageflip_irq(adev, NULL, NULL);
718 DRM_DEBUG("IH: D%d vblank\n", crtc + 1);
719 return 0;
720}
721
722static int dce_virtual_set_pageflip_irq_state(struct amdgpu_device *adev,
723 struct amdgpu_irq_src *src,
724 unsigned type,
725 enum amdgpu_interrupt_state state)
726{
727 if (type >= adev->mode_info.num_crtc) {
728 DRM_ERROR("invalid pageflip crtc %d\n", type);
729 return -EINVAL;
730 }
731 DRM_DEBUG("[FM]set pageflip irq type %d state %d\n", type, state);
732
733 return 0;
734}
735
736static int dce_virtual_pageflip_irq(struct amdgpu_device *adev,
737 struct amdgpu_irq_src *source,
738 struct amdgpu_iv_entry *entry)
739{ 716{
740 unsigned long flags; 717 unsigned long flags;
741 unsigned crtc_id = 0;
742 struct amdgpu_crtc *amdgpu_crtc; 718 struct amdgpu_crtc *amdgpu_crtc;
743 struct amdgpu_flip_work *works; 719 struct amdgpu_flip_work *works;
744 720
745 crtc_id = 0;
746 amdgpu_crtc = adev->mode_info.crtcs[crtc_id]; 721 amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
747 722
748 if (crtc_id >= adev->mode_info.num_crtc) { 723 if (crtc_id >= adev->mode_info.num_crtc) {
@@ -781,22 +756,79 @@ static int dce_virtual_pageflip_irq(struct amdgpu_device *adev,
781 return 0; 756 return 0;
782} 757}
783 758
759static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer)
760{
761 struct amdgpu_crtc *amdgpu_crtc = container_of(vblank_timer,
762 struct amdgpu_crtc, vblank_timer);
763 struct drm_device *ddev = amdgpu_crtc->base.dev;
764 struct amdgpu_device *adev = ddev->dev_private;
765
766 drm_handle_vblank(ddev, amdgpu_crtc->crtc_id);
767 dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id);
768 hrtimer_start(vblank_timer, ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD),
769 HRTIMER_MODE_REL);
770
771 return HRTIMER_NORESTART;
772}
773
774static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev,
775 int crtc,
776 enum amdgpu_interrupt_state state)
777{
778 if (crtc >= adev->mode_info.num_crtc) {
779 DRM_DEBUG("invalid crtc %d\n", crtc);
780 return;
781 }
782
783 if (state && !adev->mode_info.crtcs[crtc]->vsync_timer_enabled) {
784 DRM_DEBUG("Enable software vsync timer\n");
785 hrtimer_init(&adev->mode_info.crtcs[crtc]->vblank_timer,
786 CLOCK_MONOTONIC, HRTIMER_MODE_REL);
787 hrtimer_set_expires(&adev->mode_info.crtcs[crtc]->vblank_timer,
788 ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD));
789 adev->mode_info.crtcs[crtc]->vblank_timer.function =
790 dce_virtual_vblank_timer_handle;
791 hrtimer_start(&adev->mode_info.crtcs[crtc]->vblank_timer,
792 ktime_set(0, DCE_VIRTUAL_VBLANK_PERIOD), HRTIMER_MODE_REL);
793 } else if (!state && adev->mode_info.crtcs[crtc]->vsync_timer_enabled) {
794 DRM_DEBUG("Disable software vsync timer\n");
795 hrtimer_cancel(&adev->mode_info.crtcs[crtc]->vblank_timer);
796 }
797
798 adev->mode_info.crtcs[crtc]->vsync_timer_enabled = state;
799 DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state);
800}
801
802
803static int dce_virtual_set_crtc_irq_state(struct amdgpu_device *adev,
804 struct amdgpu_irq_src *source,
805 unsigned type,
806 enum amdgpu_interrupt_state state)
807{
808 if (type > AMDGPU_CRTC_IRQ_VBLANK6)
809 return -EINVAL;
810
811 dce_virtual_set_crtc_vblank_interrupt_state(adev, type, state);
812
813 return 0;
814}
815
784static const struct amdgpu_irq_src_funcs dce_virtual_crtc_irq_funcs = { 816static const struct amdgpu_irq_src_funcs dce_virtual_crtc_irq_funcs = {
785 .set = dce_virtual_set_crtc_irq_state, 817 .set = dce_virtual_set_crtc_irq_state,
786 .process = dce_virtual_crtc_irq, 818 .process = NULL,
787};
788
789static const struct amdgpu_irq_src_funcs dce_virtual_pageflip_irq_funcs = {
790 .set = dce_virtual_set_pageflip_irq_state,
791 .process = dce_virtual_pageflip_irq,
792}; 819};
793 820
794static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev) 821static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev)
795{ 822{
796 adev->crtc_irq.num_types = AMDGPU_CRTC_IRQ_LAST; 823 adev->crtc_irq.num_types = AMDGPU_CRTC_IRQ_LAST;
797 adev->crtc_irq.funcs = &dce_virtual_crtc_irq_funcs; 824 adev->crtc_irq.funcs = &dce_virtual_crtc_irq_funcs;
798
799 adev->pageflip_irq.num_types = AMDGPU_PAGEFLIP_IRQ_LAST;
800 adev->pageflip_irq.funcs = &dce_virtual_pageflip_irq_funcs;
801} 825}
802 826
827const struct amdgpu_ip_block_version dce_virtual_ip_block =
828{
829 .type = AMD_IP_BLOCK_TYPE_DCE,
830 .major = 1,
831 .minor = 0,
832 .rev = 0,
833 .funcs = &dce_virtual_ip_funcs,
834};