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

Commit 42e169be authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge branch 'drm-fixes-3.12' of git://people.freedesktop.org/~agd5f/linux into drm-fixes

Radeon drm fixes for 3.12.  All over the place (display, dpm, uvd, etc.).
Also adds a couple more berlin pci ids.

* 'drm-fixes-3.12' of git://people.freedesktop.org/~agd5f/linux: (25 commits)
  drm/radeon/dpm: add bapm callback for kb/kv
  drm/radeon/dpm: add bapm callback for trinity
  drm/radeon/dpm: add infrastructure to properly handle bapm
  drm/radeon/dpm: handle bapm on kb/kv
  drm/radeon/dpm: handle bapm on trinity
  drm/radeon: expose DPM thermal thresholds through sysfs
  drm/radeon: simplify driver data retrieval
  drm/radeon/atom: workaround vbios bug in transmitter table on rs880 (v2)
  drm/radeon/dpm: fix fallback for empty UVD clocks
  drm/radeon: add command submission tracepoint
  drm/radeon: remove stale radeon_fence_retire tracepoint
  drm/radeon/r6xx: add a stubbed out set_uvd_clocks callback
  drm/radeon: fix typo in PG flags
  drm/radeon: add some additional berlin pci ids
  drm/radeon/cik: update gpu_init for an additional berlin gpu
  drm/radeon: add spinlocks for indirect register accesss
  drm/radeon: protect concurrent smc register access with a spinlock
  drm/radeon: dpm updates for KV
  drm/radeon: signedness bug in kv_dpm.c
  drm/radeon: clean up r600_free_extended_power_table()
  ...
parents 2e837813 b7a5ae97
Loading
Loading
Loading
Loading
+15 −8
Original line number Diff line number Diff line
@@ -707,8 +707,9 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
	switch (connector->connector_type) {
	case DRM_MODE_CONNECTOR_DVII:
	case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
		if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
		    radeon_audio)
		if ((radeon_connector->audio == RADEON_AUDIO_ENABLE) ||
		    (drm_detect_hdmi_monitor(radeon_connector->edid) &&
		     (radeon_connector->audio == RADEON_AUDIO_AUTO)))
			return ATOM_ENCODER_MODE_HDMI;
		else if (radeon_connector->use_digital)
			return ATOM_ENCODER_MODE_DVI;
@@ -718,8 +719,9 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
	case DRM_MODE_CONNECTOR_DVID:
	case DRM_MODE_CONNECTOR_HDMIA:
	default:
		if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
		    radeon_audio)
		if ((radeon_connector->audio == RADEON_AUDIO_ENABLE) ||
		    (drm_detect_hdmi_monitor(radeon_connector->edid) &&
		     (radeon_connector->audio == RADEON_AUDIO_AUTO)))
			return ATOM_ENCODER_MODE_HDMI;
		else
			return ATOM_ENCODER_MODE_DVI;
@@ -732,8 +734,9 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
		if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
		    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
			return ATOM_ENCODER_MODE_DP;
		else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
			 radeon_audio)
		else if ((radeon_connector->audio == RADEON_AUDIO_ENABLE) ||
			 (drm_detect_hdmi_monitor(radeon_connector->edid) &&
			  (radeon_connector->audio == RADEON_AUDIO_AUTO)))
			return ATOM_ENCODER_MODE_HDMI;
		else
			return ATOM_ENCODER_MODE_DVI;
@@ -1647,8 +1650,12 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
			atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
			/* some early dce3.2 boards have a bug in their transmitter control table */
			if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730))
			/* some dce3.x boards have a bug in their transmitter control table.
			 * ACTION_ENABLE_OUTPUT can probably be dropped since ACTION_ENABLE
			 * does the same thing and more.
			 */
			if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730) &&
			    (rdev->family != CHIP_RS880))
				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
		}
		if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
