Commit d58ed707 authored by Leo Liu's avatar Leo Liu Committed by Alex Deucher
Browse files

drm/amdgpu/vcn1.0: use its own idle handler and begin use funcs



Because VCN1.0 power management and DPG mode are managed together with
JPEG1.0 under both HW and FW, so separated them from general VCN code.
Also the multiple instances case got removed, since VCN1.0 HW just have
a single instance.

v2: override work func with vcn1.0's own

Signed-off-by: default avatarLeo Liu <leo.liu@amd.com>
Reviewed-by: default avatarJames Zhu <James.Zhu@amd.com>
Reviewed-by: default avatarChristian König <christian.koenig@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent aaff8b44
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -39,9 +39,6 @@
#include "vcn/vcn_1_0_offset.h"
#include "vcn/vcn_1_0_sh_mask.h"

/* 1 second timeout */
#define VCN_IDLE_TIMEOUT	msecs_to_jiffies(1000)

/* Firmware Names */
#define FIRMWARE_RAVEN		"amdgpu/raven_vcn.bin"
#define FIRMWARE_PICASSO	"amdgpu/picasso_vcn.bin"
+3 −0
Original line number Diff line number Diff line
@@ -56,6 +56,9 @@
#define VCN_VID_IP_ADDRESS_2_0		0x0
#define VCN_AON_IP_ADDRESS_2_0		0x30000

/* 1 second timeout */
#define VCN_IDLE_TIMEOUT	msecs_to_jiffies(1000)

#define RREG32_SOC15_DPG_MODE(ip, inst, reg, mask, sram_sel) 				\
	({	WREG32_SOC15(ip, inst, mmUVD_DPG_LMA_MASK, mask); 			\
		WREG32_SOC15(ip, inst, mmUVD_DPG_LMA_CTL, 				\
+2 −1
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include "amdgpu_jpeg.h"
#include "soc15.h"
#include "soc15d.h"
#include "vcn_v1_0.h"

#include "vcn/vcn_1_0_offset.h"
#include "vcn/vcn_1_0_sh_mask.h"
@@ -561,7 +562,7 @@ static const struct amdgpu_ring_funcs jpeg_v1_0_decode_ring_vm_funcs = {
	.insert_start = jpeg_v1_0_decode_ring_insert_start,
	.insert_end = jpeg_v1_0_decode_ring_insert_end,
	.pad_ib = amdgpu_ring_generic_pad_ib,
	.begin_use = amdgpu_vcn_ring_begin_use,
	.begin_use = vcn_v1_0_ring_begin_use,
	.end_use = amdgpu_vcn_ring_end_use,
	.emit_wreg = jpeg_v1_0_decode_ring_emit_wreg,
	.emit_reg_wait = jpeg_v1_0_decode_ring_emit_reg_wait,
+88 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@

#include "amdgpu.h"
#include "amdgpu_vcn.h"
#include "amdgpu_pm.h"
#include "soc15.h"
#include "soc15d.h"
#include "soc15_common.h"
@@ -51,6 +52,8 @@ static int vcn_v1_0_set_powergating_state(void *handle, enum amd_powergating_sta
static int vcn_v1_0_pause_dpg_mode(struct amdgpu_device *adev,
				struct dpg_pause_state *new_state);

static void vcn_v1_0_idle_work_handler(struct work_struct *work);

/**
 * vcn_v1_0_early_init - set function pointers
 *
@@ -105,6 +108,9 @@ static int vcn_v1_0_sw_init(void *handle)
	if (r)
		return r;

	/* Override the work func */
	adev->vcn.idle_work.work.func = vcn_v1_0_idle_work_handler;

	if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
		const struct common_firmware_header *hdr;
		hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
@@ -1758,6 +1764,86 @@ static int vcn_v1_0_set_powergating_state(void *handle,
	return ret;
}

static void vcn_v1_0_idle_work_handler(struct work_struct *work)
{
	struct amdgpu_device *adev =
		container_of(work, struct amdgpu_device, vcn.idle_work.work);
	unsigned int fences = 0, i;

	for (i = 0; i < adev->vcn.num_enc_rings; ++i)
		fences += amdgpu_fence_count_emitted(&adev->vcn.inst->ring_enc[i]);

	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
		struct dpg_pause_state new_state;

		if (fences)
			new_state.fw_based = VCN_DPG_STATE__PAUSE;
		else
			new_state.fw_based = VCN_DPG_STATE__UNPAUSE;

		if (amdgpu_fence_count_emitted(&adev->jpeg.inst->ring_dec))
			new_state.jpeg = VCN_DPG_STATE__PAUSE;
		else
			new_state.jpeg = VCN_DPG_STATE__UNPAUSE;

		adev->vcn.pause_dpg_mode(adev, &new_state);
	}

	fences += amdgpu_fence_count_emitted(&adev->jpeg.inst->ring_dec);
	fences += amdgpu_fence_count_emitted(&adev->vcn.inst->ring_dec);

	if (fences == 0) {
		amdgpu_gfx_off_ctrl(adev, true);
		if (adev->pm.dpm_enabled)
			amdgpu_dpm_enable_uvd(adev, false);
		else
			amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
			       AMD_PG_STATE_GATE);
	} else {
		schedule_delayed_work(&adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
	}
}

void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring)
{
	struct amdgpu_device *adev = ring->adev;
	bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.idle_work);

	if (set_clocks) {
		amdgpu_gfx_off_ctrl(adev, false);
		if (adev->pm.dpm_enabled)
			amdgpu_dpm_enable_uvd(adev, true);
		else
			amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
			       AMD_PG_STATE_UNGATE);
	}

	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
		struct dpg_pause_state new_state;
		unsigned int fences = 0, i;

		for (i = 0; i < adev->vcn.num_enc_rings; ++i)
			fences += amdgpu_fence_count_emitted(&adev->vcn.inst->ring_enc[i]);

		if (fences)
			new_state.fw_based = VCN_DPG_STATE__PAUSE;
		else
			new_state.fw_based = VCN_DPG_STATE__UNPAUSE;

		if (amdgpu_fence_count_emitted(&adev->jpeg.inst->ring_dec))
			new_state.jpeg = VCN_DPG_STATE__PAUSE;
		else
			new_state.jpeg = VCN_DPG_STATE__UNPAUSE;

		if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC)
			new_state.fw_based = VCN_DPG_STATE__PAUSE;
		else if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG)
			new_state.jpeg = VCN_DPG_STATE__PAUSE;

		adev->vcn.pause_dpg_mode(adev, &new_state);
	}
}

