dce_virtual.c 20.3 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 23 24 25 26 27 28 29
/*
 * 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.
 *
 */
#include "drmP.h"
#include "amdgpu.h"
#include "amdgpu_pm.h"
#include "amdgpu_i2c.h"
#include "atom.h"
#include "amdgpu_pll.h"
#include "amdgpu_connectors.h"
30 31 32
#ifdef CONFIG_DRM_AMDGPU_SI
#include "dce_v6_0.h"
#endif
33 34 35 36 37
#ifdef CONFIG_DRM_AMDGPU_CIK
#include "dce_v8_0.h"
#endif
#include "dce_v10_0.h"
#include "dce_v11_0.h"
38
#include "dce_virtual.h"
39

40 41 42
#define DCE_VIRTUAL_VBLANK_PERIOD 16666666


43 44
static void dce_virtual_set_display_funcs(struct amdgpu_device *adev);
static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev);
45 46
static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
					      int index);
47

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
/**
 * dce_virtual_vblank_wait - vblank wait asic callback.
 *
 * @adev: amdgpu_device pointer
 * @crtc: crtc to wait for vblank on
 *
 * Wait for vblank on the requested crtc (evergreen+).
 */
static void dce_virtual_vblank_wait(struct amdgpu_device *adev, int crtc)
{
	return;
}

static u32 dce_virtual_vblank_get_counter(struct amdgpu_device *adev, int crtc)
{
63
	return 0;
64 65 66 67 68 69 70 71 72 73 74 75 76 77
}

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;

78
	return -EINVAL;
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
}

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;
}

98
static void dce_virtual_stop_mc_access(struct amdgpu_device *adev,
99 100
			      struct amdgpu_mode_mc_save *save)
{
101
	switch (adev->asic_type) {
102 103 104 105 106 107 108 109
#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
110
#ifdef CONFIG_DRM_AMDGPU_CIK
111 112 113 114 115 116 117
	case CHIP_BONAIRE:
	case CHIP_HAWAII:
	case CHIP_KAVERI:
	case CHIP_KABINI:
	case CHIP_MULLINS:
		dce_v8_0_disable_dce(adev);
		break;
118
#endif
119 120 121 122 123 124 125
	case CHIP_FIJI:
	case CHIP_TONGA:
		dce_v10_0_disable_dce(adev);
		break;
	case CHIP_CARRIZO:
	case CHIP_STONEY:
	case CHIP_POLARIS10:
126 127
	case CHIP_POLARIS11:
	case CHIP_POLARIS12:
128 129
		dce_v11_0_disable_dce(adev);
		break;
130
	case CHIP_TOPAZ:
131 132 133
#ifdef CONFIG_DRM_AMDGPU_SI
	case CHIP_HAINAN:
#endif
134 135
		/* no DCE */
		return;
136
	default:
137
		DRM_ERROR("Virtual display unsupported ASIC type: 0x%X\n", adev->asic_type);
138 139
	}

140 141
	return;
}
142
static void dce_virtual_resume_mc_access(struct amdgpu_device *adev,
143 144 145 146 147
				struct amdgpu_mode_mc_save *save)
{
	return;
}

148
static void dce_virtual_set_vga_render_state(struct amdgpu_device *adev,
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
				    bool render)
{
	return;
}

/**
 * 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;
}

167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
static int dce_virtual_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
				      u16 *green, u16 *blue, uint32_t size)
{
	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
	int i;

	/* userspace palettes are always correct as is */
	for (i = 0; i < size; i++) {
		amdgpu_crtc->lut_r[i] = red[i] >> 6;
		amdgpu_crtc->lut_g[i] = green[i] >> 6;
		amdgpu_crtc->lut_b[i] = blue[i] >> 6;
	}

	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);
}

191 192 193
static const struct drm_crtc_funcs dce_virtual_crtc_funcs = {
	.cursor_set2 = NULL,
	.cursor_move = NULL,
194 195 196
	.gamma_set = dce_virtual_crtc_gamma_set,
	.set_config = amdgpu_crtc_set_config,
	.destroy = dce_virtual_crtc_destroy,
197
	.page_flip_target = amdgpu_crtc_page_flip_target,
198 199
};

200 201 202 203 204 205 206 207 208 209
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;

	switch (mode) {
	case DRM_MODE_DPMS_ON:
		amdgpu_crtc->enabled = true;
210
		/* Make sure VBLANK interrupts are still enabled */
211 212
		type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id);
		amdgpu_irq_update(adev, &adev->crtc_irq, type);
