Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.6-rc3 761 lines 20 kB view raw
1/* 2 * Copyright 2014 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 */ 23 24#include <drm/drm_vblank.h> 25 26#include "amdgpu.h" 27#include "amdgpu_pm.h" 28#include "amdgpu_i2c.h" 29#include "atom.h" 30#include "amdgpu_pll.h" 31#include "amdgpu_connectors.h" 32#ifdef CONFIG_DRM_AMDGPU_SI 33#include "dce_v6_0.h" 34#endif 35#ifdef CONFIG_DRM_AMDGPU_CIK 36#include "dce_v8_0.h" 37#endif 38#include "dce_v10_0.h" 39#include "dce_v11_0.h" 40#include "dce_virtual.h" 41#include "ivsrcid/ivsrcid_vislands30.h" 42 43#define DCE_VIRTUAL_VBLANK_PERIOD 16666666 44 45 46static void dce_virtual_set_display_funcs(struct amdgpu_device *adev); 47static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev); 48static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev, 49 int index); 50static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev, 51 int crtc, 52 enum amdgpu_interrupt_state state); 53 54static u32 dce_virtual_vblank_get_counter(struct amdgpu_device *adev, int crtc) 55{ 56 return 0; 57} 58 59static void dce_virtual_page_flip(struct amdgpu_device *adev, 60 int crtc_id, u64 crtc_base, bool async) 61{ 62 return; 63} 64 65static int dce_virtual_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc, 66 u32 *vbl, u32 *position) 67{ 68 *vbl = 0; 69 *position = 0; 70 71 return -EINVAL; 72} 73 74static bool dce_virtual_hpd_sense(struct amdgpu_device *adev, 75 enum amdgpu_hpd_id hpd) 76{ 77 return true; 78} 79 80static void dce_virtual_hpd_set_polarity(struct amdgpu_device *adev, 81 enum amdgpu_hpd_id hpd) 82{ 83 return; 84} 85 86static u32 dce_virtual_hpd_get_gpio_reg(struct amdgpu_device *adev) 87{ 88 return 0; 89} 90 91/** 92 * dce_virtual_bandwidth_update - program display watermarks 93 * 94 * @adev: amdgpu_device pointer 95 * 96 * Calculate and program the display watermarks and line 97 * buffer allocation (CIK). 98 */ 99static void dce_virtual_bandwidth_update(struct amdgpu_device *adev) 100{ 101 return; 102} 103 104static int dce_virtual_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, 105 u16 *green, u16 *blue, uint32_t size, 106 struct drm_modeset_acquire_ctx *ctx) 107{ 108 return 0; 109} 110 111static void dce_virtual_crtc_destroy(struct drm_crtc *crtc) 112{ 113 struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); 114 115 drm_crtc_cleanup(crtc); 116 kfree(amdgpu_crtc); 117} 118 119static const struct drm_crtc_funcs dce_virtual_crtc_funcs = { 120 .cursor_set2 = NULL, 121 .cursor_move = NULL, 122 .gamma_set = dce_virtual_crtc_gamma_set, 123 .set_config = amdgpu_display_crtc_set_config, 124 .destroy = dce_virtual_crtc_destroy, 125 .page_flip_target = amdgpu_display_crtc_page_flip_target, 126}; 127 128static void dce_virtual_crtc_dpms(struct drm_crtc *crtc, int mode) 129{ 130 struct drm_device *dev = crtc->dev; 131 struct amdgpu_device *adev = dev->dev_private; 132 struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); 133 unsigned type; 134 135 if (amdgpu_sriov_vf(adev)) 136 return; 137 138 switch (mode) { 139 case DRM_MODE_DPMS_ON: 140 amdgpu_crtc->enabled = true; 141 /* Make sure VBLANK interrupts are still enabled */ 142 type = amdgpu_display_crtc_idx_to_irq_type(adev, 143 amdgpu_crtc->crtc_id); 144 amdgpu_irq_update(adev, &adev->crtc_irq, type); 145 drm_crtc_vblank_on(crtc); 146 break; 147 case DRM_MODE_DPMS_STANDBY: 148 case DRM_MODE_DPMS_SUSPEND: 149 case DRM_MODE_DPMS_OFF: 150 drm_crtc_vblank_off(crtc); 151 amdgpu_crtc->enabled = false; 152 break; 153 } 154} 155 156 157static void dce_virtual_crtc_prepare(struct drm_crtc *crtc) 158{ 159 dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); 160} 161 162static void dce_virtual_crtc_commit(struct drm_crtc *crtc) 163{ 164 dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_ON); 165} 166 167static void dce_virtual_crtc_disable(struct drm_crtc *crtc) 168{ 169 struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); 170 171 dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); 172 173 amdgpu_crtc->pll_id = ATOM_PPLL_INVALID; 174 amdgpu_crtc->encoder = NULL; 175 amdgpu_crtc->connector = NULL; 176} 177 178static int dce_virtual_crtc_mode_set(struct drm_crtc *crtc, 179 struct drm_display_mode *mode, 180 struct drm_display_mode *adjusted_mode, 181 int x, int y, struct drm_framebuffer *old_fb) 182{ 183 struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); 184 185 /* update the hw version fpr dpm */ 186 amdgpu_crtc->hw_mode = *adjusted_mode; 187 188 return 0; 189} 190 191static bool dce_virtual_crtc_mode_fixup(struct drm_crtc *crtc, 192 const struct drm_display_mode *mode, 193 struct drm_display_mode *adjusted_mode) 194{ 195 return true; 196} 197 198 199static int dce_virtual_crtc_set_base(struct drm_crtc *crtc, int x, int y, 200 struct drm_framebuffer *old_fb) 201{ 202 return 0; 203} 204 205static int dce_virtual_crtc_set_base_atomic(struct drm_crtc *crtc, 206 struct drm_framebuffer *fb, 207 int x, int y, enum mode_set_atomic state) 208{ 209 return 0; 210} 211 212static const struct drm_crtc_helper_funcs dce_virtual_crtc_helper_funcs = { 213 .dpms = dce_virtual_crtc_dpms, 214 .mode_fixup = dce_virtual_crtc_mode_fixup, 215 .mode_set = dce_virtual_crtc_mode_set, 216 .mode_set_base = dce_virtual_crtc_set_base, 217 .mode_set_base_atomic = dce_virtual_crtc_set_base_atomic, 218 .prepare = dce_virtual_crtc_prepare, 219 .commit = dce_virtual_crtc_commit, 220 .disable = dce_virtual_crtc_disable, 221}; 222 223static int dce_virtual_crtc_init(struct amdgpu_device *adev, int index) 224{ 225 struct amdgpu_crtc *amdgpu_crtc; 226 227 amdgpu_crtc = kzalloc(sizeof(struct amdgpu_crtc) + 228 (AMDGPUFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL); 229 if (amdgpu_crtc == NULL) 230 return -ENOMEM; 231 232 drm_crtc_init(adev->ddev, &amdgpu_crtc->base, &dce_virtual_crtc_funcs); 233 234 drm_mode_crtc_set_gamma_size(&amdgpu_crtc->base, 256); 235 amdgpu_crtc->crtc_id = index; 236 adev->mode_info.crtcs[index] = amdgpu_crtc; 237 238 amdgpu_crtc->pll_id = ATOM_PPLL_INVALID; 239 amdgpu_crtc->encoder = NULL; 240 amdgpu_crtc->connector = NULL; 241 amdgpu_crtc->vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE; 242 drm_crtc_helper_add(&amdgpu_crtc->base, &dce_virtual_crtc_helper_funcs); 243 244 return 0; 245} 246 247static int dce_virtual_early_init(void *handle) 248{ 249 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 250 251 dce_virtual_set_display_funcs(adev); 252 dce_virtual_set_irq_funcs(adev); 253 254 adev->mode_info.num_hpd = 1; 255 adev->mode_info.num_dig = 1; 256 return 0; 257} 258 259static struct drm_encoder * 260dce_virtual_encoder(struct drm_connector *connector) 261{ 262 struct drm_encoder *encoder; 263 264 drm_connector_for_each_possible_encoder(connector, encoder) { 265 if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL) 266 return encoder; 267 } 268 269 /* pick the first one */ 270 drm_connector_for_each_possible_encoder(connector, encoder) 271 return encoder; 272 273 return NULL; 274} 275 276static int dce_virtual_get_modes(struct drm_connector *connector) 277{ 278 struct drm_device *dev = connector->dev; 279 struct drm_display_mode *mode = NULL; 280 unsigned i; 281 static const struct mode_size { 282 int w; 283 int h; 284 } common_modes[17] = { 285 { 640, 480}, 286 { 720, 480}, 287 { 800, 600}, 288 { 848, 480}, 289 {1024, 768}, 290 {1152, 768}, 291 {1280, 720}, 292 {1280, 800}, 293 {1280, 854}, 294 {1280, 960}, 295 {1280, 1024}, 296 {1440, 900}, 297 {1400, 1050}, 298 {1680, 1050}, 299 {1600, 1200}, 300 {1920, 1080}, 301 {1920, 1200} 302 }; 303 304 for (i = 0; i < 17; i++) { 305 mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false); 306 drm_mode_probed_add(connector, mode); 307 } 308 309 return 0; 310} 311 312static enum drm_mode_status dce_virtual_mode_valid(struct drm_connector *connector, 313 struct drm_display_mode *mode) 314{ 315 return MODE_OK; 316} 317 318static int 319dce_virtual_dpms(struct drm_connector *connector, int mode) 320{ 321 return 0; 322} 323 324static int 325dce_virtual_set_property(struct drm_connector *connector, 326 struct drm_property *property, 327 uint64_t val) 328{ 329 return 0; 330} 331 332static void dce_virtual_destroy(struct drm_connector *connector) 333{ 334 drm_connector_unregister(connector); 335 drm_connector_cleanup(connector); 336 kfree(connector); 337} 338 339static void dce_virtual_force(struct drm_connector *connector) 340{ 341 return; 342} 343 344static const struct drm_connector_helper_funcs dce_virtual_connector_helper_funcs = { 345 .get_modes = dce_virtual_get_modes, 346 .mode_valid = dce_virtual_mode_valid, 347 .best_encoder = dce_virtual_encoder, 348}; 349 350static const struct drm_connector_funcs dce_virtual_connector_funcs = { 351 .dpms = dce_virtual_dpms, 352 .fill_modes = drm_helper_probe_single_connector_modes, 353 .set_property = dce_virtual_set_property, 354 .destroy = dce_virtual_destroy, 355 .force = dce_virtual_force, 356}; 357 358static int dce_virtual_sw_init(void *handle) 359{ 360 int r, i; 361 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 362 363 r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, VISLANDS30_IV_SRCID_SMU_DISP_TIMER2_TRIGGER, &adev->crtc_irq); 364 if (r) 365 return r; 366 367 adev->ddev->max_vblank_count = 0; 368 369 adev->ddev->mode_config.funcs = &amdgpu_mode_funcs; 370 371 adev->ddev->mode_config.max_width = 16384; 372 adev->ddev->mode_config.max_height = 16384; 373 374 adev->ddev->mode_config.preferred_depth = 24; 375 adev->ddev->mode_config.prefer_shadow = 1; 376 377 adev->ddev->mode_config.fb_base = adev->gmc.aper_base; 378 379 r = amdgpu_display_modeset_create_props(adev); 380 if (r) 381 return r; 382 383 adev->ddev->mode_config.max_width = 16384; 384 adev->ddev->mode_config.max_height = 16384; 385 386 /* allocate crtcs, encoders, connectors */ 387 for (i = 0; i < adev->mode_info.num_crtc; i++) { 388 r = dce_virtual_crtc_init(adev, i); 389 if (r) 390 return r; 391 r = dce_virtual_connector_encoder_init(adev, i); 392 if (r) 393 return r; 394 } 395 396 drm_kms_helper_poll_init(adev->ddev); 397 398 adev->mode_info.mode_config_initialized = true; 399 return 0; 400} 401 402static int dce_virtual_sw_fini(void *handle) 403{ 404 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 405 406 kfree(adev->mode_info.bios_hardcoded_edid); 407 408 drm_kms_helper_poll_fini(adev->ddev); 409 410 drm_mode_config_cleanup(adev->ddev); 411 /* clear crtcs pointer to avoid dce irq finish routine access freed data */ 412 memset(adev->mode_info.crtcs, 0, sizeof(adev->mode_info.crtcs[0]) * AMDGPU_MAX_CRTCS); 413 adev->mode_info.mode_config_initialized = false; 414 return 0; 415} 416 417static int dce_virtual_hw_init(void *handle) 418{ 419 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 420 421 switch (adev->asic_type) { 422#ifdef CONFIG_DRM_AMDGPU_SI 423 case CHIP_TAHITI: 424 case CHIP_PITCAIRN: 425 case CHIP_VERDE: 426 case CHIP_OLAND: 427 dce_v6_0_disable_dce(adev); 428 break; 429#endif 430#ifdef CONFIG_DRM_AMDGPU_CIK 431 case CHIP_BONAIRE: 432 case CHIP_HAWAII: 433 case CHIP_KAVERI: 434 case CHIP_KABINI: 435 case CHIP_MULLINS: 436 dce_v8_0_disable_dce(adev); 437 break; 438#endif 439 case CHIP_FIJI: 440 case CHIP_TONGA: 441 dce_v10_0_disable_dce(adev); 442 break; 443 case CHIP_CARRIZO: 444 case CHIP_STONEY: 445 case CHIP_POLARIS10: 446 case CHIP_POLARIS11: 447 case CHIP_VEGAM: 448 dce_v11_0_disable_dce(adev); 449 break; 450 case CHIP_TOPAZ: 451#ifdef CONFIG_DRM_AMDGPU_SI 452 case CHIP_HAINAN: 453#endif 454 /* no DCE */ 455 break; 456 default: 457 break; 458 } 459 return 0; 460} 461 462static int dce_virtual_hw_fini(void *handle) 463{ 464 struct amdgpu_device *adev = (struct amdgpu_device *)handle; 465 int i = 0; 466 467 for (i = 0; i<adev->mode_info.num_crtc; i++) 468 if (adev->mode_info.crtcs[i]) 469 dce_virtual_set_crtc_vblank_interrupt_state(adev, i, AMDGPU_IRQ_STATE_DISABLE); 470 471 return 0; 472} 473 474static int dce_virtual_suspend(void *handle) 475{ 476 return dce_virtual_hw_fini(handle); 477} 478 479static int dce_virtual_resume(void *handle) 480{ 481 return dce_virtual_hw_init(handle); 482} 483 484static bool dce_virtual_is_idle(void *handle) 485{ 486 return true; 487} 488 489static int dce_virtual_wait_for_idle(void *handle) 490{ 491 return 0; 492} 493 494static int dce_virtual_soft_reset(void *handle) 495{ 496 return 0; 497} 498 499static int dce_virtual_set_clockgating_state(void *handle, 500 enum amd_clockgating_state state) 501{ 502 return 0; 503} 504 505static int dce_virtual_set_powergating_state(void *handle, 506 enum amd_powergating_state state) 507{ 508 return 0; 509} 510 511static const struct amd_ip_funcs dce_virtual_ip_funcs = { 512 .name = "dce_virtual", 513 .early_init = dce_virtual_early_init, 514 .late_init = NULL, 515 .sw_init = dce_virtual_sw_init, 516 .sw_fini = dce_virtual_sw_fini, 517 .hw_init = dce_virtual_hw_init, 518 .hw_fini = dce_virtual_hw_fini, 519 .suspend = dce_virtual_suspend, 520 .resume = dce_virtual_resume, 521 .is_idle = dce_virtual_is_idle, 522 .wait_for_idle = dce_virtual_wait_for_idle, 523 .soft_reset = dce_virtual_soft_reset, 524 .set_clockgating_state = dce_virtual_set_clockgating_state, 525 .set_powergating_state = dce_virtual_set_powergating_state, 526}; 527 528/* these are handled by the primary encoders */ 529static void dce_virtual_encoder_prepare(struct drm_encoder *encoder) 530{ 531 return; 532} 533 534static void dce_virtual_encoder_commit(struct drm_encoder *encoder) 535{ 536 return; 537} 538 539static void 540dce_virtual_encoder_mode_set(struct drm_encoder *encoder, 541 struct drm_display_mode *mode, 542 struct drm_display_mode *adjusted_mode) 543{ 544 return; 545} 546 547static void dce_virtual_encoder_disable(struct drm_encoder *encoder) 548{ 549 return; 550} 551 552static void 553dce_virtual_encoder_dpms(struct drm_encoder *encoder, int mode) 554{ 555 return; 556} 557 558static bool dce_virtual_encoder_mode_fixup(struct drm_encoder *encoder, 559 const struct drm_display_mode *mode, 560 struct drm_display_mode *adjusted_mode) 561{ 562 return true; 563} 564 565static const struct drm_encoder_helper_funcs dce_virtual_encoder_helper_funcs = { 566 .dpms = dce_virtual_encoder_dpms, 567 .mode_fixup = dce_virtual_encoder_mode_fixup, 568 .prepare = dce_virtual_encoder_prepare, 569 .mode_set = dce_virtual_encoder_mode_set, 570 .commit = dce_virtual_encoder_commit, 571 .disable = dce_virtual_encoder_disable, 572}; 573 574static void dce_virtual_encoder_destroy(struct drm_encoder *encoder) 575{ 576 drm_encoder_cleanup(encoder); 577 kfree(encoder); 578} 579 580static const struct drm_encoder_funcs dce_virtual_encoder_funcs = { 581 .destroy = dce_virtual_encoder_destroy, 582}; 583 584static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev, 585 int index) 586{ 587 struct drm_encoder *encoder; 588 struct drm_connector *connector; 589 590 /* add a new encoder */ 591 encoder = kzalloc(sizeof(struct drm_encoder), GFP_KERNEL); 592 if (!encoder) 593 return -ENOMEM; 594 encoder->possible_crtcs = 1 << index; 595 drm_encoder_init(adev->ddev, encoder, &dce_virtual_encoder_funcs, 596 DRM_MODE_ENCODER_VIRTUAL, NULL); 597 drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs); 598 599 connector = kzalloc(sizeof(struct drm_connector), GFP_KERNEL); 600 if (!connector) { 601 kfree(encoder); 602 return -ENOMEM; 603 } 604 605 /* add a new connector */ 606 drm_connector_init(adev->ddev, connector, &dce_virtual_connector_funcs, 607 DRM_MODE_CONNECTOR_VIRTUAL); 608 drm_connector_helper_add(connector, &dce_virtual_connector_helper_funcs); 609 connector->display_info.subpixel_order = SubPixelHorizontalRGB; 610 connector->interlace_allowed = false; 611 connector->doublescan_allowed = false; 612 drm_connector_register(connector); 613 614 /* link them */ 615 drm_connector_attach_encoder(connector, encoder); 616 617 return 0; 618} 619 620static const struct amdgpu_display_funcs dce_virtual_display_funcs = { 621 .bandwidth_update = &dce_virtual_bandwidth_update, 622 .vblank_get_counter = &dce_virtual_vblank_get_counter, 623 .backlight_set_level = NULL, 624 .backlight_get_level = NULL, 625 .hpd_sense = &dce_virtual_hpd_sense, 626 .hpd_set_polarity = &dce_virtual_hpd_set_polarity, 627 .hpd_get_gpio_reg = &dce_virtual_hpd_get_gpio_reg, 628 .page_flip = &dce_virtual_page_flip, 629 .page_flip_get_scanoutpos = &dce_virtual_crtc_get_scanoutpos, 630 .add_encoder = NULL, 631 .add_connector = NULL, 632}; 633 634static void dce_virtual_set_display_funcs(struct amdgpu_device *adev) 635{ 636 adev->mode_info.funcs = &dce_virtual_display_funcs; 637} 638 639static int dce_virtual_pageflip(struct amdgpu_device *adev, 640 unsigned crtc_id) 641{ 642 unsigned long flags; 643 struct amdgpu_crtc *amdgpu_crtc; 644 struct amdgpu_flip_work *works; 645 646 amdgpu_crtc = adev->mode_info.crtcs[crtc_id]; 647 648 if (crtc_id >= adev->mode_info.num_crtc) { 649 DRM_ERROR("invalid pageflip crtc %d\n", crtc_id); 650 return -EINVAL; 651 } 652 653 /* IRQ could occur when in initial stage */ 654 if (amdgpu_crtc == NULL) 655 return 0; 656 657 spin_lock_irqsave(&adev->ddev->event_lock, flags); 658 works = amdgpu_crtc->pflip_works; 659 if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) { 660 DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != " 661 "AMDGPU_FLIP_SUBMITTED(%d)\n", 662 amdgpu_crtc->pflip_status, 663 AMDGPU_FLIP_SUBMITTED); 664 spin_unlock_irqrestore(&adev->ddev->event_lock, flags); 665 return 0; 666 } 667 668 /* page flip completed. clean up */ 669 amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE; 670 amdgpu_crtc->pflip_works = NULL; 671 672 /* wakeup usersapce */ 673 if (works->event) 674 drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event); 675 676 spin_unlock_irqrestore(&adev->ddev->event_lock, flags); 677 678 drm_crtc_vblank_put(&amdgpu_crtc->base); 679 amdgpu_bo_unref(&works->old_abo); 680 kfree(works->shared); 681 kfree(works); 682 683 return 0; 684} 685 686static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer) 687{ 688 struct amdgpu_crtc *amdgpu_crtc = container_of(vblank_timer, 689 struct amdgpu_crtc, vblank_timer); 690 struct drm_device *ddev = amdgpu_crtc->base.dev; 691 struct amdgpu_device *adev = ddev->dev_private; 692 693 drm_handle_vblank(ddev, amdgpu_crtc->crtc_id); 694 dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id); 695 hrtimer_start(vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD, 696 HRTIMER_MODE_REL); 697 698 return HRTIMER_NORESTART; 699} 700 701static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev, 702 int crtc, 703 enum amdgpu_interrupt_state state) 704{ 705 if (crtc >= adev->mode_info.num_crtc || !adev->mode_info.crtcs[crtc]) { 706 DRM_DEBUG("invalid crtc %d\n", crtc); 707 return; 708 } 709 710 if (state && !adev->mode_info.crtcs[crtc]->vsync_timer_enabled) { 711 DRM_DEBUG("Enable software vsync timer\n"); 712 hrtimer_init(&adev->mode_info.crtcs[crtc]->vblank_timer, 713 CLOCK_MONOTONIC, HRTIMER_MODE_REL); 714 hrtimer_set_expires(&adev->mode_info.crtcs[crtc]->vblank_timer, 715 DCE_VIRTUAL_VBLANK_PERIOD); 716 adev->mode_info.crtcs[crtc]->vblank_timer.function = 717 dce_virtual_vblank_timer_handle; 718 hrtimer_start(&adev->mode_info.crtcs[crtc]->vblank_timer, 719 DCE_VIRTUAL_VBLANK_PERIOD, HRTIMER_MODE_REL); 720 } else if (!state && adev->mode_info.crtcs[crtc]->vsync_timer_enabled) { 721 DRM_DEBUG("Disable software vsync timer\n"); 722 hrtimer_cancel(&adev->mode_info.crtcs[crtc]->vblank_timer); 723 } 724 725 adev->mode_info.crtcs[crtc]->vsync_timer_enabled = state; 726 DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state); 727} 728 729 730static int dce_virtual_set_crtc_irq_state(struct amdgpu_device *adev, 731 struct amdgpu_irq_src *source, 732 unsigned type, 733 enum amdgpu_interrupt_state state) 734{ 735 if (type > AMDGPU_CRTC_IRQ_VBLANK6) 736 return -EINVAL; 737 738 dce_virtual_set_crtc_vblank_interrupt_state(adev, type, state); 739 740 return 0; 741} 742 743static const struct amdgpu_irq_src_funcs dce_virtual_crtc_irq_funcs = { 744 .set = dce_virtual_set_crtc_irq_state, 745 .process = NULL, 746}; 747 748static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev) 749{ 750 adev->crtc_irq.num_types = AMDGPU_CRTC_IRQ_VBLANK6 + 1; 751 adev->crtc_irq.funcs = &dce_virtual_crtc_irq_funcs; 752} 753 754const struct amdgpu_ip_block_version dce_virtual_ip_block = 755{ 756 .type = AMD_IP_BLOCK_TYPE_DCE, 757 .major = 1, 758 .minor = 0, 759 .rev = 0, 760 .funcs = &dce_virtual_ip_funcs, 761};