dce_virtual.c 19.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 * Copyright 2014 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 */
23 24 25

#include <drm/drm_vblank.h>

26 27 28 29 30 31
#include "amdgpu.h"
#include "amdgpu_pm.h"
#include "amdgpu_i2c.h"
#include "atom.h"
#include "amdgpu_pll.h"
#include "amdgpu_connectors.h"
32 33 34
#ifdef CONFIG_DRM_AMDGPU_SI
#include "dce_v6_0.h"
#endif
35 36 37 38 39
#ifdef CONFIG_DRM_AMDGPU_CIK
#include "dce_v8_0.h"
#endif
#include "dce_v10_0.h"
#include "dce_v11_0.h"
40
#include "dce_virtual.h"
41
#include "ivsrcid/ivsrcid_vislands30.h"
42

43 44 45
#define DCE_VIRTUAL_VBLANK_PERIOD 16666666


46 47
static void dce_virtual_set_display_funcs(struct amdgpu_device *adev);
static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev);
48 49
static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
					      int index);
50 51 52
static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev,
							int crtc,
							enum amdgpu_interrupt_state state);
53

54 55
static u32 dce_virtual_vblank_get_counter(struct amdgpu_device *adev, int crtc)
{
56
	return 0;
57 58 59 60 61 62 63 64 65 66 67 68 69 70
}

static void dce_virtual_page_flip(struct amdgpu_device *adev,
			      int crtc_id, u64 crtc_base, bool async)
{
	return;
}

static int dce_virtual_crtc_get_scanoutpos(struct amdgpu_device *adev, int crtc,
					u32 *vbl, u32 *position)
{
	*vbl = 0;
	*position = 0;

71
	return -EINVAL;
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
}

static bool dce_virtual_hpd_sense(struct amdgpu_device *adev,
			       enum amdgpu_hpd_id hpd)
{
	return true;
}

static void dce_virtual_hpd_set_polarity(struct amdgpu_device *adev,
				      enum amdgpu_hpd_id hpd)
{
	return;
}

static u32 dce_virtual_hpd_get_gpio_reg(struct amdgpu_device *adev)
{
	return 0;
}

/**
 * dce_virtual_bandwidth_update - program display watermarks
 *
 * @adev: amdgpu_device pointer
 *
 * Calculate and program the display watermarks and line
 * buffer allocation (CIK).
 */
static void dce_virtual_bandwidth_update(struct amdgpu_device *adev)
{
	return;
}

104
static int dce_virtual_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
105 106
				      u16 *green, u16 *blue, uint32_t size,
				      struct drm_modeset_acquire_ctx *ctx)
107 108 109 110 111 112 113 114 115 116 117 118
{
	return 0;
}

static void dce_virtual_crtc_destroy(struct drm_crtc *crtc)
{
	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);

	drm_crtc_cleanup(crtc);
	kfree(amdgpu_crtc);
}

119 120 121
static const struct drm_crtc_funcs dce_virtual_crtc_funcs = {
	.cursor_set2 = NULL,
	.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
};

128 129 130 131 132 133 134
static void dce_virtual_crtc_dpms(struct drm_crtc *crtc, int mode)
{
	struct drm_device *dev = crtc->dev;
	struct amdgpu_device *adev = dev->dev_private;
	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
	unsigned type;

135 136 137
	if (amdgpu_sriov_vf(adev))
		return;

138 139 140
	switch (mode) {
	case DRM_MODE_DPMS_ON:
		amdgpu_crtc->enabled = true;
141
		/* Make sure VBLANK interrupts are still enabled */
142 143
		type = amdgpu_display_crtc_idx_to_irq_type(adev,
						amdgpu_crtc->crtc_id);
144
		amdgpu_irq_update(adev, &adev->crtc_irq, type);
145
		drm_crtc_vblank_on(crtc);
146 147 148 149
		break;
	case DRM_MODE_DPMS_STANDBY:
	case DRM_MODE_DPMS_SUSPEND:
	case DRM_MODE_DPMS_OFF:
150
		drm_crtc_vblank_off(crtc);
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
		amdgpu_crtc->enabled = false;
		break;
	}
}


