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
  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        int i;
 264
 265        drm_connector_for_each_possible_encoder(connector, encoder, i) {
 266                if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
 267                        return encoder;
 268        }
 269
 270        /* pick the first one */
 271        drm_connector_for_each_possible_encoder(connector, encoder, i)
 272                return encoder;
 273
 274        return NULL;
 275}
 276
 277static int dce_virtual_get_modes(struct drm_connector *connector)
 278{
 279        struct drm_device *dev = connector->dev;
 280        struct drm_display_mode *mode = NULL;
 281        unsigned i;
 282        static const struct mode_size {
 283                int w;
 284                int h;
 285        } common_modes[17] = {
 286                { 640,  480},
 287                { 720,  480},
 288                { 800,  600},
 289                { 848,  480},
 290                {1024,  768},
 291                {1152,  768},
 292                {1280,  720},
 293                {1280,  800},
 294                {1280,  854},
 295                {1280,  960},
 296                {1280, 1024},
 297                {1440,  900},
 298                {1400, 1050},
 299                {1680, 1050},
 300                {1600, 1200},
 301                {1920, 1080},
 302                {1920, 1200}
 303        };
 304
 305        for (i = 0; i < 17; i++) {
 306                mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
 307                drm_mode_probed_add(connector, mode);
 308        }
 309
 310        return 0;
 311}
 312
 313static enum drm_mode_status dce_virtual_mode_valid(struct drm_connector *connector,
 314                                  struct drm_display_mode *mode)
 315{
 316        return MODE_OK;
 317}
 318
 319static int
 320dce_virtual_dpms(struct drm_connector *connector, int mode)
 321{
 322        return 0;
 323}
 324
 325static int
 326dce_virtual_set_property(struct drm_connector *connector,
 327                         struct drm_property *property,
 328                         uint64_t val)
 329{
 330        return 0;
 331}
 332
 333static void dce_virtual_destroy(struct drm_connector *connector)
 334{
 335        drm_connector_unregister(connector);
 336        drm_connector_cleanup(connector);
 337        kfree(connector);
 338}
 339
 340static void dce_virtual_force(struct drm_connector *connector)
 341{
 342        return;
 343}
 344
 345static const struct drm_connector_helper_funcs dce_virtual_connector_helper_funcs = {
 346        .get_modes = dce_virtual_get_modes,
 347        .mode_valid = dce_virtual_mode_valid,
 348        .best_encoder = dce_virtual_encoder,
 349};
 350
 351static const struct drm_connector_funcs dce_virtual_connector_funcs = {
 352        .dpms = dce_virtual_dpms,
 353        .fill_modes = drm_helper_probe_single_connector_modes,
 354        .set_property = dce_virtual_set_property,
 355        .destroy = dce_virtual_destroy,
 356        .force = dce_virtual_force,
 357};
 358
 359static int dce_virtual_sw_init(void *handle)
 360{
 361        int r, i;
 362        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 363
 364        r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, VISLANDS30_IV_SRCID_SMU_DISP_TIMER2_TRIGGER, &adev->crtc_irq);
 365        if (r)
 366                return r;
 367
 368        adev->ddev->max_vblank_count = 0;
 369
 370        adev->ddev->mode_config.funcs = &amdgpu_mode_funcs;
 371
 372        adev->ddev->mode_config.max_width = 16384;
 373        adev->ddev->mode_config.max_height = 16384;
 374
 375        adev->ddev->mode_config.preferred_depth = 24;
 376        adev->ddev->mode_config.prefer_shadow = 1;
 377
 378        adev->ddev->mode_config.fb_base = adev->gmc.aper_base;
 379
 380        r = amdgpu_display_modeset_create_props(adev);
 381        if (r)
 382                return r;
 383
 384        adev->ddev->mode_config.max_width = 16384;
 385        adev->ddev->mode_config.max_height = 16384;
 386
 387        /* allocate crtcs, encoders, connectors */
 388        for (i = 0; i < adev->mode_info.num_crtc; i++) {
 389                r = dce_virtual_crtc_init(adev, i);
 390                if (r)
 391                        return r;
 392                r = dce_virtual_connector_encoder_init(adev, i);
 393                if (r)
 394                        return r;
 395        }
 396
 397        drm_kms_helper_poll_init(adev->ddev);
 398
 399        adev->mode_info.mode_config_initialized = true;
 400        return 0;
 401}
 402
 403static int dce_virtual_sw_fini(void *handle)
 404{
 405        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 406
 407        kfree(adev->mode_info.bios_hardcoded_edid);
 408
 409        drm_kms_helper_poll_fini(adev->ddev);
 410
 411        drm_mode_config_cleanup(adev->ddev);
 412        /* clear crtcs pointer to avoid dce irq finish routine access freed data */
 413        memset(adev->mode_info.crtcs, 0, sizeof(adev->mode_info.crtcs[0]) * AMDGPU_MAX_CRTCS);
 414        adev->mode_info.mode_config_initialized = false;
 415        return 0;
 416}
 417
 418static int dce_virtual_hw_init(void *handle)
 419{
 420        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 421
 422        switch (adev->asic_type) {
 423#ifdef CONFIG_DRM_AMDGPU_SI
 424        case CHIP_TAHITI:
 425        case CHIP_PITCAIRN:
 426        case CHIP_VERDE:
 427        case CHIP_OLAND:
 428                dce_v6_0_disable_dce(adev);
 429                break;
 430#endif
 431#ifdef CONFIG_DRM_AMDGPU_CIK
 432        case CHIP_BONAIRE:
 433        case CHIP_HAWAII:
 434        case CHIP_KAVERI:
 435        case CHIP_KABINI:
 436        case CHIP_MULLINS:
 437                dce_v8_0_disable_dce(adev);
 438                break;
 439#endif
 440        case CHIP_FIJI:
 441        case CHIP_TONGA:
 442                dce_v10_0_disable_dce(adev);
 443                break;
 444        case CHIP_CARRIZO:
 445        case CHIP_STONEY:
 446        case CHIP_POLARIS10:
 447        case CHIP_POLARIS11:
 448        case CHIP_VEGAM:
 449                dce_v11_0_disable_dce(adev);
 450                break;
 451        case CHIP_TOPAZ:
 452#ifdef CONFIG_DRM_AMDGPU_SI
 453        case CHIP_HAINAN:
 454#endif
 455                /* no DCE */
 456                break;
 457        default:
 458                break;
 459        }
 460        return 0;
 461}
 462
 463static int dce_virtual_hw_fini(void *handle)
 464{
 465        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 466        int i = 0;
 467
 468        for (i = 0; i<adev->mode_info.num_crtc; i++)
 469                if (adev->mode_info.crtcs[i])
 470                        dce_virtual_set_crtc_vblank_interrupt_state(adev, i, AMDGPU_IRQ_STATE_DISABLE);
 471
 472        return 0;
 473}
 474
 475static int dce_virtual_suspend(void *handle)
 476{
 477        return dce_virtual_hw_fini(handle);
 478}
 479
 480static int dce_virtual_resume(void *handle)
 481{
 482        return dce_virtual_hw_init(handle);
 483}
 484
 485static bool dce_virtual_is_idle(void *handle)
 486{
 487        return true;
 488}
 489
 490static int dce_virtual_wait_for_idle(void *handle)
 491{
 492        return 0;
 493}
 494
 495static int dce_virtual_soft_reset(void *handle)
 496{
 497        return 0;
 498}
 499
 500static int dce_virtual_set_clockgating_state(void *handle,
 501                                          enum amd_clockgating_state state)
 502{
 503        return 0;
 504}
 505
 506static int dce_virtual_set_powergating_state(void *handle,
 507                                          enum amd_powergating_state state)
 508{
 509        return 0;
 510}
 511
 512static const struct amd_ip_funcs dce_virtual_ip_funcs = {
 513        .name = "dce_virtual",
 514        .early_init = dce_virtual_early_init,
 515        .late_init = NULL,
 516        .sw_init = dce_virtual_sw_init,
 517        .sw_fini = dce_virtual_sw_fini,
 518        .hw_init = dce_virtual_hw_init,
 519        .hw_fini = dce_virtual_hw_fini,
 520        .suspend = dce_virtual_suspend,
 521        .resume = dce_virtual_resume,
 522        .is_idle = dce_virtual_is_idle,
 523        .wait_for_idle = dce_virtual_wait_for_idle,
 524        .soft_reset = dce_virtual_soft_reset,
 525        .set_clockgating_state = dce_virtual_set_clockgating_state,
 526        .set_powergating_state = dce_virtual_set_powergating_state,
 527};
 528
 529/* these are handled by the primary encoders */
 530static void dce_virtual_encoder_prepare(struct drm_encoder *encoder)
 531{
 532        return;
 533}
 534
 535static void dce_virtual_encoder_commit(struct drm_encoder *encoder)
 536{
 537        return;
 538}
 539
 540static void
 541dce_virtual_encoder_mode_set(struct drm_encoder *encoder,
 542                             struct drm_display_mode *mode,
 543                             struct drm_display_mode *adjusted_mode)
 544{
 545        return;
 546}
 547
 548static void dce_virtual_encoder_disable(struct drm_encoder *encoder)
 549{
 550        return;
 551}
 552
 553static void
 554dce_virtual_encoder_dpms(struct drm_encoder *encoder, int mode)
 555{
 556        return;
 557}
 558
 559static bool dce_virtual_encoder_mode_fixup(struct drm_encoder *encoder,
 560                                    const struct drm_display_mode *mode,
 561                                    struct drm_display_mode *adjusted_mode)
 562{
 563        return true;
 564}
 565
 566static const struct drm_encoder_helper_funcs dce_virtual_encoder_helper_funcs = {
 567        .dpms = dce_virtual_encoder_dpms,
 568        .mode_fixup = dce_virtual_encoder_mode_fixup,
 569        .prepare = dce_virtual_encoder_prepare,
 570        .mode_set = dce_virtual_encoder_mode_set,
 571        .commit = dce_virtual_encoder_commit,
 572        .disable = dce_virtual_encoder_disable,
 573};
 574
 575static void dce_virtual_encoder_destroy(struct drm_encoder *encoder)
 576{
 577        drm_encoder_cleanup(encoder);
 578        kfree(encoder);
 579}
 580
 581static const struct drm_encoder_funcs dce_virtual_encoder_funcs = {
 582        .destroy = dce_virtual_encoder_destroy,
 583};
 584
 585static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
 586                                              int index)
 587{
 588        struct drm_encoder *encoder;
 589        struct drm_connector *connector;
 590
 591        /* add a new encoder */
 592        encoder = kzalloc(sizeof(struct drm_encoder), GFP_KERNEL);
 593        if (!encoder)
 594                return -ENOMEM;
 595        encoder->possible_crtcs = 1 << index;
 596        drm_encoder_init(adev->ddev, encoder, &dce_virtual_encoder_funcs,
 597                         DRM_MODE_ENCODER_VIRTUAL, NULL);
 598        drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs);
 599
 600        connector = kzalloc(sizeof(struct drm_connector), GFP_KERNEL);
 601        if (!connector) {
 602                kfree(encoder);
 603                return -ENOMEM;
 604        }
 605
 606        /* add a new connector */
 607        drm_connector_init(adev->ddev, connector, &dce_virtual_connector_funcs,
 608                           DRM_MODE_CONNECTOR_VIRTUAL);
 609        drm_connector_helper_add(connector, &dce_virtual_connector_helper_funcs);
 610        connector->display_info.subpixel_order = SubPixelHorizontalRGB;
 611        connector->interlace_allowed = false;
 612        connector->doublescan_allowed = false;
 613        drm_connector_register(connector);
 614
 615        /* link them */
 616        drm_connector_attach_encoder(connector, encoder);
 617
 618        return 0;
 619}
 620
 621static const struct amdgpu_display_funcs dce_virtual_display_funcs = {
 622        .bandwidth_update = &dce_virtual_bandwidth_update,
 623        .vblank_get_counter = &dce_virtual_vblank_get_counter,
 624        .backlight_set_level = NULL,
 625        .backlight_get_level = NULL,
 626        .hpd_sense = &dce_virtual_hpd_sense,
 627        .hpd_set_polarity = &dce_virtual_hpd_set_polarity,
 628        .hpd_get_gpio_reg = &dce_virtual_hpd_get_gpio_reg,
 629        .page_flip = &dce_virtual_page_flip,
 630        .page_flip_get_scanoutpos = &dce_virtual_crtc_get_scanoutpos,
 631        .add_encoder = NULL,
 632        .add_connector = NULL,
 633};
 634
 635static void dce_virtual_set_display_funcs(struct amdgpu_device *adev)
 636{
 637        adev->mode_info.funcs = &dce_virtual_display_funcs;
 638}
 639
 640static int dce_virtual_pageflip(struct amdgpu_device *adev,
 641                                unsigned crtc_id)
 642{
 643        unsigned long flags;
 644        struct amdgpu_crtc *amdgpu_crtc;
 645        struct amdgpu_flip_work *works;
 646
 647        amdgpu_crtc = adev->mode_info.crtcs[crtc_id];
 648
 649        if (crtc_id >= adev->mode_info.num_crtc) {
 650                DRM_ERROR("invalid pageflip crtc %d\n", crtc_id);
 651                return -EINVAL;
 652        }
 653
 654        /* IRQ could occur when in initial stage */
 655        if (amdgpu_crtc == NULL)
 656                return 0;
 657
 658        spin_lock_irqsave(&adev->ddev->event_lock, flags);
 659        works = amdgpu_crtc->pflip_works;
 660        if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) {
 661                DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != "
 662                        "AMDGPU_FLIP_SUBMITTED(%d)\n",
 663                        amdgpu_crtc->pflip_status,
 664                        AMDGPU_FLIP_SUBMITTED);
 665                spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
 666                return 0;
 667        }
 668
 669        /* page flip completed. clean up */
 670        amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE;
 671        amdgpu_crtc->pflip_works = NULL;
 672
 673        /* wakeup usersapce */
 674        if (works->event)
 675                drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event);
 676
 677        spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
 678
 679        drm_crtc_vblank_put(&amdgpu_crtc->base);
 680        amdgpu_bo_unref(&works->old_abo);
 681        kfree(works->shared);
 682        kfree(works);
 683
 684        return 0;
 685}
 686
 687static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer)
 688{
 689        struct amdgpu_crtc *amdgpu_crtc = container_of(vblank_timer,
 690                                                       struct amdgpu_crtc, vblank_timer);
 691        struct drm_device *ddev = amdgpu_crtc->base.dev;
 692        struct amdgpu_device *adev = ddev->dev_private;
 693
 694        drm_handle_vblank(ddev, amdgpu_crtc->crtc_id);
 695        dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id);
 696        hrtimer_start(vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD,
 697                      HRTIMER_MODE_REL);
 698
 699        return HRTIMER_NORESTART;
 700}
 701
 702static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev,
 703                                                        int crtc,
 704                                                        enum amdgpu_interrupt_state state)
 705{
 706        if (crtc >= adev->mode_info.num_crtc || !adev->mode_info.crtcs[crtc]) {
 707                DRM_DEBUG("invalid crtc %d\n", crtc);
 708                return;
 709        }
 710
 711        if (state && !adev->mode_info.crtcs[crtc]->vsync_timer_enabled) {
 712                DRM_DEBUG("Enable software vsync timer\n");
 713                hrtimer_init(&adev->mode_info.crtcs[crtc]->vblank_timer,
 714                             CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 715                hrtimer_set_expires(&adev->mode_info.crtcs[crtc]->vblank_timer,
 716                                    DCE_VIRTUAL_VBLANK_PERIOD);
 717                adev->mode_info.crtcs[crtc]->vblank_timer.function =
 718                        dce_virtual_vblank_timer_handle;
 719                hrtimer_start(&adev->mode_info.crtcs[crtc]->vblank_timer,
 720                              DCE_VIRTUAL_VBLANK_PERIOD, HRTIMER_MODE_REL);
 721        } else if (!state && adev->mode_info.crtcs[crtc]->vsync_timer_enabled) {
 722                DRM_DEBUG("Disable software vsync timer\n");
 723                hrtimer_cancel(&adev->mode_info.crtcs[crtc]->vblank_timer);
 724        }
 725
 726        adev->mode_info.crtcs[crtc]->vsync_timer_enabled = state;
 727        DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state);
 728}
 729
 730
 731static int dce_virtual_set_crtc_irq_state(struct amdgpu_device *adev,
 732                                          struct amdgpu_irq_src *source,
 733                                          unsigned type,
 734                                          enum amdgpu_interrupt_state state)
 735{
 736        if (type > AMDGPU_CRTC_IRQ_VBLANK6)
 737                return -EINVAL;
 738
 739        dce_virtual_set_crtc_vblank_interrupt_state(adev, type, state);
 740
 741        return 0;
 742}
 743
 744static const struct amdgpu_irq_src_funcs dce_virtual_crtc_irq_funcs = {
 745        .set = dce_virtual_set_crtc_irq_state,
 746        .process = NULL,
 747};
 748
 749static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev)
 750{
 751        adev->crtc_irq.num_types = AMDGPU_CRTC_IRQ_VBLANK6 + 1;
 752        adev->crtc_irq.funcs = &dce_virtual_crtc_irq_funcs;
 753}
 754
 755const struct amdgpu_ip_block_version dce_virtual_ip_block =
 756{
 757        .type = AMD_IP_BLOCK_TYPE_DCE,
 758        .major = 1,
 759        .minor = 0,
 760        .rev = 0,
 761        .funcs = &dce_virtual_ip_funcs,
 762};
 763