213
		drm_crtc_vblank_on(crtc);
214 215 216 217
		break;
	case DRM_MODE_DPMS_STANDBY:
	case DRM_MODE_DPMS_SUSPEND:
	case DRM_MODE_DPMS_OFF:
218
		drm_crtc_vblank_off(crtc);
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
		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);
	if (crtc->primary->fb) {
		int r;
		struct amdgpu_framebuffer *amdgpu_fb;
243
		struct amdgpu_bo *abo;
244 245

		amdgpu_fb = to_amdgpu_framebuffer(crtc->primary->fb);
246 247
		abo = gem_to_amdgpu_bo(amdgpu_fb->obj);
		r = amdgpu_bo_reserve(abo, false);
248
		if (unlikely(r))
249
			DRM_ERROR("failed to reserve abo before unpin\n");
250
		else {
251 252
			amdgpu_bo_unpin(abo);
			amdgpu_bo_unreserve(abo);
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 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
		}
	}

	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 void dce_virtual_crtc_load_lut(struct drm_crtc *crtc)
{
	return;
}

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;
}

300
static const struct drm_crtc_helper_funcs dce_virtual_crtc_helper_funcs = {
301 302 303 304 305 306 307 308 309
	.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,
	.load_lut = dce_virtual_crtc_load_lut,
	.disable = dce_virtual_crtc_disable,
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
};

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

	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;

	for (i = 0; i < 256; i++) {
		amdgpu_crtc->lut_r[i] = i << 2;
		amdgpu_crtc->lut_g[i] = i << 2;
		amdgpu_crtc->lut_b[i] = i << 2;
	}

	amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
	amdgpu_crtc->encoder = NULL;
	amdgpu_crtc->connector = NULL;
337
	amdgpu_crtc->vsync_timer_enabled = AMDGPU_IRQ_STATE_DISABLE;
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354
	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;
}

355 356
static struct drm_encoder *
dce_virtual_encoder(struct drm_connector *connector)
357
{
358 359 360 361 362 363 364 365 366 367 368
	int enc_id = connector->encoder_ids[0];
	struct drm_encoder *encoder;
	int i;

	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
		if (connector->encoder_ids[i] == 0)
			break;

		encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
		if (!encoder)
			continue;
369

370 371 372
		if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
			return encoder;
	}
373

374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
	/* pick the first one */
	if (enc_id)
		return drm_encoder_find(connector->dev, enc_id);
	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);
	}
412

413 414
	return 0;
}
415

416 417 418 419 420
static int dce_virtual_mode_valid(struct drm_connector *connector,
				  struct drm_display_mode *mode)
{
	return MODE_OK;
}
421

422 423 424 425
static int
dce_virtual_dpms(struct drm_connector *connector, int mode)
{
	return 0;
426 427
}

428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
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,
};

462 463 464 465 466 467 468 469 470
static int dce_virtual_sw_init(void *handle)
{
	int r, i;
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;

	r = amdgpu_irq_add_id(adev, 229, &adev->crtc_irq);
	if (r)
		return r;

471 472
	adev->ddev->max_vblank_count = 0;

473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
	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;

	adev->ddev->mode_config.fb_base = adev->mc.aper_base;

	r = amdgpu_modeset_create_props(adev);
	if (r)
		return r;

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

490
	/* allocate crtcs, encoders, connectors */
491 492 493 494
	for (i = 0; i < adev->mode_info.num_crtc; i++) {
		r = dce_virtual_crtc_init(adev, i);
		if (r)
			return r;
495 496 497
		r = dce_virtual_connector_encoder_init(adev, i);
		if (r)
			return r;
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535
	}

	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);
	adev->mode_info.mode_config_initialized = false;
	return 0;
}

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

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

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

static int dce_virtual_resume(void *handle)
{
536
	return dce_virtual_hw_init(handle);
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
}

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;
}

566
static const struct amd_ip_funcs dce_virtual_ip_funcs = {
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
	.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,
};