static void dce_virtual_crtc_prepare(struct drm_crtc *crtc)
{
	dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
}

static void dce_virtual_crtc_commit(struct drm_crtc *crtc)
{
	dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
}

static void dce_virtual_crtc_disable(struct drm_crtc *crtc)
{
	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);

	dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);

	amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
	amdgpu_crtc->encoder = NULL;
	amdgpu_crtc->connector = NULL;
}

static int dce_virtual_crtc_mode_set(struct drm_crtc *crtc,
				  struct drm_display_mode *mode,
				  struct drm_display_mode *adjusted_mode,
				  int x, int y, struct drm_framebuffer *old_fb)
{
	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);

	/* update the hw version fpr dpm */
	amdgpu_crtc->hw_mode = *adjusted_mode;

	return 0;
}

static bool dce_virtual_crtc_mode_fixup(struct drm_crtc *crtc,
				     const struct drm_display_mode *mode,
				     struct drm_display_mode *adjusted_mode)
{
	return true;
}


static int dce_virtual_crtc_set_base(struct drm_crtc *crtc, int x, int y,
				  struct drm_framebuffer *old_fb)
{
	return 0;
}

static int dce_virtual_crtc_set_base_atomic(struct drm_crtc *crtc,
					 struct drm_framebuffer *fb,
					 int x, int y, enum mode_set_atomic state)
{
	return 0;
}

212
static const struct drm_crtc_helper_funcs dce_virtual_crtc_helper_funcs = {
213 214 215 216 217 218 219 220
	.dpms = dce_virtual_crtc_dpms,
	.mode_fixup = dce_virtual_crtc_mode_fixup,
	.mode_set = dce_virtual_crtc_mode_set,
	.mode_set_base = dce_virtual_crtc_set_base,
	.mode_set_base_atomic = dce_virtual_crtc_set_base_atomic,
	.prepare = dce_virtual_crtc_prepare,
	.commit = dce_virtual_crtc_commit,
	.disable = dce_virtual_crtc_disable,
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
};

static int dce_virtual_crtc_init(struct amdgpu_device *adev, int index)
{
	struct amdgpu_crtc *amdgpu_crtc;

	amdgpu_crtc = kzalloc(sizeof(struct amdgpu_crtc) +
			      (AMDGPUFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL);
	if (amdgpu_crtc == NULL)
		return -ENOMEM;

	drm_crtc_init(adev->ddev, &amdgpu_crtc->base, &dce_virtual_crtc_funcs);

	drm_mode_crtc_set_gamma_size(&amdgpu_crtc->base, 256);
	amdgpu_crtc->crtc_id = index;
	adev->mode_info.crtcs[index] = amdgpu_crtc;

	amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
	amdgpu_crtc->encoder = NULL;
	amdgpu_crtc->connector = NULL;
241
	amdgpu_crtc->vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE;
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
	drm_crtc_helper_add(&amdgpu_crtc->base, &dce_virtual_crtc_helper_funcs);

	return 0;
}

static int dce_virtual_early_init(void *handle)
{
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;

	dce_virtual_set_display_funcs(adev);
	dce_virtual_set_irq_funcs(adev);

	adev->mode_info.num_hpd = 1;
	adev->mode_info.num_dig = 1;
	return 0;
}

259 260
static struct drm_encoder *
dce_virtual_encoder(struct drm_connector *connector)
261
{
262 263 264
	struct drm_encoder *encoder;
	int i;

265
	drm_connector_for_each_possible_encoder(connector, encoder, i) {
266 267 268
		if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
			return encoder;
	}
269

270
	/* pick the first one */
271 272 273
	drm_connector_for_each_possible_encoder(connector, encoder, i)
		return encoder;

274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
	return NULL;
}

static int dce_virtual_get_modes(struct drm_connector *connector)
{
	struct drm_device *dev = connector->dev;
	struct drm_display_mode *mode = NULL;
	unsigned i;
	static const struct mode_size {
		int w;
		int h;
	} common_modes[17] = {
		{ 640,  480},
		{ 720,  480},
		{ 800,  600},
		{ 848,  480},
		{1024,  768},
		{1152,  768},
		{1280,  720},
		{1280,  800},
		{1280,  854},
		{1280,  960},
		{1280, 1024},
		{1440,  900},
		{1400, 1050},
		{1680, 1050},
		{1600, 1200},
		{1920, 1080},
		{1920, 1200}
	};

	for (i = 0; i < 17; i++) {
		mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false, false);
		drm_mode_probed_add(connector, mode);
	}
309

310 311
	return 0;
}
312

