Commit ed9d2053 authored by Bokun Zhang's avatar Bokun Zhang Committed by Alex Deucher
Browse files

drm/amdgpu: Complete multimedia bandwidth interface



- Update SRIOV PF2VF header with latest revision

- Extend existing function in amdgpu_virt.c to read MM bandwidth config
  from PF2VF message

- Add SRIOV Sienna Cichlid codec array and update the bandwidth with
  PF2VF message

v2: squash in removal of unused variable (Alex)

Signed-off-by: default avatarBokun Zhang <bokun.zhang@amd.com>
Reviewed-by: default avatarMonk liu <monk.liu@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 2b2339ee
Loading
Loading
Loading
Loading
+56 −0
Original line number Diff line number Diff line
@@ -432,6 +432,9 @@ static int amdgpu_virt_read_pf2vf_data(struct amdgpu_device *adev)
	uint32_t checksum;
	uint32_t checkval;

	uint32_t i;
	uint32_t tmp;

	if (adev->virt.fw_reserve.p_pf2vf == NULL)
		return -EINVAL;

@@ -472,6 +475,27 @@ static int amdgpu_virt_read_pf2vf_data(struct amdgpu_device *adev)
		adev->virt.reg_access =
			((struct amd_sriov_msg_pf2vf_info *)pf2vf_info)->reg_access_flags.all;

		adev->virt.decode_max_dimension_pixels = 0;
		adev->virt.decode_max_frame_pixels = 0;
		adev->virt.encode_max_dimension_pixels = 0;
		adev->virt.encode_max_frame_pixels = 0;
		adev->virt.is_mm_bw_enabled = false;
		for (i = 0; i < AMD_SRIOV_MSG_RESERVE_VCN_INST; i++) {
			tmp = ((struct amd_sriov_msg_pf2vf_info *)pf2vf_info)->mm_bw_management[i].decode_max_dimension_pixels;
			adev->virt.decode_max_dimension_pixels = max(tmp, adev->virt.decode_max_dimension_pixels);

			tmp = ((struct amd_sriov_msg_pf2vf_info *)pf2vf_info)->mm_bw_management[i].decode_max_frame_pixels;
			adev->virt.decode_max_frame_pixels = max(tmp, adev->virt.decode_max_frame_pixels);

			tmp = ((struct amd_sriov_msg_pf2vf_info *)pf2vf_info)->mm_bw_management[i].encode_max_dimension_pixels;
			adev->virt.encode_max_dimension_pixels = max(tmp, adev->virt.encode_max_dimension_pixels);

			tmp = ((struct amd_sriov_msg_pf2vf_info *)pf2vf_info)->mm_bw_management[i].encode_max_frame_pixels;
			adev->virt.encode_max_frame_pixels = max(tmp, adev->virt.encode_max_frame_pixels);
		}
		if((adev->virt.decode_max_dimension_pixels > 0) || (adev->virt.encode_max_dimension_pixels > 0))
			adev->virt.is_mm_bw_enabled = true;

		break;
	default:
		DRM_ERROR("invalid pf2vf version\n");
@@ -744,3 +768,35 @@ enum amdgpu_sriov_vf_mode amdgpu_virt_get_sriov_vf_mode(struct amdgpu_device *ad

	return mode;
}

void amdgpu_virt_update_sriov_video_codec(struct amdgpu_device *adev,
			struct amdgpu_video_codec_info *encode, uint32_t encode_array_size,
			struct amdgpu_video_codec_info *decode, uint32_t decode_array_size)
{
	uint32_t i;

	if (!adev->virt.is_mm_bw_enabled)
		return;

	if (encode) {
		for (i = 0; i < encode_array_size; i++) {
			encode[i].max_width = adev->virt.encode_max_dimension_pixels;
			encode[i].max_pixels_per_frame = adev->virt.encode_max_frame_pixels;
			if (encode[i].max_width > 0)
				encode[i].max_height = encode[i].max_pixels_per_frame / encode[i].max_width;
			else
				encode[i].max_height = 0;
		}
	}