+26 −13
Original line number Diff line number Diff line
@@ -47,10 +47,11 @@ int ci_copy_bytes_to_smc(struct radeon_device *rdev,
			 u32 smc_start_address,
			 const u8 *src, u32 byte_count, u32 limit)
{
	unsigned long flags;
	u32 data, original_data;
	u32 addr;
	u32 extra_shift;
	int ret;
	int ret = 0;

	if (smc_start_address & 3)
		return -EINVAL;
@@ -59,13 +60,14 @@ int ci_copy_bytes_to_smc(struct radeon_device *rdev,

	addr = smc_start_address;

	spin_lock_irqsave(&rdev->smc_idx_lock, flags);
	while (byte_count >= 4) {
		/* SMC address space is BE */
		data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];

		ret = ci_set_smc_sram_address(rdev, addr, limit);
		if (ret)
			return ret;
			goto done;

		WREG32(SMC_IND_DATA_0, data);

@@ -80,7 +82,7 @@ int ci_copy_bytes_to_smc(struct radeon_device *rdev,

		ret = ci_set_smc_sram_address(rdev, addr, limit);
		if (ret)
			return ret;
			goto done;

		original_data = RREG32(SMC_IND_DATA_0);

@@ -97,11 +99,15 @@ int ci_copy_bytes_to_smc(struct radeon_device *rdev,

		ret = ci_set_smc_sram_address(rdev, addr, limit);
		if (ret)
			return ret;
			goto done;

		WREG32(SMC_IND_DATA_0, data);
	}
	return 0;

done:
	spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);

	return ret;
}

void ci_start_smc(struct radeon_device *rdev)
@@ -197,6 +203,7 @@ PPSMC_Result ci_wait_for_smc_inactive(struct radeon_device *rdev)

int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit)
{
	unsigned long flags;
	u32 ucode_start_address;
	u32 ucode_size;
	const u8 *src;
@@ -219,6 +226,7 @@ int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit)
		return -EINVAL;

	src = (const u8 *)rdev->smc_fw->data;
	spin_lock_irqsave(&rdev->smc_idx_lock, flags);
	WREG32(SMC_IND_INDEX_0, ucode_start_address);
	WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0);
	while (ucode_size >= 4) {
@@ -231,6 +239,7 @@ int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit)
		ucode_size -= 4;
	}
	WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0);
	spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);

	return 0;
}
@@ -238,25 +247,29 @@ int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit)
int ci_read_smc_sram_dword(struct radeon_device *rdev,
			   u32 smc_address, u32 *value, u32 limit)
{
	unsigned long flags;
	int ret;

	spin_lock_irqsave(&rdev->smc_idx_lock, flags);
	ret = ci_set_smc_sram_address(rdev, smc_address, limit);
	if (ret)
		return ret;

	if (ret == 0)
		*value = RREG32(SMC_IND_DATA_0);
	return 0;
	spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);

	return ret;
}

int ci_write_smc_sram_dword(struct radeon_device *rdev,
			    u32 smc_address, u32 value, u32 limit)
{
	unsigned long flags;
	int ret;

	spin_lock_irqsave(&rdev->smc_idx_lock, flags);
	ret = ci_set_smc_sram_address(rdev, smc_address, limit);
	if (ret)
		return ret;

	if (ret == 0)
		WREG32(SMC_IND_DATA_0, value);
	return 0;
	spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);

	return ret;
}
+29 −7
Original line number Diff line number Diff line
@@ -77,6 +77,8 @@ static void cik_pcie_gen3_enable(struct radeon_device *rdev);
static void cik_program_aspm(struct radeon_device *rdev);
static void cik_init_pg(struct radeon_device *rdev);
static void cik_init_cg(struct radeon_device *rdev);
static void cik_enable_gui_idle_interrupt(struct radeon_device *rdev,
					  bool enable);

/* get temperature in millidegrees */
int ci_get_temp(struct radeon_device *rdev)
@@ -120,20 +122,27 @@ int kv_get_temp(struct radeon_device *rdev)
 */
u32 cik_pciep_rreg(struct radeon_device *rdev, u32 reg)
{
	unsigned long flags;
	u32 r;

	spin_lock_irqsave(&rdev->pciep_idx_lock, flags);
	WREG32(PCIE_INDEX, reg);
	(void)RREG32(PCIE_INDEX);
	r = RREG32(PCIE_DATA);
	spin_unlock_irqrestore(&rdev->pciep_idx_lock, flags);
	return r;
}