313
static enum drm_mode_status dce_virtual_mode_valid(struct drm_connector *connector,
314 315 316 317
				  struct drm_display_mode *mode)
{
	return MODE_OK;
}
318

319 320 321 322
static int
dce_virtual_dpms(struct drm_connector *connector, int mode)
{
	return 0;
323 324
}

325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
static int
dce_virtual_set_property(struct drm_connector *connector,
			 struct drm_property *property,
			 uint64_t val)
{
	return 0;
}

static void dce_virtual_destroy(struct drm_connector *connector)
{
	drm_connector_unregister(connector);
	drm_connector_cleanup(connector);
	kfree(connector);
}

static void dce_virtual_force(struct drm_connector *connector)
{
	return;
}

static const struct drm_connector_helper_funcs dce_virtual_connector_helper_funcs = {
	.get_modes = dce_virtual_get_modes,
	.mode_valid = dce_virtual_mode_valid,
	.best_encoder = dce_virtual_encoder,
};

static const struct drm_connector_funcs dce_virtual_connector_funcs = {
	.dpms = dce_virtual_dpms,
	.fill_modes = drm_helper_probe_single_connector_modes,
	.set_property = dce_virtual_set_property,
	.destroy = dce_virtual_destroy,
	.force = dce_virtual_force,
};

359 360 361 362 363
static int dce_virtual_sw_init(void *handle)
{
	int r, i;
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;

364
	r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, VISLANDS30_IV_SRCID_SMU_DISP_TIMER2_TRIGGER, &adev->crtc_irq);
365 366 367
	if (r)
		return r;

368 369
	adev->ddev->max_vblank_count = 0;

370 371 372 373 374 375 376 377
	adev->ddev->mode_config.funcs = &amdgpu_mode_funcs;

	adev->ddev->mode_config.max_width = 16384;
	adev->ddev->mode_config.max_height = 16384;

	adev->ddev->mode_config.preferred_depth = 24;
	adev->ddev->mode_config.prefer_shadow = 1;

378
	adev->ddev->mode_config.fb_base = adev->gmc.aper_base;
379

380
	r = amdgpu_display_modeset_create_props(adev);
381 382 383 384 385 386
	if (r)
		return r;

	adev->ddev->mode_config.max_width = 16384;
	adev->ddev->mode_config.max_height = 16384;

387
	/* allocate crtcs, encoders, connectors */
388 389 390 391
	for (i = 0; i < adev->mode_info.num_crtc; i++) {
		r = dce_virtual_crtc_init(adev, i);
		if (r)
			return r;
392 393 394
		r = dce_virtual_connector_encoder_init(adev, i);
		if (r)
			return r;
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
	}

	drm_kms_helper_poll_init(adev->ddev);

	adev->mode_info.mode_config_initialized = true;
	return 0;
}

static int dce_virtual_sw_fini(void *handle)
{
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;

	kfree(adev->mode_info.bios_hardcoded_edid);

	drm_kms_helper_poll_fini(adev->ddev);

	drm_mode_config_cleanup(adev->ddev);
M
Monk Liu 已提交
412 413
	/* clear crtcs pointer to avoid dce irq finish routine access freed data */
	memset(adev->mode_info.crtcs, 0, sizeof(adev->mode_info.crtcs[0]) * AMDGPU_MAX_CRTCS);
414 415 416 417 418 419
	adev->mode_info.mode_config_initialized = false;
	return 0;
}

