diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/soc15.c')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/soc15.c | 383 | 
1 files changed, 324 insertions, 59 deletions
| diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 1221aa6b40a9..d80e12b80c7e 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -25,6 +25,8 @@  #include <linux/module.h>  #include <linux/pci.h> +#include <drm/amdgpu_drm.h> +  #include "amdgpu.h"  #include "amdgpu_atombios.h"  #include "amdgpu_ih.h" @@ -71,9 +73,9 @@  #include "jpeg_v2_5.h"  #include "smuio_v9_0.h"  #include "smuio_v11_0.h" +#include "smuio_v13_0.h"  #include "dce_virtual.h"  #include "mxgpu_ai.h" -#include "amdgpu_smu.h"  #include "amdgpu_ras.h"  #include "amdgpu_xgmi.h"  #include <uapi/linux/kfd_ioctl.h> @@ -83,6 +85,234 @@  #define mmMP0_MISC_LIGHT_SLEEP_CTRL                                                             0x01ba  #define mmMP0_MISC_LIGHT_SLEEP_CTRL_BASE_IDX                                                    0 +/* Vega, Raven, Arcturus */ +static const struct amdgpu_video_codec_info vega_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 const struct amdgpu_video_codecs vega_video_codecs_encode = +{ +	.codec_count = ARRAY_SIZE(vega_video_codecs_encode_array), +	.codec_array = vega_video_codecs_encode_array, +}; + +/* Vega */ +static const struct amdgpu_video_codec_info vega_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 = 4096, +		.max_height = 4096, +		.max_pixels_per_frame = 4096 * 4096, +		.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, +	}, +}; + +static const struct amdgpu_video_codecs vega_video_codecs_decode = +{ +	.codec_count = ARRAY_SIZE(vega_video_codecs_decode_array), +	.codec_array = vega_video_codecs_decode_array, +}; + +/* Raven */ +static const struct amdgpu_video_codec_info rv_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 = 4096, +		.max_height = 4096, +		.max_pixels_per_frame = 4096 * 4096, +		.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 = 4096, +		.max_height = 4096, +		.max_pixels_per_frame = 4096 * 4096, +		.max_level = 0, +	}, +}; + +static const struct amdgpu_video_codecs rv_video_codecs_decode = +{ +	.codec_count = ARRAY_SIZE(rv_video_codecs_decode_array), +	.codec_array = rv_video_codecs_decode_array, +}; + +/* Renoir, Arcturus */ +static const struct amdgpu_video_codec_info rn_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 = 4096 * 4096, +		.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 = 4096 * 4096, +		.max_level = 0, +	}, +}; + +static const struct amdgpu_video_codecs rn_video_codecs_decode = +{ +	.codec_count = ARRAY_SIZE(rn_video_codecs_decode_array), +	.codec_array = rn_video_codecs_decode_array, +}; + +static int soc15_query_video_codecs(struct amdgpu_device *adev, bool encode, +				    const struct amdgpu_video_codecs **codecs) +{ +	switch (adev->asic_type) { +	case CHIP_VEGA20: +	case CHIP_VEGA10: +	case CHIP_VEGA12: +		if (encode) +			*codecs = &vega_video_codecs_encode; +		else +			*codecs = &vega_video_codecs_decode; +		return 0; +	case CHIP_RAVEN: +		if (encode) +			*codecs = &vega_video_codecs_encode; +		else +			*codecs = &rv_video_codecs_decode; +		return 0; +	case CHIP_ARCTURUS: +	case CHIP_RENOIR: +		if (encode) +			*codecs = &vega_video_codecs_encode; +		else +			*codecs = &rn_video_codecs_decode; +		return 0; +	default: +		return -EINVAL; +	} +} +  /*   * Indirect registers accessor   */ @@ -419,40 +649,6 @@ void soc15_program_register_sequence(struct amdgpu_device *adev,  } -static int soc15_asic_mode1_reset(struct amdgpu_device *adev) -{ -	u32 i; -	int ret = 0; - -	amdgpu_atombios_scratch_regs_engine_hung(adev, true); - -	dev_info(adev->dev, "GPU mode1 reset\n"); - -	/* disable BM */ -	pci_clear_master(adev->pdev); - -	amdgpu_device_cache_pci_state(adev->pdev); - -	ret = psp_gpu_reset(adev); -	if (ret) -		dev_err(adev->dev, "GPU mode1 reset failed\n"); - -	amdgpu_device_load_pci_state(adev->pdev); - -	/* wait for asic to come out of reset */ -	for (i = 0; i < adev->usec_timeout; i++) { -		u32 memsize = adev->nbio.funcs->get_memsize(adev); - -		if (memsize != 0xffffffff) -			break; -		udelay(1); -	} - -	amdgpu_atombios_scratch_regs_engine_hung(adev, false); - -	return ret; -} -  static int soc15_asic_baco_reset(struct amdgpu_device *adev)  {  	struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); @@ -477,13 +673,21 @@ static enum amd_reset_method  soc15_asic_reset_method(struct amdgpu_device *adev)  {  	bool baco_reset = false; +	bool connected_to_cpu = false;  	struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); +        if (adev->gmc.xgmi.supported && adev->gmc.xgmi.connected_to_cpu) +                connected_to_cpu = true; +  	if (amdgpu_reset_method == AMD_RESET_METHOD_MODE1 ||  	    amdgpu_reset_method == AMD_RESET_METHOD_MODE2 ||  	    amdgpu_reset_method == AMD_RESET_METHOD_BACO || -	    amdgpu_reset_method == AMD_RESET_METHOD_PCI) -		return amdgpu_reset_method; +	    amdgpu_reset_method == AMD_RESET_METHOD_PCI) { +		/* If connected to cpu, driver only support mode2 */ +                if (connected_to_cpu) +                        return AMD_RESET_METHOD_MODE2; +                return amdgpu_reset_method; +        }  	if (amdgpu_reset_method != -1)  		dev_warn(adev->dev, "Specified reset method:%d isn't supported, using AUTO instead.\n", @@ -509,6 +713,14 @@ soc15_asic_reset_method(struct amdgpu_device *adev)  		if ((ras && ras->supported) && adev->pm.fw_version <= 0x283400)  			baco_reset = false;  		break; +	case CHIP_ALDEBARAN: +		 /* +		 * 1.connected to cpu: driver issue mode2 reset +		 * 2.discret gpu: driver issue mode1 reset +		 */ +		if (connected_to_cpu) +			return AMD_RESET_METHOD_MODE2; +		break;  	default:  		break;  	} @@ -538,7 +750,7 @@ static int soc15_asic_reset(struct amdgpu_device *adev)  		return amdgpu_dpm_mode2_reset(adev);  	default:  		dev_info(adev->dev, "MODE1 reset\n"); -		return soc15_asic_mode1_reset(adev); +		return amdgpu_device_mode1_reset(adev);  	}  } @@ -604,11 +816,12 @@ static void soc15_pcie_gen3_enable(struct amdgpu_device *adev)  static void soc15_program_aspm(struct amdgpu_device *adev)  { - -	if (amdgpu_aspm == 0) +	if (amdgpu_aspm != 1)  		return; -	/* todo */ +	if (!(adev->flags & AMD_IS_APU) && +	    (adev->nbio.funcs->program_aspm)) +		adev->nbio.funcs->program_aspm(adev);  }  static void soc15_enable_doorbell_aperture(struct amdgpu_device *adev, @@ -661,6 +874,9 @@ static void soc15_reg_base_init(struct amdgpu_device *adev)  	case CHIP_ARCTURUS:  		arct_reg_base_init(adev);  		break; +	case CHIP_ALDEBARAN: +		aldebaran_reg_base_init(adev); +		break;  	default:  		DRM_ERROR("Unsupported asic type: %d!\n", adev->asic_type);  		break; @@ -683,14 +899,12 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)  	if (!amdgpu_sriov_vf(adev))  		soc15_reg_base_init(adev); -	if (adev->asic_type == CHIP_VEGA20 || adev->asic_type == CHIP_ARCTURUS) -		adev->gmc.xgmi.supported = true; -  	if (adev->flags & AMD_IS_APU) {  		adev->nbio.funcs = &nbio_v7_0_funcs;  		adev->nbio.hdp_flush_reg = &nbio_v7_0_hdp_flush_reg;  	} else if (adev->asic_type == CHIP_VEGA20 || -		   adev->asic_type == CHIP_ARCTURUS) { +		   adev->asic_type == CHIP_ARCTURUS || +		   adev->asic_type == CHIP_ALDEBARAN) {  		adev->nbio.funcs = &nbio_v7_4_funcs;  		adev->nbio.hdp_flush_reg = &nbio_v7_4_hdp_flush_reg;  	} else { @@ -699,7 +913,9 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)  	}  	adev->hdp.funcs = &hdp_v4_0_funcs; -	if (adev->asic_type == CHIP_VEGA20 || adev->asic_type == CHIP_ARCTURUS) +	if (adev->asic_type == CHIP_VEGA20 || +	    adev->asic_type == CHIP_ARCTURUS || +	    adev->asic_type == CHIP_ALDEBARAN)  		adev->df.funcs = &df_v3_6_funcs;  	else  		adev->df.funcs = &df_v1_7_funcs; @@ -707,6 +923,8 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)  	if (adev->asic_type == CHIP_VEGA20 ||  	    adev->asic_type == CHIP_ARCTURUS)  		adev->smuio.funcs = &smuio_v11_0_funcs; +	else if (adev->asic_type == CHIP_ALDEBARAN) +		adev->smuio.funcs = &smuio_v13_0_funcs;  	else  		adev->smuio.funcs = &smuio_v9_0_funcs; @@ -826,6 +1044,27 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)  		amdgpu_device_ip_block_add(adev, &vcn_v2_0_ip_block);  		amdgpu_device_ip_block_add(adev, &jpeg_v2_0_ip_block);  		break; +	case CHIP_ALDEBARAN: +		amdgpu_device_ip_block_add(adev, &vega10_common_ip_block); +		amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block); + +		if (amdgpu_sriov_vf(adev)) { +			if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)) +				amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block); +			amdgpu_device_ip_block_add(adev, &vega20_ih_ip_block); +		} else { +			amdgpu_device_ip_block_add(adev, &vega20_ih_ip_block); +			if (likely(adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)) +				amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block); +		} + +		amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block); +		amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block); + +		amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block); +		amdgpu_device_ip_block_add(adev, &vcn_v2_6_ip_block); +		amdgpu_device_ip_block_add(adev, &jpeg_v2_6_ip_block); +		break;  	default:  		return -EINVAL;  	} @@ -994,6 +1233,7 @@ static const struct amdgpu_asic_funcs soc15_asic_funcs =  	.get_pcie_replay_count = &soc15_get_pcie_replay_count,  	.supports_baco = &soc15_supports_baco,  	.pre_asic_init = &soc15_pre_asic_init, +	.query_video_codecs = &soc15_query_video_codecs,  };  static const struct amdgpu_asic_funcs vega20_asic_funcs = @@ -1015,6 +1255,7 @@ static const struct amdgpu_asic_funcs vega20_asic_funcs =  	.get_pcie_replay_count = &soc15_get_pcie_replay_count,  	.supports_baco = &soc15_supports_baco,  	.pre_asic_init = &soc15_pre_asic_init, +	.query_video_codecs = &soc15_query_video_codecs,  };  static int soc15_common_early_init(void *handle) @@ -1244,6 +1485,21 @@ static int soc15_common_early_init(void *handle)  				 AMD_PG_SUPPORT_JPEG |  				 AMD_PG_SUPPORT_VCN_DPG;  		break; +	case CHIP_ALDEBARAN: +		adev->asic_funcs = &vega20_asic_funcs; +		adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG | +			AMD_CG_SUPPORT_GFX_MGLS | +			AMD_CG_SUPPORT_GFX_CGCG | +			AMD_CG_SUPPORT_GFX_CGLS | +			AMD_CG_SUPPORT_GFX_CP_LS | +			AMD_CG_SUPPORT_HDP_LS | +			AMD_CG_SUPPORT_SDMA_MGCG | +			AMD_CG_SUPPORT_SDMA_LS | +			AMD_CG_SUPPORT_IH_CG | +			AMD_CG_SUPPORT_VCN_MGCG | AMD_CG_SUPPORT_JPEG_MGCG; +		adev->pg_flags = AMD_PG_SUPPORT_VCN_DPG; +		adev->external_rev_id = adev->rev_id + 0x3c; +		break;  	default:  		/* FIXME: not supported yet */  		return -EINVAL; @@ -1268,8 +1524,9 @@ static int soc15_common_late_init(void *handle)  	if (adev->hdp.funcs->reset_ras_error_count)  		adev->hdp.funcs->reset_ras_error_count(adev); -	if (adev->nbio.funcs->ras_late_init) -		r = adev->nbio.funcs->ras_late_init(adev); +	if (adev->nbio.ras_funcs && +	    adev->nbio.ras_funcs->ras_late_init) +		r = adev->nbio.ras_funcs->ras_late_init(adev);  	return r;  } @@ -1290,7 +1547,9 @@ static int soc15_common_sw_fini(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle; -	amdgpu_nbio_ras_fini(adev); +	if (adev->nbio.ras_funcs && +	    adev->nbio.ras_funcs->ras_fini) +		adev->nbio.ras_funcs->ras_fini(adev);  	adev->df.funcs->sw_fini(adev);  	return 0;  } @@ -1354,9 +1613,11 @@ static int soc15_common_hw_fini(void *handle)  	if (adev->nbio.ras_if &&  	    amdgpu_ras_is_supported(adev, adev->nbio.ras_if->block)) { -		if (adev->nbio.funcs->init_ras_controller_interrupt) +		if (adev->nbio.ras_funcs && +		    adev->nbio.ras_funcs->init_ras_controller_interrupt)  			amdgpu_irq_put(adev, &adev->nbio.ras_controller_irq, 0); -		if (adev->nbio.funcs->init_ras_err_event_athub_interrupt) +		if (adev->nbio.ras_funcs && +		    adev->nbio.ras_funcs->init_ras_err_event_athub_interrupt)  			amdgpu_irq_put(adev, &adev->nbio.ras_err_event_athub_irq, 0);  	} @@ -1477,6 +1738,7 @@ static int soc15_common_set_clockgating_state(void *handle,  				state == AMD_CG_STATE_GATE);  		break;  	case CHIP_ARCTURUS: +	case CHIP_ALDEBARAN:  		adev->hdp.funcs->update_clock_gating(adev,  				state == AMD_CG_STATE_GATE);  		break; @@ -1498,15 +1760,18 @@ static void soc15_common_get_clockgating_state(void *handle, u32 *flags)  	adev->hdp.funcs->get_clock_gating_state(adev, flags); -	/* AMD_CG_SUPPORT_DRM_MGCG */ -	data = RREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_MISC_CGTT_CTRL0)); -	if (!(data & 0x01000000)) -		*flags |= AMD_CG_SUPPORT_DRM_MGCG; +	if (adev->asic_type != CHIP_ALDEBARAN) { + +		/* AMD_CG_SUPPORT_DRM_MGCG */ +		data = RREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_MISC_CGTT_CTRL0)); +		if (!(data & 0x01000000)) +			*flags |= AMD_CG_SUPPORT_DRM_MGCG; -	/* AMD_CG_SUPPORT_DRM_LS */ -	data = RREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_MISC_LIGHT_SLEEP_CTRL)); -	if (data & 0x1) -		*flags |= AMD_CG_SUPPORT_DRM_LS; +		/* AMD_CG_SUPPORT_DRM_LS */ +		data = RREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_MISC_LIGHT_SLEEP_CTRL)); +		if (data & 0x1) +			*flags |= AMD_CG_SUPPORT_DRM_LS; +	}  	/* AMD_CG_SUPPORT_ROM_MGCG */  	adev->smuio.funcs->get_clock_gating_state(adev, flags); | 