static const struct amd_ip_funcs vcn_v1_0_ip_funcs = {
	.name = "vcn_v1_0",
	.early_init = vcn_v1_0_early_init,
@@ -1804,7 +1890,7 @@ static const struct amdgpu_ring_funcs vcn_v1_0_dec_ring_vm_funcs = {
	.insert_start = vcn_v1_0_dec_ring_insert_start,
	.insert_end = vcn_v1_0_dec_ring_insert_end,
	.pad_ib = amdgpu_ring_generic_pad_ib,
	.begin_use = amdgpu_vcn_ring_begin_use,
	.begin_use = vcn_v1_0_ring_begin_use,
	.end_use = amdgpu_vcn_ring_end_use,
	.emit_wreg = vcn_v1_0_dec_ring_emit_wreg,
	.emit_reg_wait = vcn_v1_0_dec_ring_emit_reg_wait,
@@ -1836,7 +1922,7 @@ static const struct amdgpu_ring_funcs vcn_v1_0_enc_ring_vm_funcs = {
	.insert_nop = amdgpu_ring_insert_nop,
	.insert_end = vcn_v1_0_enc_ring_insert_end,
	.pad_ib = amdgpu_ring_generic_pad_ib,
	.begin_use = amdgpu_vcn_ring_begin_use,
	.begin_use = vcn_v1_0_ring_begin_use,
	.end_use = amdgpu_vcn_ring_end_use,
	.emit_wreg = vcn_v1_0_enc_ring_emit_wreg,
	.emit_reg_wait = vcn_v1_0_enc_ring_emit_reg_wait,
+2 −0
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@
#ifndef __VCN_V1_0_H__
#define __VCN_V1_0_H__

void vcn_v1_0_ring_begin_use(struct amdgpu_ring *ring);

extern const struct amdgpu_ip_block_version vcn_v1_0_ip_block;

#endif