static int dce_virtual_hw_init(void *handle)
{
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;

	switch (adev->asic_type) {
#ifdef CONFIG_DRM_AMDGPU_SI
	case CHIP_TAHITI:
	case CHIP_PITCAIRN:
	case CHIP_VERDE:
	case CHIP_OLAND:
		dce_v6_0_disable_dce(adev);
		break;
#endif
#ifdef CONFIG_DRM_AMDGPU_CIK
	case CHIP_BONAIRE:
	case CHIP_HAWAII:
	case CHIP_KAVERI:
	case CHIP_KABINI:
	case CHIP_MULLINS:
		dce_v8_0_disable_dce(adev);
		break;
#endif
	case CHIP_FIJI:
	case CHIP_TONGA:
		dce_v10_0_disable_dce(adev);
		break;
	case CHIP_CARRIZO:
	case CHIP_STONEY:
	case CHIP_POLARIS10:
447 448
	case CHIP_POLARIS11:
	case CHIP_VEGAM:
449 450 451 452 453 454 455 456
		dce_v11_0_disable_dce(adev);
		break;
	case CHIP_TOPAZ:
#ifdef CONFIG_DRM_AMDGPU_SI
	case CHIP_HAINAN:
#endif
		/* no DCE */
		break;
457
	case CHIP_VEGA10:
458
	case CHIP_VEGA12:
459
	case CHIP_VEGA20:
460
	case CHIP_ARCTURUS:
461
	case CHIP_RENOIR:
462
	case CHIP_NAVI10:
463
	case CHIP_NAVI14:
464
	case CHIP_NAVI12:
465
		break;
466 467 468
	default:
		DRM_ERROR("Virtual display unsupported ASIC type: 0x%X\n", adev->asic_type);
	}
469 470 471 472 473
	return 0;
}

static int dce_virtual_hw_fini(void *handle)
{
474 475 476 477 478 479 480
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
	int i = 0;

	for (i = 0; i<adev->mode_info.num_crtc; i++)
		if (adev->mode_info.crtcs[i])
			dce_virtual_set_crtc_vblank_interrupt_state(adev, i, AMDGPU_IRQ_STATE_DISABLE);

481 482 483 484 485 486 487 488 489 490
	return 0;
}

static int dce_virtual_suspend(void *handle)
{
	return dce_virtual_hw_fini(handle);
}

static int dce_virtual_resume(void *handle)
{
491
	return dce_virtual_hw_init(handle);
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
}

static bool dce_virtual_is_idle(void *handle)
{
	return true;
}

static int dce_virtual_wait_for_idle(void *handle)
{
	return 0;
}

static int dce_virtual_soft_reset(void *handle)
{
	return 0;
}

static int dce_virtual_set_clockgating_state(void *handle,
					  enum amd_clockgating_state state)
{
	return 0;
}

static int dce_virtual_set_powergating_state(void *handle,
					  enum amd_powergating_state state)
{
	return 0;
}

521
static const struct amd_ip_funcs dce_virtual_ip_funcs = {
522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
	.name = "dce_virtual",
	.early_init = dce_virtual_early_init,
	.late_init = NULL,
	.sw_init = dce_virtual_sw_init,
	.sw_fini = dce_virtual_sw_fini,
	.hw_init = dce_virtual_hw_init,
	.hw_fini = dce_virtual_hw_fini,
	.suspend = dce_virtual_suspend,
	.resume = dce_virtual_resume,
	.is_idle = dce_virtual_is_idle,
	.wait_for_idle = dce_virtual_wait_for_idle,
	.soft_reset = dce_virtual_soft_reset,
	.set_clockgating_state = dce_virtual_set_clockgating_state,
	.set_powergating_state = dce_virtual_set_powergating_state,
};

538 539 540 541 542 543 544 545 546 547 548 549 550
/* these are handled by the primary encoders */
static void dce_virtual_encoder_prepare(struct drm_encoder *encoder)
{
	return;
}

static void dce_virtual_encoder_commit(struct drm_encoder *encoder)
{
	return;
}

static void
dce_virtual_encoder_mode_set(struct drm_encoder *encoder,
551 552
			     struct drm_display_mode *mode,
			     struct drm_display_mode *adjusted_mode)
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586
{
	return;
}

static void dce_virtual_encoder_disable(struct drm_encoder *encoder)
{
	return;
}

static void
dce_virtual_encoder_dpms(struct drm_encoder *encoder, int mode)
{
	return;
}

