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