583 584 585 586 587 588 589 590 591 592 593 594 595
/* 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,
596 597
			     struct drm_display_mode *mode,
			     struct drm_display_mode *adjusted_mode)
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631
{
	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);
632
	kfree(encoder);
633 634 635 636 637 638
}

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

639 640
static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev,
					      int index)
641 642
{
	struct drm_encoder *encoder;
643
	struct drm_connector *connector;
644

645 646 647 648 649 650 651 652 653 654 655 656 657
	/* 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;
658 659
	}

660 661 662 663 664 665 666 667
	/* 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);
668

669 670 671 672
	/* link them */
	drm_mode_connector_attach_encoder(connector, encoder);

	return 0;
673 674
}

675
static const struct amdgpu_display_funcs dce_virtual_display_funcs = {
676 677 678 679
	.set_vga_render_state = &dce_virtual_set_vga_render_state,
	.bandwidth_update = &dce_virtual_bandwidth_update,
	.vblank_get_counter = &dce_virtual_vblank_get_counter,
	.vblank_wait = &dce_virtual_vblank_wait,
680 681
	.backlight_set_level = NULL,
	.backlight_get_level = NULL,
682 683 684 685 686
	.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,
687 688
	.add_encoder = NULL,
	.add_connector = NULL,
689 690
	.stop_mc_access = &dce_virtual_stop_mc_access,
	.resume_mc_access = &dce_virtual_resume_mc_access,
691 692 693 694 695 696 697 698
};

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

699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743
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);
	schedule_work(&works->unpin_work);

	return 0;
}

744 745
static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vblank_timer)
{
746 747 748 749
	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;
750

751 752
	drm_handle_vblank(ddev, amdgpu_crtc->crtc_id);
	dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id);
753
	hrtimer_start(vblank_timer, DCE_VIRTUAL_VBLANK_PERIOD,
754 755
		      HRTIMER_MODE_REL);

756 757 758
	return HRTIMER_NORESTART;
}

759
static void dce_virtual_set_crtc_vblank_interrupt_state(struct amdgpu_device *adev,
760 761
							int crtc,
							enum amdgpu_interrupt_state state)
762 763 764 765 766
{
	if (crtc >= adev->mode_info.num_crtc) {
		DRM_DEBUG("invalid crtc %d\n", crtc);
		return;
	}
767

768
	if (state && !adev->mode_info.crtcs[crtc]->vsync_timer_enabled) {
769
		DRM_DEBUG("Enable software vsync timer\n");
770 771 772
		hrtimer_init(&adev->mode_info.crtcs[crtc]->vblank_timer,
			     CLOCK_MONOTONIC, HRTIMER_MODE_REL);
		hrtimer_set_expires(&adev->mode_info.crtcs[crtc]->vblank_timer,
773
				    DCE_VIRTUAL_VBLANK_PERIOD);
774 775 776
		adev->mode_info.crtcs[crtc]->vblank_timer.function =
			dce_virtual_vblank_timer_handle;
		hrtimer_start(&adev->mode_info.crtcs[crtc]->vblank_timer,
777
			      DCE_VIRTUAL_VBLANK_PERIOD, HRTIMER_MODE_REL);
778
	} else if (!state && adev->mode_info.crtcs[crtc]->vsync_timer_enabled) {
779
		DRM_DEBUG("Disable software vsync timer\n");
780
		hrtimer_cancel(&adev->mode_info.crtcs[crtc]->vblank_timer);
781 782
	}

783
	adev->mode_info.crtcs[crtc]->vsync_timer_enabled = state;
784
	DRM_DEBUG("[FM]set crtc %d vblank interrupt state %d\n", crtc, state);
785 786
}

787

788
static int dce_virtual_set_crtc_irq_state(struct amdgpu_device *adev,
789 790 791
					  struct amdgpu_irq_src *source,
					  unsigned type,
					  enum amdgpu_interrupt_state state)
792
{
793 794 795 796 797
	if (type > AMDGPU_CRTC_IRQ_VBLANK6)
		return -EINVAL;

	dce_virtual_set_crtc_vblank_interrupt_state(adev, type, state);

798 799 800
	return 0;
}

801
static const struct amdgpu_irq_src_funcs dce_virtual_crtc_irq_funcs = {
802
	.set = dce_virtual_set_crtc_irq_state,
803
	.process = NULL,
804 805 806 807 808 809 810 811
};

static void dce_virtual_set_irq_funcs(struct amdgpu_device *adev)
{
	adev->crtc_irq.num_types = AMDGPU_CRTC_IRQ_LAST;
	adev->crtc_irq.funcs = &dce_virtual_crtc_irq_funcs;
}

812 813 814 815 816 817 818 819
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,
};