static bool dce_virtual_encoder_mode_fixup(struct drm_encoder *encoder,
				    const struct drm_display_mode *mode,
				    struct drm_display_mode *adjusted_mode)
{
	return true;
}

static const struct drm_encoder_helper_funcs dce_virtual_encoder_helper_funcs = {
	.dpms = dce_virtual_encoder_dpms,
	.mode_fixup = dce_virtual_encoder_mode_fixup,
	.prepare = dce_virtual_encoder_prepare,
	.mode_set = dce_virtual_encoder_mode_set,
	.commit = dce_virtual_encoder_commit,
	.disable = dce_virtual_encoder_disable,
};

static void dce_virtual_encoder_destroy(struct drm_encoder *encoder)
{
	drm_encoder_cleanup(encoder);
587
	kfree(encoder);
588 589 590 591 592 593
}

static const struct drm_encoder_funcs dce_virtual_encoder_funcs = {
	.destroy = dce_virtual_encoder_destroy,
};

594 595
static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
					      int index)
596 597
{
	struct drm_encoder *encoder;
598
	struct drm_connector *connector;
599

600 601 602 603 604 605 606 607 608 609 610 611 612
	/* add a new encoder */
	encoder = kzalloc(sizeof(struct drm_encoder), GFP_KERNEL);
	if (!encoder)
		return -ENOMEM;
	encoder->possible_crtcs = 1 << index;
	drm_encoder_init(adev->ddev, encoder, &dce_virtual_encoder_funcs,
			 DRM_MODE_ENCODER_VIRTUAL, NULL);
	drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs);

	connector = kzalloc(sizeof(struct drm_connector), GFP_KERNEL);
	if (!connector) {
		kfree(encoder);
		return -ENOMEM;
613 614
	}

615 616 617 618 619 620 621 622
	/* add a new connector */
	drm_connector_init(adev->ddev, connector, &dce_virtual_connector_funcs,
			   DRM_MODE_CONNECTOR_VIRTUAL);
	drm_connector_helper_add(connector, &dce_virtual_connector_helper_funcs);
	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
	connector->interlace_allowed = false;
	connector->doublescan_allowed = false;
	drm_connector_register(connector);
623

624
	/* link them */
625
	drm_connector_attach_encoder(connector, encoder);
626 627

	return 0;
628 629
}

630
static const struct amdgpu_display_funcs dce_virtual_display_funcs = {
631 632
	.bandwidth_update = &dce_virtual_bandwidth_update,
	.vblank_get_counter = &dce_virtual_vblank_get_counter,
633 634
	.backlight_set_level = NULL,
	.backlight_get_level = NULL,
635 636 637 638 639
	.hpd_sense = &dce_virtual_hpd_sense,
	.hpd_set_polarity = &dce_virtual_hpd_set_polarity,
	.hpd_get_gpio_reg = &dce_virtual_hpd_get_gpio_reg,
	.page_flip = &dce_virtual_page_flip,
	.page_flip_get_scanoutpos = &dce_virtual_crtc_get_scanoutpos,
640 641
	.add_encoder = NULL,
	.add_connector = NULL,
642 643 644 645
};

static void dce_virtual_set_display_funcs(struct amdgpu_device *adev)
{
646
	adev->mode_info.funcs = &dce_virtual_display_funcs;
647 648
}

649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
static int dce_virtual_pageflip(struct amdgpu_device *adev,
				unsigned crtc_id)
{
	unsigned long flags;
	struct amdgpu_crtc *amdgpu_crtc;
	struct amdgpu_flip_work *works;

	amdgpu_crtc = adev->mode_info.crtcs[crtc_id];

	if (crtc_id >= adev->mode_info.num_crtc) {
		DRM_ERROR("invalid pageflip crtc %d\n", crtc_id);
		return -EINVAL;
	}

	/* IRQ could occur when in initial stage */
	if (amdgpu_crtc == NULL)
		return 0;

	spin_lock_irqsave(&adev->ddev->event_lock, flags);
	works = amdgpu_crtc->pflip_works;
	if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) {
		DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != "
			"AMDGPU_FLIP_SUBMITTED(%d)\n",
			amdgpu_crtc->pflip_status,
			AMDGPU_FLIP_SUBMITTED);
		spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
		return 0;
	}

	/* page flip completed. clean up */
	amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE;
	amdgpu_crtc->pflip_works = NULL;

	/* wakeup usersapce */
	if (works->event)
		drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event);

	spin_unlock_irqrestore(&adev->ddev->event_lock, flags);

	drm_crtc_vblank_put(&amdgpu_crtc->base);