	if (decode) {
		for (i = 0; i < decode_array_size; i++) {
			decode[i].max_width = adev->virt.decode_max_dimension_pixels;
			decode[i].max_pixels_per_frame = adev->virt.decode_max_frame_pixels;
			if (decode[i].max_width > 0)
				decode[i].max_height = decode[i].max_pixels_per_frame / decode[i].max_width;
			else
				decode[i].max_height = 0;
		}
	}
}
+13 −0
Original line number Diff line number Diff line
@@ -233,8 +233,17 @@ struct amdgpu_virt {
	/* vf2pf message */
	struct delayed_work vf2pf_work;
	uint32_t vf2pf_update_interval_ms;

	/* multimedia bandwidth config */
	bool     is_mm_bw_enabled;
	uint32_t decode_max_dimension_pixels;
	uint32_t decode_max_frame_pixels;
	uint32_t encode_max_dimension_pixels;
	uint32_t encode_max_frame_pixels;
};

struct amdgpu_video_codec_info;

#define amdgpu_sriov_enabled(adev) \
((adev)->virt.caps & AMDGPU_SRIOV_CAPS_ENABLE_IOV)

@@ -307,4 +316,8 @@ int amdgpu_virt_enable_access_debugfs(struct amdgpu_device *adev);
void amdgpu_virt_disable_access_debugfs(struct amdgpu_device *adev);

enum amdgpu_sriov_vf_mode amdgpu_virt_get_sriov_vf_mode(struct amdgpu_device *adev);

void amdgpu_virt_update_sriov_video_codec(struct amdgpu_device *adev,
			struct amdgpu_video_codec_info *encode, uint32_t encode_array_size,
			struct amdgpu_video_codec_info *decode, uint32_t decode_array_size);
#endif
+48 −6
Original line number Diff line number Diff line
@@ -56,6 +56,8 @@

#define AMD_SRIOV_MSG_RESERVE_UCODE		24

#define AMD_SRIOV_MSG_RESERVE_VCN_INST 4

