Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4d538b79 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'drm-next-3.15' of git://people.freedesktop.org/~deathsimple/linux into drm-next

So this is the initial pull request for radeon drm-next 3.15. Highlights:
- VCE bringup including DPM support
- Few cleanups for the ring handling code

* 'drm-next-3.15' of git://people.freedesktop.org/~deathsimple/linux:
  drm/radeon: cleanup false positive lockup handling
  drm/radeon: drop radeon_ring_force_activity
  drm/radeon: drop drivers copy of the rptr
  drm/radeon/cik: enable/disable vce cg when encoding v2
  drm/radeon: add support for vce 2.0 clock gating
  drm/radeon/dpm: properly enable/disable vce when vce pg is enabled
  drm/radeon/dpm: enable dynamic vce state switching v2
  drm/radeon: add vce dpm support for KV/KB
  drm/radeon: enable vce dpm on CI
  drm/radeon: add vce dpm support for CI
  drm/radeon: fill in set_vce_clocks for CIK asics
  drm/radeon/dpm: fetch vce states from the vbios
  drm/radeon/dpm: fill in some initial vce infrastructure
  drm/radeon/dpm: move platform caps fetching to a separate function
  drm/radeon: add callback for setting vce clocks
  drm/radeon: add VCE version parsing and checking
  drm/radeon: add VCE ring query
  drm/radeon: initial VCE support v4
  drm/radeon: fix CP semaphores on CIK
parents c48cdd23 82dc62a3
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -99,6 +99,12 @@ radeon-y += \
	uvd_v3_1.o \
	uvd_v4_2.o

# add VCE block
radeon-y += \
	radeon_vce.o \
	vce_v1_0.o \
	vce_v2_0.o \

radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
radeon-$(CONFIG_ACPI) += radeon_acpi.o
+4 −0
Original line number Diff line number Diff line
@@ -2601,6 +2601,10 @@ int btc_dpm_init(struct radeon_device *rdev)
	pi->min_vddc_in_table = 0;
	pi->max_vddc_in_table = 0;

	ret = r600_get_platform_caps(rdev);
	if (ret)
		return ret;

	ret = rv7xx_parse_power_table(rdev);
	if (ret)
		return ret;
+54 −13
Original line number Diff line number Diff line
@@ -172,6 +172,8 @@ extern void si_trim_voltage_table_to_fit_state_table(struct radeon_device *rdev,
extern void cik_enter_rlc_safe_mode(struct radeon_device *rdev);
extern void cik_exit_rlc_safe_mode(struct radeon_device *rdev);
extern int ci_mc_load_microcode(struct radeon_device *rdev);
extern void cik_update_cg(struct radeon_device *rdev,
			  u32 block, bool enable);

static int ci_get_std_voltage_value_sidd(struct radeon_device *rdev,
					 struct atom_voltage_table_entry *voltage_table,
@@ -746,6 +748,14 @@ static void ci_apply_state_adjust_rules(struct radeon_device *rdev,
	u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc;
	int i;

	if (rps->vce_active) {
		rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk;
		rps->ecclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].ecclk;
	} else {
		rps->evclk = 0;
		rps->ecclk = 0;
	}

	if ((rdev->pm.dpm.new_active_crtc_count > 1) ||
	    ci_dpm_vblank_too_short(rdev))
		disable_mclk_switching = true;
@@ -804,6 +814,13 @@ static void ci_apply_state_adjust_rules(struct radeon_device *rdev,
		sclk = ps->performance_levels[0].sclk;
	}

	if (rps->vce_active) {
		if (sclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk)
			sclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk;
		if (mclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].mclk)
			mclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].mclk;
	}

	ps->performance_levels[0].sclk = sclk;
	ps->performance_levels[0].mclk = mclk;

@@ -3468,7 +3485,6 @@ static int ci_enable_uvd_dpm(struct radeon_device *rdev, bool enable)
		0 : -EINVAL;
}

#if 0
static int ci_enable_vce_dpm(struct radeon_device *rdev, bool enable)
{
	struct ci_power_info *pi = ci_get_pi(rdev);
@@ -3501,6 +3517,7 @@ static int ci_enable_vce_dpm(struct radeon_device *rdev, bool enable)
		0 : -EINVAL;
}

#if 0
static int ci_enable_samu_dpm(struct radeon_device *rdev, bool enable)
{
	struct ci_power_info *pi = ci_get_pi(rdev);
@@ -3587,7 +3604,6 @@ static int ci_update_uvd_dpm(struct radeon_device *rdev, bool gate)
	return ci_enable_uvd_dpm(rdev, !gate);
}