689 690 691
	amdgpu_bo_unref(&works->old_abo);
	kfree(works->shared);
	kfree(works);
692 693 694 695

	return 0;
}

696 697
static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer)
{
698 699 700 701
	struct amdgpu_crtc *amdgpu_crtc = container_of(vblank_timer,
						       struct amdgpu_crtc, vblank_timer);
	struct drm_device *ddev = amdgpu_crtc->base.dev;
	struct amdgpu_device *adev = ddev->dev_private;
702

703 704
	drm_handle_vblank(ddev, amdgpu_crtc->crtc_id);
	dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id);
T
Thomas Gleixner 已提交
705
	hrtimer_start(vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD,
706 707
		      HRTIMER_MODE_REL);

708 709 710
	return HRTIMER_NORESTART;
}

711
static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev,
712 713
							int crtc,
							enum amdgpu_interrupt_state state)
714
{
M
Monk Liu 已提交
715
	if (crtc >= adev->mode_info.num_crtc || !adev->mode_info.crtcs[crtc]) {
716 717 718
		DRM_DEBUG("invalid crtc %d\n", crtc);
		return;
	}
719

720
	if (state && !adev->mode_info.crtcs[crtc]->vsync_timer_enabled) {
721
		DRM_DEBUG("Enable software vsync timer\n");
722 723 724
		hrtimer_init(&adev->mode_info.crtcs[crtc]->vblank_timer,
			     CLOCK_MONOTONIC, HRTIMER_MODE_REL);
		hrtimer_set_expires(&adev->mode_info.crtcs[crtc]->vblank_timer,
T
Thomas Gleixner 已提交
725
				    DCE_VIRTUAL_VBLANK_PERIOD);
726 727 728
		adev->mode_info.crtcs[crtc]->vblank_timer.function =
			dce_virtual_vblank_timer_handle;
		hrtimer_start(&adev->mode_info.crtcs[crtc]->vblank_timer,
T
Thomas Gleixner 已提交
729
			      DCE_VIRTUAL_VBLANK_PERIOD, HRTIMER_MODE_REL);
730
	} else if (!state && adev->mode_info.crtcs[crtc]->vsync_timer_enabled) {
731
		DRM_DEBUG("Disable software vsync timer\n");
732
		hrtimer_cancel(&adev->mode_info.crtcs[crtc]->vblank_timer);
733 734
	}

735
	adev->mode_info.crtcs[crtc]->vsync_timer_enabled = state;
736
	DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state);
737 738
}

739

740
static int dce_virtual_set_crtc_irq_state(struct amdgpu_device *adev,
741 742 743
					  struct amdgpu_irq_src *source,
					  unsigned type,
					  enum amdgpu_interrupt_state state)
744
{
745 746 747 748 749
	if (type > AMDGPU_CRTC_IRQ_VBLANK6)
		return -EINVAL;

	dce_virtual_set_crtc_vblank_interrupt_state(adev, type, state);

750 751 752
	return 0;
}

753
static const struct amdgpu_irq_src_funcs dce_virtual_crtc_irq_funcs = {
754
	.set = dce_virtual_set_crtc_irq_state,
755
	.process = NULL,
756 757 758 759
};

static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev)
{
760
	adev->crtc_irq.num_types = AMDGPU_CRTC_IRQ_VBLANK6 + 1;
761 762 763
	adev->crtc_irq.funcs = &dce_virtual_crtc_irq_funcs;
}

764 765 766 767 768 769 770 771
const struct amdgpu_ip_block_version dce_virtual_ip_block =
{
	.type = AMD_IP_BLOCK_TYPE_DCE,
	.major = 1,
	.minor = 0,
	.rev = 0,
	.funcs = &dce_virtual_ip_funcs,
};