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