#if 0
static u8 ci_get_vce_boot_level(struct radeon_device *rdev)
{
	u8 i;
@@ -3608,15 +3624,15 @@ static int ci_update_vce_dpm(struct radeon_device *rdev,
			     struct radeon_ps *radeon_current_state)
{
	struct ci_power_info *pi = ci_get_pi(rdev);
	bool new_vce_clock_non_zero = (radeon_new_state->evclk != 0);
	bool old_vce_clock_non_zero = (radeon_current_state->evclk != 0);
	int ret = 0;
	u32 tmp;

	if (new_vce_clock_non_zero != old_vce_clock_non_zero) {
		if (new_vce_clock_non_zero) {
			pi->smc_state_table.VceBootLevel = ci_get_vce_boot_level(rdev);
	if (radeon_current_state->evclk != radeon_new_state->evclk) {
		if (radeon_new_state->evclk) {
			/* turn the clocks on when encoding */
			cik_update_cg(rdev, RADEON_CG_BLOCK_VCE, false);

			pi->smc_state_table.VceBootLevel = ci_get_vce_boot_level(rdev);
			tmp = RREG32_SMC(DPM_TABLE_475);
			tmp &= ~VceBootLevel_MASK;
			tmp |= VceBootLevel(pi->smc_state_table.VceBootLevel);
@@ -3624,12 +3640,16 @@ static int ci_update_vce_dpm(struct radeon_device *rdev,

			ret = ci_enable_vce_dpm(rdev, true);
		} else {
			/* turn the clocks off when not encoding */
			cik_update_cg(rdev, RADEON_CG_BLOCK_VCE, true);

			ret = ci_enable_vce_dpm(rdev, false);
		}
	}
	return ret;
}

#if 0
static int ci_update_samu_dpm(struct radeon_device *rdev, bool gate)
{
	return ci_enable_samu_dpm(rdev, gate);
@@ -4752,13 +4772,13 @@ int ci_dpm_set_power_state(struct radeon_device *rdev)
		DRM_ERROR("ci_generate_dpm_level_enable_mask failed\n");
		return ret;
	}
#if 0

	ret = ci_update_vce_dpm(rdev, new_ps, old_ps);
	if (ret) {
		DRM_ERROR("ci_update_vce_dpm failed\n");
		return ret;
	}
#endif

	ret = ci_update_sclk_t(rdev);
	if (ret) {
		DRM_ERROR("ci_update_sclk_t failed\n");
@@ -4959,9 +4979,6 @@ static int ci_parse_power_table(struct radeon_device *rdev)
	if (!rdev->pm.dpm.ps)
		return -ENOMEM;
	power_state_offset = (u8 *)state_array->states;
	rdev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps);
	rdev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime);
	rdev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime);
	for (i = 0; i < state_array->ucNumEntries; i++) {
		u8 *idx;
		power_state = (union pplib_power_state *)power_state_offset;
@@ -4998,6 +5015,21 @@ static int ci_parse_power_table(struct radeon_device *rdev)
		power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
	}
	rdev->pm.dpm.num_ps = state_array->ucNumEntries;

	/* fill in the vce power states */
	for (i = 0; i < RADEON_MAX_VCE_LEVELS; i++) {
		u32 sclk, mclk;
		clock_array_index = rdev->pm.dpm.vce_states[i].clk_idx;
		clock_info = (union pplib_clock_info *)
			&clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize];
		sclk = le16_to_cpu(clock_info->ci.usEngineClockLow);
		sclk |= clock_info->ci.ucEngineClockHigh << 16;
		mclk = le16_to_cpu(clock_info->ci.usMemoryClockLow);
		mclk |= clock_info->ci.ucMemoryClockHigh << 16;
		rdev->pm.dpm.vce_states[i].sclk = sclk;
		rdev->pm.dpm.vce_states[i].mclk = mclk;
	}

	return 0;
}

@@ -5077,17 +5109,25 @@ int ci_dpm_init(struct radeon_device *rdev)
		ci_dpm_fini(rdev);
		return ret;
	}
	ret = ci_parse_power_table(rdev);

	ret = r600_get_platform_caps(rdev);
	if (ret) {
		ci_dpm_fini(rdev);
		return ret;
	}

	ret = r600_parse_extended_power_table(rdev);
	if (ret) {
		ci_dpm_fini(rdev);
		return ret;
	}

	ret = ci_parse_power_table(rdev);
	if (ret) {
		ci_dpm_fini(rdev);
		return ret;
	}

        pi->dll_default_on = false;
        pi->sram_end = SMC_RAM_END;