enum amd_sriov_ucode_engine_id {
	AMD_SRIOV_UCODE_ID_VCE = 0,
	AMD_SRIOV_UCODE_ID_UVD,
@@ -98,9 +100,9 @@ union amd_sriov_msg_feature_flags {

union amd_sriov_reg_access_flags {
	struct {
		uint32_t vf_reg_psp_access_ih    : 1;
		uint32_t vf_reg_rlc_access_mmhub : 1;
		uint32_t vf_reg_rlc_access_gc    : 1;
		uint32_t vf_reg_access_ih 	 : 1;
		uint32_t vf_reg_access_mmhub : 1;
		uint32_t vf_reg_access_gc 	 : 1;
		uint32_t reserved	         : 29;
	} flags;
	uint32_t all;
@@ -114,6 +116,37 @@ union amd_sriov_msg_os_info {
	uint32_t      all;
};

struct amd_sriov_msg_uuid_info {
	union {
		struct {
			uint32_t did	: 16;
			uint32_t fcn	: 8;
			uint32_t asic_7 : 8;
		};
		uint32_t time_low;
	};

	struct {
		uint32_t time_mid  : 16;
		uint32_t time_high : 12;
		uint32_t version   : 4;
	};

	struct {
		struct {
			uint8_t clk_seq_hi : 6;
			uint8_t variant    : 2;
		};
		union {
			uint8_t clk_seq_low;
			uint8_t asic_6;
		};
		uint16_t asic_4;
	};

	uint32_t asic_0;
};

struct amd_sriov_msg_pf2vf_info_header {
	/* the total structure size in byte */
	uint32_t size;
@@ -160,10 +193,19 @@ struct amd_sriov_msg_pf2vf_info {
	/* identification in ROCm SMI */
	uint64_t uuid;
	uint32_t fcn_idx;
	/* flags which indicate the register access method VF should use */
	/* flags to indicate which register access method VF should use */
	union amd_sriov_reg_access_flags reg_access_flags;
	/* MM BW management */
	struct {
		uint32_t decode_max_dimension_pixels;
		uint32_t decode_max_frame_pixels;
		uint32_t encode_max_dimension_pixels;
		uint32_t encode_max_frame_pixels;
	} mm_bw_management[AMD_SRIOV_MSG_RESERVE_VCN_INST];
	/* UUID info */
	struct amd_sriov_msg_uuid_info uuid_info;
	/* reserved */
	uint32_t reserved[256-27];
	uint32_t reserved[256 - 47];
};

struct amd_sriov_msg_vf2pf_info_header {
+108 −1
Original line number Diff line number Diff line
@@ -218,11 +218,114 @@ static const struct amdgpu_video_codecs sc_video_codecs_decode =
	.codec_array = sc_video_codecs_decode_array,
};

/* SRIOV Sienna Cichlid, not const since data is controlled by host */
static struct amdgpu_video_codec_info sriov_sc_video_codecs_encode_array[] =
{
	{
		.codec_type = AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC,
		.max_width = 4096,
		.max_height = 2304,
		.max_pixels_per_frame = 4096 * 2304,
		.max_level = 0,
	},
	{
		.codec_type = AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC,
		.max_width = 4096,
		.max_height = 2304,
		.max_pixels_per_frame = 4096 * 2304,
		.max_level = 0,
	},
};

static struct amdgpu_video_codec_info sriov_sc_video_codecs_decode_array[] =
{
	{
		.codec_type = AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2,
		.max_width = 4096,
		.max_height = 4096,
		.max_pixels_per_frame = 4096 * 4096,
		.max_level = 3,
	},
	{
		.codec_type = AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4,
		.max_width = 4096,
		.max_height = 4096,
		.max_pixels_per_frame = 4096 * 4096,
		.max_level = 5,
	},
	{
		.codec_type = AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC,
		.max_width = 4096,
		.max_height = 4096,
		.max_pixels_per_frame = 4096 * 4096,
		.max_level = 52,
	},
	{
		.codec_type = AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1,
		.max_width = 4096,
		.max_height = 4096,
		.max_pixels_per_frame = 4096 * 4096,
		.max_level = 4,
	},
	{
		.codec_type = AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC,
		.max_width = 8192,
		.max_height = 4352,
		.max_pixels_per_frame = 8192 * 4352,
		.max_level = 186,
	},
	{
		.codec_type = AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG,
		.max_width = 4096,
		.max_height = 4096,
		.max_pixels_per_frame = 4096 * 4096,
		.max_level = 0,
	},
	{
		.codec_type = AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9,
		.max_width = 8192,
		.max_height = 4352,
		.max_pixels_per_frame = 8192 * 4352,
		.max_level = 0,
	},
	{
		.codec_type = AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_AV1,
		.max_width = 8192,
		.max_height = 4352,
		.max_pixels_per_frame = 8192 * 4352,
		.max_level = 0,
	},
};

static struct amdgpu_video_codecs sriov_sc_video_codecs_encode =
{
	.codec_count = ARRAY_SIZE(sriov_sc_video_codecs_encode_array),
	.codec_array = sriov_sc_video_codecs_encode_array,
};

static struct amdgpu_video_codecs sriov_sc_video_codecs_decode =
{
	.codec_count = ARRAY_SIZE(sriov_sc_video_codecs_decode_array),
	.codec_array = sriov_sc_video_codecs_decode_array,
};

static int nv_query_video_codecs(struct amdgpu_device *adev, bool encode,
				 const struct amdgpu_video_codecs **codecs)
{
	switch (adev->asic_type) {
	case CHIP_SIENNA_CICHLID:
		if (amdgpu_sriov_vf(adev)) {
			if (encode)
				*codecs = &sriov_sc_video_codecs_encode;
			else
				*codecs = &sriov_sc_video_codecs_decode;
		} else {
			if (encode)
				*codecs = &nv_video_codecs_encode;
			else
				*codecs = &sc_video_codecs_decode;
		}
		return 0;
	case CHIP_NAVY_FLOUNDER:
	case CHIP_DIMGREY_CAVEFISH:
	case CHIP_VANGOGH:
@@ -1174,8 +1277,12 @@ static int nv_common_late_init(void *handle)
{
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;

	if (amdgpu_sriov_vf(adev))
	if (amdgpu_sriov_vf(adev)) {
		xgpu_nv_mailbox_get_irq(adev);
		amdgpu_virt_update_sriov_video_codec(adev,
				sriov_sc_video_codecs_encode_array, ARRAY_SIZE(sriov_sc_video_codecs_encode_array),
				sriov_sc_video_codecs_decode_array, ARRAY_SIZE(sriov_sc_video_codecs_decode_array));
	}

	return 0;
}