void cik_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v)
{
	unsigned long flags;

	spin_lock_irqsave(&rdev->pciep_idx_lock, flags);
	WREG32(PCIE_INDEX, reg);
	(void)RREG32(PCIE_INDEX);
	WREG32(PCIE_DATA, v);
	(void)RREG32(PCIE_DATA);
	spin_unlock_irqrestore(&rdev->pciep_idx_lock, flags);
}

static const u32 spectre_rlc_save_restore_register_list[] =
@@ -2722,7 +2731,8 @@ static void cik_gpu_init(struct radeon_device *rdev)
		} else if ((rdev->pdev->device == 0x1309) ||
			   (rdev->pdev->device == 0x130A) ||
			   (rdev->pdev->device == 0x130D) ||
			   (rdev->pdev->device == 0x1313)) {
			   (rdev->pdev->device == 0x1313) ||
			   (rdev->pdev->device == 0x131D)) {
			rdev->config.cik.max_cu_per_sh = 6;
			rdev->config.cik.max_backends_per_se = 2;
		} else if ((rdev->pdev->device == 0x1306) ||
@@ -4013,6 +4023,8 @@ static int cik_cp_resume(struct radeon_device *rdev)
{
	int r;

	cik_enable_gui_idle_interrupt(rdev, false);

	r = cik_cp_load_microcode(rdev);
	if (r)
		return r;
@@ -4024,6 +4036,8 @@ static int cik_cp_resume(struct radeon_device *rdev)
	if (r)
		return r;

	cik_enable_gui_idle_interrupt(rdev, true);

	return 0;
}

@@ -5376,7 +5390,9 @@ static void cik_enable_hdp_ls(struct radeon_device *rdev,
void cik_update_cg(struct radeon_device *rdev,
		   u32 block, bool enable)
{

	if (block & RADEON_CG_BLOCK_GFX) {
		cik_enable_gui_idle_interrupt(rdev, false);
		/* order matters! */
		if (enable) {
			cik_enable_mgcg(rdev, true);
@@ -5385,6 +5401,7 @@ void cik_update_cg(struct radeon_device *rdev,
			cik_enable_cgcg(rdev, false);
			cik_enable_mgcg(rdev, false);
		}
		cik_enable_gui_idle_interrupt(rdev, true);
	}

	if (block & RADEON_CG_BLOCK_MC) {
@@ -5541,7 +5558,7 @@ static void cik_enable_gfx_cgpg(struct radeon_device *rdev,
{
	u32 data, orig;

	if (enable && (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_CG)) {
	if (enable && (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_PG)) {
		orig = data = RREG32(RLC_PG_CNTL);
		data |= GFX_PG_ENABLE;
		if (orig != data)
@@ -5805,7 +5822,7 @@ static void cik_init_pg(struct radeon_device *rdev)
	if (rdev->pg_flags) {
		cik_enable_sck_slowdown_on_pu(rdev, true);
		cik_enable_sck_slowdown_on_pd(rdev, true);
		if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_CG) {
		if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_PG) {
			cik_init_gfx_cgpg(rdev);
			cik_enable_cp_pg(rdev, true);
			cik_enable_gds_pg(rdev, true);
@@ -5819,7 +5836,7 @@ static void cik_fini_pg(struct radeon_device *rdev)
{
	if (rdev->pg_flags) {
		cik_update_gfx_pg(rdev, false);
		if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_CG) {
		if (rdev->pg_flags & RADEON_PG_SUPPORT_GFX_PG) {
			cik_enable_cp_pg(rdev, false);
			cik_enable_gds_pg(rdev, false);
		}
@@ -5895,7 +5912,9 @@ static void cik_disable_interrupt_state(struct radeon_device *rdev)
	u32 tmp;

	/* gfx ring */
	WREG32(CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
	tmp = RREG32(CP_INT_CNTL_RING0) &
		(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
	WREG32(CP_INT_CNTL_RING0, tmp);
	/* sdma */
	tmp = RREG32(SDMA0_CNTL + SDMA0_REGISTER_OFFSET) & ~TRAP_ENABLE;
	WREG32(SDMA0_CNTL + SDMA0_REGISTER_OFFSET, tmp);
@@ -6036,8 +6055,7 @@ static int cik_irq_init(struct radeon_device *rdev)
 */
int cik_irq_set(struct radeon_device *rdev)
{
	u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE |
		PRIV_INSTR_INT_ENABLE | PRIV_REG_INT_ENABLE;
	u32 cp_int_cntl;
	u32 cp_m1p0, cp_m1p1, cp_m1p2, cp_m1p3;
	u32 cp_m2p0, cp_m2p1, cp_m2p2, cp_m2p3;
	u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0;
@@ -6058,6 +6076,10 @@ int cik_irq_set(struct radeon_device *rdev)
		return 0;
	}

	cp_int_cntl = RREG32(CP_INT_CNTL_RING0) &
		(CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE);
	cp_int_cntl |= PRIV_INSTR_INT_ENABLE | PRIV_REG_INT_ENABLE;

	hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN;
	hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN;
	hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN;
+10 −2
Original line number Diff line number Diff line
@@ -28,22 +28,30 @@
static u32 dce6_endpoint_rreg(struct radeon_device *rdev,
			      u32 block_offset, u32 reg)
{
	unsigned long flags;
	u32 r;

	spin_lock_irqsave(&rdev->end_idx_lock, flags);
	WREG32(AZ_F0_CODEC_ENDPOINT_INDEX + block_offset, reg);
	r = RREG32(AZ_F0_CODEC_ENDPOINT_DATA + block_offset);
	spin_unlock_irqrestore(&rdev->end_idx_lock, flags);

	return r;
}

static void dce6_endpoint_wreg(struct radeon_device *rdev,
			       u32 block_offset, u32 reg, u32 v)
{
	unsigned long flags;

	spin_lock_irqsave(&rdev->end_idx_lock, flags);
	if (ASIC_IS_DCE8(rdev))
		WREG32(AZ_F0_CODEC_ENDPOINT_INDEX + block_offset, reg);
	else
		WREG32(AZ_F0_CODEC_ENDPOINT_INDEX + block_offset,
		       AZ_ENDPOINT_REG_WRITE_EN | AZ_ENDPOINT_REG_INDEX(reg));
	WREG32(AZ_F0_CODEC_ENDPOINT_DATA + block_offset, v);
	spin_unlock_irqrestore(&rdev->end_idx_lock, flags);
}

#define RREG32_ENDPOINT(block, reg) dce6_endpoint_rreg(rdev, (block), (reg))
@@ -86,12 +94,12 @@ void dce6_afmt_select_pin(struct drm_encoder *encoder)
	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
	struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
	u32 offset = dig->afmt->offset;
	u32 id = dig->afmt->pin->id;

	if (!dig->afmt->pin)
		return;

	WREG32(AFMT_AUDIO_SRC_CONTROL + offset, AFMT_AUDIO_SRC_SELECT(id));
	WREG32(AFMT_AUDIO_SRC_CONTROL + offset,
	       AFMT_AUDIO_SRC_SELECT(dig->afmt->pin->id));
}

void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder)
+129 −34
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ static int kv_calculate_dpm_settings(struct radeon_device *rdev);
static void kv_enable_new_levels(struct radeon_device *rdev);
static void kv_program_nbps_index_settings(struct radeon_device *rdev,
					   struct radeon_ps *new_rps);
static int kv_set_enabled_level(struct radeon_device *rdev, u32 level);
static int kv_set_enabled_levels(struct radeon_device *rdev);
static int kv_force_dpm_highest(struct radeon_device *rdev);
static int kv_force_dpm_lowest(struct radeon_device *rdev);
@@ -519,7 +520,7 @@ static int kv_set_dpm_boot_state(struct radeon_device *rdev)

static void kv_program_vc(struct radeon_device *rdev)
{
	WREG32_SMC(CG_FTV_0, 0x3FFFC000);
	WREG32_SMC(CG_FTV_0, 0x3FFFC100);
}

static void kv_clear_vc(struct radeon_device *rdev)
@@ -638,7 +639,10 @@ static int kv_force_lowest_valid(struct radeon_device *rdev)

static int kv_unforce_levels(struct radeon_device *rdev)
{
	if (rdev->family == CHIP_KABINI)
		return kv_notify_message_to_smu(rdev, PPSMC_MSG_NoForcedLevel);
	else
		return kv_set_enabled_levels(rdev);
}

static int kv_update_sclk_t(struct radeon_device *rdev)
@@ -667,9 +671,8 @@ static int kv_program_bootup_state(struct radeon_device *rdev)
		&rdev->pm.dpm.dyn_state.vddc_dependency_on_sclk;

	if (table && table->count) {
		for (i = pi->graphics_dpm_level_count - 1; i >= 0; i--) {
			if ((table->entries[i].clk == pi->boot_pl.sclk) ||
			    (i == 0))
		for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) {
			if (table->entries[i].clk == pi->boot_pl.sclk)
				break;
		}

@@ -682,9 +685,8 @@ static int kv_program_bootup_state(struct radeon_device *rdev)
		if (table->num_max_dpm_entries == 0)
			return -EINVAL;

		for (i = pi->graphics_dpm_level_count - 1; i >= 0; i--) {
			if ((table->entries[i].sclk_frequency == pi->boot_pl.sclk) ||
			    (i == 0))
		for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) {
			if (table->entries[i].sclk_frequency == pi->boot_pl.sclk)
				break;
		}

@@ -1078,6 +1080,13 @@ static int kv_enable_ulv(struct radeon_device *rdev, bool enable)
					PPSMC_MSG_EnableULV : PPSMC_MSG_DisableULV);
}

static void kv_reset_acp_boot_level(struct radeon_device *rdev)
{
	struct kv_power_info *pi = kv_get_pi(rdev);

	pi->acp_boot_level = 0xff;
}

static void kv_update_current_ps(struct radeon_device *rdev,
				 struct radeon_ps *rps)
{
@@ -1100,6 +1109,18 @@ static void kv_update_requested_ps(struct radeon_device *rdev,
	pi->requested_rps.ps_priv = &pi->requested_ps;
}

void kv_dpm_enable_bapm(struct radeon_device *rdev, bool enable)
{
	struct kv_power_info *pi = kv_get_pi(rdev);
	int ret;

	if (pi->bapm_enable) {
		ret = kv_smc_bapm_enable(rdev, enable);
		if (ret)
			DRM_ERROR("kv_smc_bapm_enable failed\n");
	}
}

int kv_dpm_enable(struct radeon_device *rdev)
{
	struct kv_power_info *pi = kv_get_pi(rdev);
@@ -1192,6 +1213,8 @@ int kv_dpm_enable(struct radeon_device *rdev)
		return ret;
	}

	kv_reset_acp_boot_level(rdev);

	if (rdev->irq.installed &&
	    r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) {
		ret = kv_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX);
@@ -1203,6 +1226,12 @@ int kv_dpm_enable(struct radeon_device *rdev)
		radeon_irq_set(rdev);
	}

	ret = kv_smc_bapm_enable(rdev, false);
	if (ret) {
		DRM_ERROR("kv_smc_bapm_enable failed\n");
		return ret;
	}

	/* powerdown unused blocks for now */
	kv_dpm_powergate_acp(rdev, true);
	kv_dpm_powergate_samu(rdev, true);
@@ -1226,6 +1255,8 @@ void kv_dpm_disable(struct radeon_device *rdev)
			     RADEON_CG_BLOCK_BIF |
			     RADEON_CG_BLOCK_HDP), false);

	kv_smc_bapm_enable(rdev, false);

	/* powerup blocks */
	kv_dpm_powergate_acp(rdev, false);
	kv_dpm_powergate_samu(rdev, false);
@@ -1450,6 +1481,39 @@ static int kv_update_samu_dpm(struct radeon_device *rdev, bool gate)
	return kv_enable_samu_dpm(rdev, !gate);
}

static u8 kv_get_acp_boot_level(struct radeon_device *rdev)
{
	u8 i;
	struct radeon_clock_voltage_dependency_table *table =
		&rdev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table;

	for (i = 0; i < table->count; i++) {
		if (table->entries[i].clk >= 0) /* XXX */
			break;
	}

	if (i >= table->count)
		i = table->count - 1;

	return i;
}

static void kv_update_acp_boot_level(struct radeon_device *rdev)
{
	struct kv_power_info *pi = kv_get_pi(rdev);
	u8 acp_boot_level;

	if (!pi->caps_stable_p_state) {
		acp_boot_level = kv_get_acp_boot_level(rdev);
		if (acp_boot_level != pi->acp_boot_level) {
			pi->acp_boot_level = acp_boot_level;
			kv_send_msg_to_smc_with_parameter(rdev,
							  PPSMC_MSG_ACPDPM_SetEnabledMask,
							  (1 << pi->acp_boot_level));
		}
	}
}

static int kv_update_acp_dpm(struct radeon_device *rdev, bool gate)
{
	struct kv_power_info *pi = kv_get_pi(rdev);
@@ -1461,7 +1525,7 @@ static int kv_update_acp_dpm(struct radeon_device *rdev, bool gate)
		if (pi->caps_stable_p_state)
			pi->acp_boot_level = table->count - 1;
		else
			pi->acp_boot_level = 0;
			pi->acp_boot_level = kv_get_acp_boot_level(rdev);

		ret = kv_copy_bytes_to_smc(rdev,
					   pi->dpm_table_start +
@@ -1588,13 +1652,11 @@ static void kv_set_valid_clock_range(struct radeon_device *rdev,
			}
		}

		for (i = pi->graphics_dpm_level_count - 1; i >= 0; i--) {
			if ((table->entries[i].clk <= new_ps->levels[new_ps->num_levels -1].sclk) ||
			    (i == 0)) {
				pi->highest_valid = i;
		for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) {
			if (table->entries[i].clk <= new_ps->levels[new_ps->num_levels - 1].sclk)
				break;
		}
		}
		pi->highest_valid = i;

		if (pi->lowest_valid > pi->highest_valid) {
			if ((new_ps->levels[0].sclk - table->entries[pi->highest_valid].clk) >
@@ -1615,14 +1677,12 @@ static void kv_set_valid_clock_range(struct radeon_device *rdev,
			}
		}

		for (i = pi->graphics_dpm_level_count - 1; i >= 0; i--) {
		for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) {
			if (table->entries[i].sclk_frequency <=
			    new_ps->levels[new_ps->num_levels - 1].sclk ||
			    i == 0) {
				pi->highest_valid = i;
			    new_ps->levels[new_ps->num_levels - 1].sclk)
				break;
		}
		}
		pi->highest_valid = i;

		if (pi->lowest_valid > pi->highest_valid) {
			if ((new_ps->levels[0].sclk -
@@ -1724,6 +1784,14 @@ int kv_dpm_set_power_state(struct radeon_device *rdev)
			     RADEON_CG_BLOCK_BIF |
			     RADEON_CG_BLOCK_HDP), false);

	if (pi->bapm_enable) {
		ret = kv_smc_bapm_enable(rdev, rdev->pm.dpm.ac_power);
		if (ret) {
			DRM_ERROR("kv_smc_bapm_enable failed\n");
			return ret;
		}
	}

	if (rdev->family == CHIP_KABINI) {
		if (pi->enable_dpm) {
			kv_set_valid_clock_range(rdev, new_ps);
@@ -1775,6 +1843,7 @@ int kv_dpm_set_power_state(struct radeon_device *rdev)
				return ret;
			}
#endif
			kv_update_acp_boot_level(rdev);
			kv_update_sclk_t(rdev);
			kv_enable_nb_dpm(rdev);
		}
@@ -1806,12 +1875,23 @@ void kv_dpm_setup_asic(struct radeon_device *rdev)

void kv_dpm_reset_asic(struct radeon_device *rdev)
{
	struct kv_power_info *pi = kv_get_pi(rdev);

	if (rdev->family == CHIP_KABINI) {
		kv_force_lowest_valid(rdev);
		kv_init_graphics_levels(rdev);
		kv_program_bootup_state(rdev);
		kv_upload_dpm_settings(rdev);
		kv_force_lowest_valid(rdev);
		kv_unforce_levels(rdev);
	} else {
		kv_init_graphics_levels(rdev);
		kv_program_bootup_state(rdev);
		kv_freeze_sclk_dpm(rdev, true);
		kv_upload_dpm_settings(rdev);
		kv_freeze_sclk_dpm(rdev, false);
		kv_set_enabled_level(rdev, pi->graphics_boot_level);
	}
}

//XXX use sumo_dpm_display_configuration_changed
@@ -1871,12 +1951,15 @@ static int kv_force_dpm_highest(struct radeon_device *rdev)
	if (ret)
		return ret;

	for (i = SMU7_MAX_LEVELS_GRAPHICS - 1; i >= 0; i--) {
	for (i = SMU7_MAX_LEVELS_GRAPHICS - 1; i > 0; i--) {
		if (enable_mask & (1 << i))
			break;
	}

	if (rdev->family == CHIP_KABINI)
		return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i);
	else
		return kv_set_enabled_level(rdev, i);
}

static int kv_force_dpm_lowest(struct radeon_device *rdev)
@@ -1893,7 +1976,10 @@ static int kv_force_dpm_lowest(struct radeon_device *rdev)
			break;
	}

	if (rdev->family == CHIP_KABINI)
		return kv_send_msg_to_smc_with_parameter(rdev, PPSMC_MSG_DPM_ForceState, i);
	else
		return kv_set_enabled_level(rdev, i);
}

static u8 kv_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
@@ -1911,9 +1997,9 @@ static u8 kv_get_sleep_divider_id_from_clock(struct radeon_device *rdev,
	if (!pi->caps_sclk_ds)
		return 0;

	for (i = KV_MAX_DEEPSLEEP_DIVIDER_ID; i <= 0; i--) {
	for (i = KV_MAX_DEEPSLEEP_DIVIDER_ID; i > 0; i--) {
		temp = sclk / sumo_get_sleep_divider_from_id(i);
		if ((temp >= min) || (i == 0))
		if (temp >= min)
			break;
	}

@@ -2039,12 +2125,12 @@ static void kv_apply_state_adjust_rules(struct radeon_device *rdev,
		ps->dpmx_nb_ps_lo = 0x1;
		ps->dpmx_nb_ps_hi = 0x0;
	} else {
		ps->dpm0_pg_nb_ps_lo = 0x1;
		ps->dpm0_pg_nb_ps_lo = 0x3;
		ps->dpm0_pg_nb_ps_hi = 0x0;
		ps->dpmx_nb_ps_lo = 0x2;
		ps->dpmx_nb_ps_hi = 0x1;
		ps->dpmx_nb_ps_lo = 0x3;
		ps->dpmx_nb_ps_hi = 0x0;

		if (pi->sys_info.nb_dpm_enable && pi->battery_state) {
		if (pi->sys_info.nb_dpm_enable) {
			force_high = (mclk >= pi->sys_info.nbp_memory_clock[3]) ||
				pi->video_start || (rdev->pm.dpm.new_active_crtc_count >= 3) ||
				pi->disable_nb_ps3_in_battery;
@@ -2210,6 +2296,15 @@ static void kv_enable_new_levels(struct radeon_device *rdev)
	}
}

static int kv_set_enabled_level(struct radeon_device *rdev, u32 level)
{
	u32 new_mask = (1 << level);

	return kv_send_msg_to_smc_with_parameter(rdev,
						 PPSMC_MSG_SCLKDPM_SetEnabledMask,
						 new_mask);
}

static int kv_set_enabled_levels(struct radeon_device *rdev)
{
	struct kv_power_info *pi = kv_get_pi(rdev);
Loading