@@ -5120,6 +5160,7 @@ int ci_dpm_init(struct radeon_device *rdev)
	pi->caps_sclk_throttle_low_notification = false;

	pi->caps_uvd_dpm = true;
	pi->caps_vce_dpm = true;

        ci_get_leakage_voltages(rdev);
        ci_patch_dependency_tables_with_leakage(rdev);
+102 −7
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ extern void si_init_uvd_internal_cg(struct radeon_device *rdev);
extern int cik_sdma_resume(struct radeon_device *rdev);
extern void cik_sdma_enable(struct radeon_device *rdev, bool enable);
extern void cik_sdma_fini(struct radeon_device *rdev);
extern void vce_v2_0_enable_mgcg(struct radeon_device *rdev, bool enable);
static void cik_rlc_stop(struct radeon_device *rdev);
static void cik_pcie_gen3_enable(struct radeon_device *rdev);
static void cik_program_aspm(struct radeon_device *rdev);
@@ -4030,8 +4031,6 @@ static int cik_cp_gfx_resume(struct radeon_device *rdev)
	WREG32(CP_RB0_BASE, rb_addr);
	WREG32(CP_RB0_BASE_HI, upper_32_bits(rb_addr));

	ring->rptr = RREG32(CP_RB0_RPTR);

	/* start the ring */
	cik_cp_gfx_start(rdev);
	rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = true;
@@ -4586,8 +4585,7 @@ static int cik_cp_compute_resume(struct radeon_device *rdev)
		rdev->ring[idx].wptr = 0;
		mqd->queue_state.cp_hqd_pq_wptr = rdev->ring[idx].wptr;
		WREG32(CP_HQD_PQ_WPTR, mqd->queue_state.cp_hqd_pq_wptr);
		rdev->ring[idx].rptr = RREG32(CP_HQD_PQ_RPTR);
		mqd->queue_state.cp_hqd_pq_rptr = rdev->ring[idx].rptr;
		mqd->queue_state.cp_hqd_pq_rptr = RREG32(CP_HQD_PQ_RPTR);

		/* set the vmid for the queue */
		mqd->queue_state.cp_hqd_vmid = 0;
@@ -5117,11 +5115,9 @@ bool cik_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
	if (!(reset_mask & (RADEON_RESET_GFX |
			    RADEON_RESET_COMPUTE |
			    RADEON_RESET_CP))) {
		radeon_ring_lockup_update(ring);
		radeon_ring_lockup_update(rdev, ring);
		return false;
	}
	/* force CP activities */
	radeon_ring_force_activity(rdev, ring);
	return radeon_ring_test_lockup(rdev, ring);
}

@@ -6141,6 +6137,10 @@ void cik_update_cg(struct radeon_device *rdev,
		cik_enable_hdp_mgcg(rdev, enable);
		cik_enable_hdp_ls(rdev, enable);
	}

	if (block & RADEON_CG_BLOCK_VCE) {
		vce_v2_0_enable_mgcg(rdev, enable);
	}
}

static void cik_init_cg(struct radeon_device *rdev)
@@ -7490,6 +7490,20 @@ restart_ih:
			/* reset addr and status */
			WREG32_P(VM_CONTEXT1_CNTL2, 1, ~1);
			break;
		case 167: /* VCE */
			DRM_DEBUG("IH: VCE int: 0x%08x\n", src_data);
			switch (src_data) {
			case 0:
				radeon_fence_process(rdev, TN_RING_TYPE_VCE1_INDEX);
				break;
			case 1:
				radeon_fence_process(rdev, TN_RING_TYPE_VCE2_INDEX);
				break;
			default:
				DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data);
				break;
			}
			break;
		case 176: /* GFX RB CP_INT */
		case 177: /* GFX IB CP_INT */
			radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX);
@@ -7789,6 +7803,22 @@ static int cik_startup(struct radeon_device *rdev)
	if (r)
		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;

	r = radeon_vce_resume(rdev);
	if (!r) {
		r = vce_v2_0_resume(rdev);
		if (!r)
			r = radeon_fence_driver_start_ring(rdev,
							   TN_RING_TYPE_VCE1_INDEX);
		if (!r)
			r = radeon_fence_driver_start_ring(rdev,
							   TN_RING_TYPE_VCE2_INDEX);
	}
	if (r) {
		dev_err(rdev->dev, "VCE init error (%d).\n", r);
		rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
		rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
	}

	/* Enable IRQ */
	if (!rdev->irq.installed) {
		r = radeon_irq_kms_init(rdev);
@@ -7864,6 +7894,23 @@ static int cik_startup(struct radeon_device *rdev)
			DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
	}

	r = -ENOENT;

	ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
	if (ring->ring_size)
		r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
				     VCE_CMD_NO_OP);

	ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
	if (ring->ring_size)
		r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
				     VCE_CMD_NO_OP);

	if (!r)
		r = vce_v1_0_init(rdev);
	else if (r != -ENOENT)
		DRM_ERROR("radeon: failed initializing VCE (%d).\n", r);

	r = radeon_ib_pool_init(rdev);
	if (r) {
		dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
@@ -7934,6 +7981,7 @@ int cik_suspend(struct radeon_device *rdev)
	cik_sdma_enable(rdev, false);
	uvd_v1_0_fini(rdev);
	radeon_uvd_suspend(rdev);
	radeon_vce_suspend(rdev);
	cik_fini_pg(rdev);
	cik_fini_cg(rdev);
	cik_irq_suspend(rdev);
@@ -8066,6 +8114,17 @@ int cik_init(struct radeon_device *rdev)
		r600_ring_init(rdev, ring, 4096);
	}

	r = radeon_vce_init(rdev);
	if (!r) {
		ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
		ring->ring_obj = NULL;
		r600_ring_init(rdev, ring, 4096);

		ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
		ring->ring_obj = NULL;
		r600_ring_init(rdev, ring, 4096);
	}

	rdev->ih.ring_obj = NULL;
	r600_ih_ring_init(rdev, 64 * 1024);

@@ -8127,6 +8186,7 @@ void cik_fini(struct radeon_device *rdev)
	radeon_irq_kms_fini(rdev);
	uvd_v1_0_fini(rdev);
	radeon_uvd_fini(rdev);
	radeon_vce_fini(rdev);
	cik_pcie_gart_fini(rdev);
	r600_vram_scratch_fini(rdev);
	radeon_gem_fini(rdev);
@@ -8865,6 +8925,41 @@ int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
	return r;
}

int cik_set_vce_clocks(struct radeon_device *rdev, u32 evclk, u32 ecclk)
{
	int r, i;
	struct atom_clock_dividers dividers;
	u32 tmp;

	r = radeon_atom_get_clock_dividers(rdev, COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
					   ecclk, false, &dividers);
	if (r)
		return r;

	for (i = 0; i < 100; i++) {
		if (RREG32_SMC(CG_ECLK_STATUS) & ECLK_STATUS)
			break;
		mdelay(10);
	}
	if (i == 100)
		return -ETIMEDOUT;

	tmp = RREG32_SMC(CG_ECLK_CNTL);
	tmp &= ~(ECLK_DIR_CNTL_EN|ECLK_DIVIDER_MASK);
	tmp |= dividers.post_divider;
	WREG32_SMC(CG_ECLK_CNTL, tmp);

	for (i = 0; i < 100; i++) {
		if (RREG32_SMC(CG_ECLK_STATUS) & ECLK_STATUS)
			break;
		mdelay(10);
	}
	if (i == 100)
		return -ETIMEDOUT;

	return 0;
}

static void cik_pcie_gen3_enable(struct radeon_device *rdev)
{
	struct pci_dev *root = rdev->pdev->bus->self;
+1 −5
Original line number Diff line number Diff line
@@ -362,8 +362,6 @@ static int cik_sdma_gfx_resume(struct radeon_device *rdev)
		ring->wptr = 0;
		WREG32(SDMA0_GFX_RB_WPTR + reg_offset, ring->wptr << 2);

		ring->rptr = RREG32(SDMA0_GFX_RB_RPTR + reg_offset) >> 2;

		/* enable DMA RB */
		WREG32(SDMA0_GFX_RB_CNTL + reg_offset, rb_cntl | SDMA_RB_ENABLE);

@@ -713,11 +711,9 @@ bool cik_sdma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)
		mask = RADEON_RESET_DMA1;

	if (!(reset_mask & mask)) {
		radeon_ring_lockup_update(ring);
		radeon_ring_lockup_update(rdev, ring);
		return false;
	}
	/* force ring activities */
	radeon_ring_force_activity(rdev, ring);
	return radeon_ring_test_lockup(rdev, ring);
}

Loading